From a183b12c9135fd3431b67e9782e4910b0ad67088 Mon Sep 17 00:00:00 2001 From: erhant Date: Sun, 28 Jun 2026 20:35:49 +0300 Subject: [PATCH 01/21] initial commit with alternate provers (via `circomkit-ffi` repo) --- .eslintrc.json | 67 - .github/workflows/publish.yml | 34 - .github/workflows/tests.yml | 59 - .gitignore | 123 +- .vscode/extensions.json | 3 - .vscode/settings.json | 20 - Cargo.lock | 4658 +++++++++ Cargo.toml | 81 + LICENSE | 21 - README.md | 361 - circomkit.json | 12 - crates/circomkit-cli/Cargo.toml | 26 + crates/circomkit-cli/src/main.rs | 289 + crates/circomkit-core/Cargo.toml | 24 + crates/circomkit-core/src/config/circomkit.rs | 202 + crates/circomkit-core/src/config/circuit.rs | 69 + crates/circomkit-core/src/config/compiler.rs | 60 + crates/circomkit-core/src/config/legacy.rs | 245 + crates/circomkit-core/src/config/mod.rs | 13 + crates/circomkit-core/src/config/overrides.rs | 34 + crates/circomkit-core/src/config/prover.rs | 56 + crates/circomkit-core/src/config/witness.rs | 12 + crates/circomkit-core/src/enums.rs | 97 + crates/circomkit-core/src/error.rs | 52 + .../circomkit-core/src/functions/calldata.rs | 182 + .../circomkit-core/src/functions/compile.rs | 76 + .../src/functions/instantiate.rs | 114 + crates/circomkit-core/src/functions/mod.rs | 11 + .../circomkit-core/src/functions/symbols.rs | 180 + crates/circomkit-core/src/lib.rs | 7 + crates/circomkit-core/src/pathing.rs | 198 + crates/circomkit-core/src/types/circuit.rs | 160 + crates/circomkit-core/src/types/mod.rs | 7 + crates/circomkit-core/src/types/r1cs.rs | 52 + crates/circomkit-core/src/types/symbols.rs | 12 + crates/circomkit-core/src/utils/mod.rs | 11 + crates/circomkit-core/src/utils/primes.rs | 84 + crates/circomkit-core/src/utils/ptau.rs | 88 + crates/circomkit-core/src/utils/r1cs.rs | 245 + crates/circomkit-core/src/utils/witness.rs | 157 + crates/circomkit-prove/Cargo.toml | 40 + .../circomkit-prove/src/arkworks/convert.rs | 24 + crates/circomkit-prove/src/arkworks/core.rs | 68 + crates/circomkit-prove/src/arkworks/mod.rs | 97 + crates/circomkit-prove/src/capabilities.rs | 163 + crates/circomkit-prove/src/error.rs | 48 + .../src/lambdaworks/convert.rs | 55 + crates/circomkit-prove/src/lambdaworks/mod.rs | 143 + crates/circomkit-prove/src/lib.rs | 73 + crates/circomkit-prove/src/snarkjs/mod.rs | 261 + crates/circomkit-prove/src/traits.rs | 62 + crates/circomkit-prove/src/types.rs | 11 + .../tests/arkworks_integration.rs | 64 + .../circomkit-prove/tests/backend_matrix.rs | 226 + .../tests/lambdaworks_integration.rs | 73 + .../tests/snarkjs_integration.rs | 76 + crates/circomkit-test/Cargo.toml | 16 + crates/circomkit-test/src/error.rs | 43 + crates/circomkit-test/src/lib.rs | 7 + crates/circomkit-test/src/proof_tester.rs | 80 + crates/circomkit-test/src/witness_tester.rs | 176 + crates/circomkit-witness/Cargo.toml | 24 + crates/circomkit-witness/src/error.rs | 35 + crates/circomkit-witness/src/factory.rs | 34 + crates/circomkit-witness/src/lib.rs | 13 + crates/circomkit-witness/src/traits.rs | 9 + crates/circomkit-witness/src/wasm.rs | 481 + .../tests/wasm_integration.rs | 62 + crates/circomkit/Cargo.toml | 23 + crates/circomkit/src/circomkit/compile.rs | 100 + crates/circomkit/src/circomkit/mod.rs | 56 + crates/circomkit/src/circomkit/prove.rs | 215 + crates/circomkit/src/circomkit/testing.rs | 46 + crates/circomkit/src/lib.rs | 22 + .../tests/circuits/main/arrays_2_3.circom | 5 + .../tests/circuits/main/errors.circom | 3 +- .../tests/circuits/main}/multiplier_3.circom | 3 +- crates/circomkit/tests/e2e/common.rs | 51 + crates/circomkit/tests/e2e/compile.rs | 151 + crates/circomkit/tests/e2e/config.rs | 54 + crates/circomkit/tests/e2e/main.rs | 13 + crates/circomkit/tests/e2e/prove.rs | 111 + crates/circomkit/tests/e2e/witness.rs | 174 + examples/bun-sha256/.gitignore | 122 - examples/bun-sha256/.vscode/extensions.json | 3 - examples/bun-sha256/.vscode/settings.json | 3 - examples/bun-sha256/README.md | 37 - examples/bun-sha256/bun.lockb | Bin 38543 -> 0 bytes examples/bun-sha256/circomkit.json | 6 - examples/bun-sha256/circuits.json | 7 - .../bun-sha256/circuits/main/sha256_32.circom | 6 - examples/bun-sha256/circuits/sha256.circom | 42 - .../bun-sha256/inputs/sha256_32/default.json | 6 - examples/bun-sha256/package.json | 19 - examples/bun-sha256/src/index.ts | 37 - examples/bun-sha256/tests/sha256.test.ts | 54 - examples/bun-sha256/tsconfig.json | 26 - hardhat.config.ts | 8 - jest.config.js | 19 - package.json | 97 - pnpm-lock.yaml | 8374 ----------------- schema.json | 451 + src/cli.ts | 297 - src/configs/index.ts | 85 - src/core/index.ts | 536 -- src/core/pathing.ts | 87 - src/functions/calldata.ts | 122 - src/functions/circuit.ts | 82 - src/functions/index.ts | 3 - src/functions/r1cs.ts | 115 - src/functions/symbols.ts | 1 - src/index.ts | 5 - src/testers/index.ts | 2 - src/testers/proofTester.ts | 81 - src/testers/witnessTester.ts | 368 - src/types/index.ts | 68 - src/utils/index.ts | 41 - src/utils/ptau.ts | 51 - src/utils/teardown.ts | 15 - tests/circomkit.json | 46 + tests/circomkit.test.ts | 196 - tests/circuits.json | 17 - tests/circuits/custom.circom | 20 + tests/circuits/custom_templates.circom | 15 - tests/circuits/fibonacci/recursive.circom | 17 - .../fibonacci/test/fibo_vanilla.circom | 6 - tests/circuits/fibonacci/vanilla.circom | 17 - tests/circuits/main/multiplier_3.circom | 1 - tests/circuits/main/someArrays_2_3.circom | 6 - .../main/uses_custom_templates.circom | 7 - tests/circuits/multiout.circom | 24 - tests/circuits/tags.circom | 33 + tests/circuits/test/arrays.circom | 6 - tests/circuits/test/checkin.circom | 6 - tests/circuits/test/error_ct.circom | 6 - tests/circuits/test/fibo_recursive.circom | 6 - tests/circuits/test/fibo_vanilla.circom | 6 - tests/circuits/test/multiplier_10.circom | 6 - tests/circuits/test/multiplier_100.circom | 6 - tests/circuits/test/multiplier_20.circom | 6 - tests/circuits/test/multiplier_4.circom | 6 - tests/circuits/test/multiplier_50.circom | 6 - tests/common/circuits.ts | 68 - tests/common/index.ts | 4 - tests/configs.test.ts | 161 - tests/data/multiplier_30/groth16_pkey.zkey | Bin 0 -> 25165 bytes tests/data/multiplier_30/groth16_vkey.json | 94 + tests/data/multiplier_30/input.json | 3 + tests/data/multiplier_30/multiplier_30.r1cs | Bin 0 -> 4072 bytes .../multiplier_30/multiplier_30.r1cs.json | 340 + tests/data/multiplier_30/multiplier_30.sym | 118 + tests/data/multiplier_30/multiplier_30.wasm | Bin 0 -> 35985 bytes tests/data/multiplier_30/witness.wtns | Bin 0 -> 1996 bytes tests/errors.test.ts | 47 - tests/hooks/teardown.js | 6 - tests/inputs/arrays_2_3/default.json | 5 +- tests/inputs/errors/default.json | 4 + tests/proofTester.test.ts | 38 - tests/witnessTester.test.ts | 112 - tsconfig.json | 21 - tsconfig.test.json | 9 - 161 files changed, 12107 insertions(+), 12357 deletions(-) delete mode 100644 .eslintrc.json delete mode 100644 .github/workflows/publish.yml delete mode 100644 .github/workflows/tests.yml delete mode 100644 .vscode/extensions.json delete mode 100644 .vscode/settings.json create mode 100644 Cargo.lock create mode 100644 Cargo.toml delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 circomkit.json create mode 100644 crates/circomkit-cli/Cargo.toml create mode 100644 crates/circomkit-cli/src/main.rs create mode 100644 crates/circomkit-core/Cargo.toml create mode 100644 crates/circomkit-core/src/config/circomkit.rs create mode 100644 crates/circomkit-core/src/config/circuit.rs create mode 100644 crates/circomkit-core/src/config/compiler.rs create mode 100644 crates/circomkit-core/src/config/legacy.rs create mode 100644 crates/circomkit-core/src/config/mod.rs create mode 100644 crates/circomkit-core/src/config/overrides.rs create mode 100644 crates/circomkit-core/src/config/prover.rs create mode 100644 crates/circomkit-core/src/config/witness.rs create mode 100644 crates/circomkit-core/src/enums.rs create mode 100644 crates/circomkit-core/src/error.rs create mode 100644 crates/circomkit-core/src/functions/calldata.rs create mode 100644 crates/circomkit-core/src/functions/compile.rs create mode 100644 crates/circomkit-core/src/functions/instantiate.rs create mode 100644 crates/circomkit-core/src/functions/mod.rs create mode 100644 crates/circomkit-core/src/functions/symbols.rs create mode 100644 crates/circomkit-core/src/lib.rs create mode 100644 crates/circomkit-core/src/pathing.rs create mode 100644 crates/circomkit-core/src/types/circuit.rs create mode 100644 crates/circomkit-core/src/types/mod.rs create mode 100644 crates/circomkit-core/src/types/r1cs.rs create mode 100644 crates/circomkit-core/src/types/symbols.rs create mode 100644 crates/circomkit-core/src/utils/mod.rs create mode 100644 crates/circomkit-core/src/utils/primes.rs create mode 100644 crates/circomkit-core/src/utils/ptau.rs create mode 100644 crates/circomkit-core/src/utils/r1cs.rs create mode 100644 crates/circomkit-core/src/utils/witness.rs create mode 100644 crates/circomkit-prove/Cargo.toml create mode 100644 crates/circomkit-prove/src/arkworks/convert.rs create mode 100644 crates/circomkit-prove/src/arkworks/core.rs create mode 100644 crates/circomkit-prove/src/arkworks/mod.rs create mode 100644 crates/circomkit-prove/src/capabilities.rs create mode 100644 crates/circomkit-prove/src/error.rs create mode 100644 crates/circomkit-prove/src/lambdaworks/convert.rs create mode 100644 crates/circomkit-prove/src/lambdaworks/mod.rs create mode 100644 crates/circomkit-prove/src/lib.rs create mode 100644 crates/circomkit-prove/src/snarkjs/mod.rs create mode 100644 crates/circomkit-prove/src/traits.rs create mode 100644 crates/circomkit-prove/src/types.rs create mode 100644 crates/circomkit-prove/tests/arkworks_integration.rs create mode 100644 crates/circomkit-prove/tests/backend_matrix.rs create mode 100644 crates/circomkit-prove/tests/lambdaworks_integration.rs create mode 100644 crates/circomkit-prove/tests/snarkjs_integration.rs create mode 100644 crates/circomkit-test/Cargo.toml create mode 100644 crates/circomkit-test/src/error.rs create mode 100644 crates/circomkit-test/src/lib.rs create mode 100644 crates/circomkit-test/src/proof_tester.rs create mode 100644 crates/circomkit-test/src/witness_tester.rs create mode 100644 crates/circomkit-witness/Cargo.toml create mode 100644 crates/circomkit-witness/src/error.rs create mode 100644 crates/circomkit-witness/src/factory.rs create mode 100644 crates/circomkit-witness/src/lib.rs create mode 100644 crates/circomkit-witness/src/traits.rs create mode 100644 crates/circomkit-witness/src/wasm.rs create mode 100644 crates/circomkit-witness/tests/wasm_integration.rs create mode 100644 crates/circomkit/Cargo.toml create mode 100644 crates/circomkit/src/circomkit/compile.rs create mode 100644 crates/circomkit/src/circomkit/mod.rs create mode 100644 crates/circomkit/src/circomkit/prove.rs create mode 100644 crates/circomkit/src/circomkit/testing.rs create mode 100644 crates/circomkit/src/lib.rs create mode 100644 crates/circomkit/tests/circuits/main/arrays_2_3.circom rename tests/circuits/test/error_rt.circom => crates/circomkit/tests/circuits/main/errors.circom (79%) rename {tests/circuits/test => crates/circomkit/tests/circuits/main}/multiplier_3.circom (81%) create mode 100644 crates/circomkit/tests/e2e/common.rs create mode 100644 crates/circomkit/tests/e2e/compile.rs create mode 100644 crates/circomkit/tests/e2e/config.rs create mode 100644 crates/circomkit/tests/e2e/main.rs create mode 100644 crates/circomkit/tests/e2e/prove.rs create mode 100644 crates/circomkit/tests/e2e/witness.rs delete mode 100644 examples/bun-sha256/.gitignore delete mode 100644 examples/bun-sha256/.vscode/extensions.json delete mode 100644 examples/bun-sha256/.vscode/settings.json delete mode 100644 examples/bun-sha256/README.md delete mode 100755 examples/bun-sha256/bun.lockb delete mode 100644 examples/bun-sha256/circomkit.json delete mode 100644 examples/bun-sha256/circuits.json delete mode 100644 examples/bun-sha256/circuits/main/sha256_32.circom delete mode 100644 examples/bun-sha256/circuits/sha256.circom delete mode 100644 examples/bun-sha256/inputs/sha256_32/default.json delete mode 100644 examples/bun-sha256/package.json delete mode 100644 examples/bun-sha256/src/index.ts delete mode 100644 examples/bun-sha256/tests/sha256.test.ts delete mode 100644 examples/bun-sha256/tsconfig.json delete mode 100644 hardhat.config.ts delete mode 100644 jest.config.js delete mode 100644 package.json delete mode 100644 pnpm-lock.yaml create mode 100644 schema.json delete mode 100644 src/cli.ts delete mode 100644 src/configs/index.ts delete mode 100644 src/core/index.ts delete mode 100644 src/core/pathing.ts delete mode 100644 src/functions/calldata.ts delete mode 100644 src/functions/circuit.ts delete mode 100644 src/functions/index.ts delete mode 100644 src/functions/r1cs.ts delete mode 100644 src/functions/symbols.ts delete mode 100644 src/index.ts delete mode 100644 src/testers/index.ts delete mode 100644 src/testers/proofTester.ts delete mode 100644 src/testers/witnessTester.ts delete mode 100644 src/types/index.ts delete mode 100644 src/utils/index.ts delete mode 100644 src/utils/ptau.ts delete mode 100644 src/utils/teardown.ts create mode 100644 tests/circomkit.json delete mode 100644 tests/circomkit.test.ts delete mode 100644 tests/circuits.json create mode 100644 tests/circuits/custom.circom delete mode 100644 tests/circuits/custom_templates.circom delete mode 100644 tests/circuits/fibonacci/recursive.circom delete mode 100644 tests/circuits/fibonacci/test/fibo_vanilla.circom delete mode 100644 tests/circuits/fibonacci/vanilla.circom delete mode 100644 tests/circuits/main/someArrays_2_3.circom delete mode 100644 tests/circuits/main/uses_custom_templates.circom delete mode 100644 tests/circuits/multiout.circom create mode 100644 tests/circuits/tags.circom delete mode 100644 tests/circuits/test/arrays.circom delete mode 100644 tests/circuits/test/checkin.circom delete mode 100644 tests/circuits/test/error_ct.circom delete mode 100644 tests/circuits/test/fibo_recursive.circom delete mode 100644 tests/circuits/test/fibo_vanilla.circom delete mode 100644 tests/circuits/test/multiplier_10.circom delete mode 100644 tests/circuits/test/multiplier_100.circom delete mode 100644 tests/circuits/test/multiplier_20.circom delete mode 100644 tests/circuits/test/multiplier_4.circom delete mode 100644 tests/circuits/test/multiplier_50.circom delete mode 100644 tests/common/circuits.ts delete mode 100644 tests/common/index.ts delete mode 100644 tests/configs.test.ts create mode 100644 tests/data/multiplier_30/groth16_pkey.zkey create mode 100644 tests/data/multiplier_30/groth16_vkey.json create mode 100644 tests/data/multiplier_30/input.json create mode 100644 tests/data/multiplier_30/multiplier_30.r1cs create mode 100644 tests/data/multiplier_30/multiplier_30.r1cs.json create mode 100644 tests/data/multiplier_30/multiplier_30.sym create mode 100644 tests/data/multiplier_30/multiplier_30.wasm create mode 100644 tests/data/multiplier_30/witness.wtns delete mode 100644 tests/errors.test.ts delete mode 100644 tests/hooks/teardown.js create mode 100644 tests/inputs/errors/default.json delete mode 100644 tests/proofTester.test.ts delete mode 100644 tests/witnessTester.test.ts delete mode 100644 tsconfig.json delete mode 100644 tsconfig.test.json diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 875f9eb..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "extends": ["eslint:recommended", "plugin:node/recommended", "prettier"], - "plugins": ["node", "prettier"], - "rules": { - "prettier/prettier": "error", - "block-scoped-var": "error", - "eqeqeq": "error", - "no-var": "error", - "prefer-const": "error", - "eol-last": "error", - "prefer-arrow-callback": "error", - "no-trailing-spaces": "error", - "quotes": ["warn", "single", {"avoidEscape": true}], - "no-restricted-properties": [ - "error", - { - "object": "describe", - "property": "only" - }, - { - "object": "it", - "property": "only" - } - ] - }, - "ignorePatterns": [ - "build", - "node_modules", - "ptau", - "circuits", - "inputs", - "dist", - ".vscode", - ".github", - "jest.config.js", - "examples" - ], - "overrides": [ - { - "files": ["**/*.ts", "**/*.tsx"], - "parser": "@typescript-eslint/parser", - "extends": ["plugin:@typescript-eslint/recommended"], - "rules": { - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-warning-comments": "off", - "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/camelcase": "off", - "node/no-missing-import": "off", - "node/no-empty-function": "off", - "node/no-unsupported-features/es-syntax": "off", - "node/no-missing-require": "off", - "node/shebang": "off", - "no-dupe-class-members": "off", - "require-atomic-updates": "off" - } - } - ], - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - } -} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 49b8ff4..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: npm - -on: - release: - types: [published] - -jobs: - publish: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --no-frozen-lockfile - - - name: Build package - run: pnpm build - - - uses: JS-DevTools/npm-publish@v3 - id: publish - with: - token: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index eaa2d0c..0000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: tests - -on: - push: - branches: - - main - paths: - # Source files - - 'src/**' - - 'tests/**' - # Configurations - - 'circomkit.json' - - 'hardhat.config.ts' - - 'jest.config.js' - # workflow itself - - '.github/workflows/tests.yml' - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install --yes \ - build-essential \ - libgmp-dev \ - libsodium-dev \ - nasm \ - nlohmann-json3-dev - - - name: Download Circom Binary v2.1.5 - run: | - wget -qO /home/runner/work/circom https://github.com/iden3/circom/releases/download/v2.1.5/circom-linux-amd64 - chmod +x /home/runner/work/circom - sudo mv /home/runner/work/circom /bin/circom - - - name: Print Circom version - run: circom --version - - - name: Install pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - - - name: Use Node.js 20 - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --no-frozen-lockfile - - - name: Run tests - run: pnpm test diff --git a/.gitignore b/.gitignore index 3f8c3b4..7da90dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,118 +1,9 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* +/target -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json +# Editor config +/.vscode/ -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and *not* Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# builds -build -dist - -# is this still a thing lol -.DS_Store - -# Hardhat files -/cache -/artifacts - -# test inputs -input.test.json +# Generated test artifacts +/tests/build/ +/tests/circuits/main/ +/tests/ptau/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index dd0e89c..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["iden3.circom", "firsttris.vscode-jest-runner"] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 69a0202..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - // https://raw.githubusercontent.com/PKief/vscode-material-icon-theme/main/images/folderIcons.png - "material-icon-theme.folders.associations": { - "circuits": "Stack", - "main": "Controller", - "inputs": "Json", - "ptau": "Secure", - "zkey": "Functions", - "ejs": "JavaScript", - "testers": "Test" - }, - // https://raw.githubusercontent.com/PKief/vscode-material-icon-theme/main/images/fileIcons.png - "material-icon-theme.files.associations": { - "*.circom": "Verilog", - "*.wtns": "Authors", - "*.zkey": "Lock", - "*.r1cs": "Diff", - "*.sym": "Edge" - } -} diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..3029d5d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4658 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli 0.31.1", +] + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli 0.32.3", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ar_archive_writer" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" +dependencies = [ + "object 0.37.3", +] + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "ark-bn254" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bc66f96ebe2a17a499475b4f94791d379817592ef494171586967ffdc6f95db" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-circom" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7289925883497fad86462c39a34e836baefe372b081381215258887f82736a" +dependencies = [ + "ark-bn254", + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-groth16", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-std", + "byteorder", + "cfg-if", + "color-eyre", + "fnv", + "hex", + "num", + "num-bigint", + "num-traits", + "rayon", + "serde", + "serde_json", + "thiserror 2.0.18", + "wasmer", +] + +[[package]] +name = "ark-crypto-primitives" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b3409b1846fe459d19c95df039481575ac6d5842ae63858ad75cc31219bfc1" +dependencies = [ + "ahash", + "ark-crypto-primitives-macros", + "ark-ec", + "ark-ff", + "ark-r1cs-std", + "ark-relations", + "ark-serialize", + "ark-snark", + "ark-std", + "blake2", + "blake3", + "derivative", + "digest", + "fnv", + "merlin", + "num-bigint", + "rayon", + "sha2", +] + +[[package]] +name = "ark-crypto-primitives-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8352a2b2aedf6ba2cc38f7520fc51191d518dde96175c729af19f2d059f191c4" +dependencies = [ + "ahash", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.17.1", + "itertools 0.14.0", + "num-bigint", + "num-integer", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7a806ac6c8307b929df4645776290a50ee2aac754ad09d8bdf73391309e43af" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "digest", + "educe", + "num-bigint", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1479009684adc073dff49a1025d3a7065b317a9ead25aaaca38cdc70058ba8a2" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ff-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0691ed21ef00ef89c1e9bda832eba493dda3ec2f8d892fb25b705f73f06bb8" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-groth16" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a293328aa422e65527e285614ce5d1dceb0bd7b8b18d18b1b63191ee1f74cb41" +dependencies = [ + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-snark", + "ark-std", + "rayon", +] + +[[package]] +name = "ark-poly" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f55af10b672002b8d953e230282c51206842e20e5791a94432219b4201de5c" +dependencies = [ + "ahash", + "ark-ff", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.17.1", + "rayon", +] + +[[package]] +name = "ark-r1cs-std" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291f1c6628bfcac79b0dc2adbe401aa9100e2e96daa971645e0b18fc94de9a98" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-relations", + "ark-std", + "educe", + "itertools 0.14.0", + "num-bigint", + "num-integer", + "num-traits", + "tracing", +] + +[[package]] +name = "ark-relations" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4c11c797a64b8a23e22bf4e77bf582ac27bb21395e3183a9a506ba2561e9f9" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "foldhash", + "indexmap 2.13.1", + "rayon", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "ark-serialize" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a74dd304fd536fb95d0a328e72be759209cc496a9da094c5bc56e5fea4f9e86b" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest", + "num-bigint", + "rayon", + "serde_with", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f153690697a2b91e5e1251ff98411ee5371500a111a0fd317a70e588eb300f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-snark" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bdb461d2be9b2bd6f303c79fffc89f5858790a7b4d33257bca3178e2c071fb9" +dependencies = [ + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-std" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367c9c827ed431bff6868b7aa926e05b16eb46603cc8b6e768e4a5553fa1d155" +dependencies = [ + "num-traits", + "rand", + "rayon", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f02882884d3e1bc524fb12c79f107f6ad0e1cfd498c536ffb494301740995dfe" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line 0.25.1", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.37.3", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags 2.11.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.117", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "blake3" +version = "1.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.0", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive 0.6.12", + "ptr_meta 0.1.4", + "simdutf8", +] + +[[package]] +name = "bytecheck" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0caa33a2c0edca0419d15ac723dff03f1956f7978329b1e3b5fdaaaed9d3ca8b" +dependencies = [ + "bytecheck_derive 0.8.2", + "ptr_meta 0.3.1", + "rancor", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bytecheck_derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" + +[[package]] +name = "cc" +version = "1.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "circomkit" +version = "0.1.0" +dependencies = [ + "circomkit-core", + "circomkit-prove", + "circomkit-test", + "circomkit-witness", + "log", + "num-bigint", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "circomkit-cli" +version = "0.1.0" +dependencies = [ + "anyhow", + "circomkit", + "clap", + "env_logger", + "log", + "regex", + "serde_json", +] + +[[package]] +name = "circomkit-core" +version = "0.1.0" +dependencies = [ + "log", + "num-bigint", + "num-traits", + "schemars 0.8.22", + "serde", + "serde_json", + "thiserror 2.0.18", + "ureq", +] + +[[package]] +name = "circomkit-prove" +version = "0.1.0" +dependencies = [ + "ark-bn254", + "ark-circom", + "ark-ec", + "ark-ff", + "ark-groth16", + "ark-relations", + "ark-serialize", + "ark-std", + "circomkit-core", + "lambdaworks-circom-adapter", + "lambdaworks-groth16", + "lambdaworks-math", + "log", + "num-bigint", + "rand", + "serde", + "serde_json", + "tempfile", + "thiserror 2.0.18", +] + +[[package]] +name = "circomkit-test" +version = "0.1.0" +dependencies = [ + "circomkit-core", + "circomkit-prove", + "circomkit-witness", + "log", + "num-bigint", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "circomkit-witness" +version = "0.1.0" +dependencies = [ + "circomkit-core", + "log", + "num-bigint", + "num-traits", + "serde_json", + "thiserror 2.0.18", + "wasmtime", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] + +[[package]] +name = "color-eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "corosensei" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6886a0c0f263965933c438626e7179139a62b978a33aa18281cbf0cd5a975f34" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "scopeguard", + "windows-sys 0.59.0", +] + +[[package]] +name = "cpp_demangle" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-assembler-x64" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4b56ebe316895d3fa37775d0a87b0c889cc933f5c8b253dbcc7c7bcb7fe7e4" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95cabbc01dfbd7dcd6c329ca44f0212910309c221797ac736a67a5bc8857fe1b" + +[[package]] +name = "cranelift-bforest" +version = "0.110.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "305d51c180ebdc46ef61bc60c54ae6512db3bc9a05842a1f1e762e45977019ab" +dependencies = [ + "cranelift-entity 0.110.2", +] + +[[package]] +name = "cranelift-bforest" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ffe46df300a45f1dc6f609dc808ce963f0e3a2e971682c479a2d13e3b9b8ef" +dependencies = [ + "cranelift-entity 0.118.0", +] + +[[package]] +name = "cranelift-bitset" +version = "0.110.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "690d8ae6c73748e5ce3d8fe59034dceadb8823e6c8994ba324141c5eae909b0e" + +[[package]] +name = "cranelift-bitset" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b265bed7c51e1921fdae6419791d31af77d33662ee56d7b0fa0704dc8d231cab" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "cranelift-codegen" +version = "0.110.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7ca95e831c18d1356da783765c344207cbdffea91e13e47fa9327dbb2e0719" +dependencies = [ + "bumpalo", + "cranelift-bforest 0.110.2", + "cranelift-bitset 0.110.3", + "cranelift-codegen-meta 0.110.3", + "cranelift-codegen-shared 0.110.3", + "cranelift-control 0.110.3", + "cranelift-entity 0.110.2", + "cranelift-isle 0.110.2", + "gimli 0.28.1", + "hashbrown 0.14.5", + "log", + "regalloc2 0.9.3", + "rustc-hash 1.1.0", + "smallvec", + "target-lexicon 0.12.16", +] + +[[package]] +name = "cranelift-codegen" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e606230a7e3a6897d603761baee0d19f88d077f17b996bb5089488a29ae96e41" +dependencies = [ + "bumpalo", + "cranelift-assembler-x64", + "cranelift-bforest 0.118.0", + "cranelift-bitset 0.118.0", + "cranelift-codegen-meta 0.118.0", + "cranelift-codegen-shared 0.118.0", + "cranelift-control 0.118.0", + "cranelift-entity 0.118.0", + "cranelift-isle 0.118.0", + "gimli 0.31.1", + "hashbrown 0.15.5", + "log", + "pulley-interpreter", + "regalloc2 0.11.2", + "rustc-hash 2.1.2", + "serde", + "smallvec", + "target-lexicon 0.13.5", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.110.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0a2d2ab65e6cbf91f81781d8da65ec2005510f18300eff21a99526ed6785863" +dependencies = [ + "cranelift-codegen-shared 0.110.3", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a63bffafc23bc60969ad528e138788495999d935f0adcfd6543cb151ca8637d" +dependencies = [ + "cranelift-assembler-x64", + "cranelift-codegen-shared 0.118.0", + "pulley-interpreter", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.110.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efcff860573cf3db9ae98fbd949240d78b319df686cc306872e7fab60e9c84d7" + +[[package]] +name = "cranelift-codegen-shared" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af50281b67324b58e843170a6a5943cf6d387c06f7eeacc9f5696e4ab7ae7d7e" + +[[package]] +name = "cranelift-control" +version = "0.110.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d70e5b75c2d5541ef80a99966ccd97aaa54d2a6af19ea31759a28538e1685a" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-control" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c20c1b38d1abfbcebb0032e497e71156c0e3b8dcb3f0a92b9863b7bcaec290c" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.110.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a48cb0a194c9ba82fec35a1e492055388d89b2e3c03dee9dcf2488892be8004d" +dependencies = [ + "cranelift-bitset 0.110.3", +] + +[[package]] +name = "cranelift-entity" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2c67d95507c51b4a1ff3f3555fe4bfec36b9e13c1b684ccc602736f5d5f4a2" +dependencies = [ + "cranelift-bitset 0.118.0", + "serde", + "serde_derive", +] + +[[package]] +name = "cranelift-frontend" +version = "0.110.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8327afc6c1c05f4be62fefce5b439fa83521c65363a322e86ea32c85e7ceaf64" +dependencies = [ + "cranelift-codegen 0.110.2", + "log", + "smallvec", + "target-lexicon 0.12.16", +] + +[[package]] +name = "cranelift-frontend" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e002691cc69c38b54fc7ec93e5be5b744f627d027031d991cc845d1d512d0ce" +dependencies = [ + "cranelift-codegen 0.118.0", + "log", + "smallvec", + "target-lexicon 0.13.5", +] + +[[package]] +name = "cranelift-isle" +version = "0.110.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b08621c00321efcfa3eee6a3179adc009e21ea8d24ca7adc3c326184bc3f48" + +[[package]] +name = "cranelift-isle" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93588ed1796cbcb0e2ad160403509e2c5d330d80dd6e0014ac6774c7ebac496" + +[[package]] +name = "cranelift-native" +version = "0.118.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5b09bdd6407bf5d89661b80cf926ce731c9e8cc184bf49102267a2369a8358e" +dependencies = [ + "cranelift-codegen 0.118.0", + "libc", + "target-lexicon 0.13.5", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dashmap" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "serde_core", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-iterator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "enumset" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "839c4174b41e75c8f7306110b2c51996a293b8d1d850edd529011841d9fede7d" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd536557b58c682b217b8fb199afdff47cd3eff260623f19e77074eb073d63a" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "env_filter" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fastrand" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f" + +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "fxprof-processed-profile" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" +dependencies = [ + "bitflags 2.11.0", + "debugid", + "fxhash", + "serde", + "serde_json", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "fallible-iterator", + "indexmap 2.13.1", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +dependencies = [ + "fallible-iterator", + "indexmap 2.13.1", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "ittapi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] + +[[package]] +name = "jiff" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures 0.2.17", +] + +[[package]] +name = "lambdaworks-circom-adapter" +version = "0.11.0" +source = "git+https://github.com/erhant/lambdaworks?branch=erhant%2Ffix-circom-adapter#14f46222a52943dbb98fca8a9713e05718419dcf" +dependencies = [ + "lambdaworks-groth16", + "lambdaworks-math", + "serde", + "serde_json", +] + +[[package]] +name = "lambdaworks-crypto" +version = "0.11.0" +source = "git+https://github.com/erhant/lambdaworks?branch=erhant%2Ffix-circom-adapter#14f46222a52943dbb98fca8a9713e05718419dcf" +dependencies = [ + "lambdaworks-math", + "sha2", + "sha3", +] + +[[package]] +name = "lambdaworks-groth16" +version = "0.11.0" +source = "git+https://github.com/erhant/lambdaworks?branch=erhant%2Ffix-circom-adapter#14f46222a52943dbb98fca8a9713e05718419dcf" +dependencies = [ + "lambdaworks-crypto", + "lambdaworks-math", + "rand", + "rand_chacha", + "serde", + "serde_json", +] + +[[package]] +name = "lambdaworks-math" +version = "0.11.0" +source = "git+https://github.com/erhant/lambdaworks?branch=erhant%2Ffix-circom-adapter#14f46222a52943dbb98fca8a9713e05718419dcf" +dependencies = [ + "rayon", + "serde", + "serde_json", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83bff1d572d6b9aeef67ddfc8448e4a3737909cb28e81f97c791b9018703e52" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +dependencies = [ + "libc", +] + +[[package]] +name = "libunwind" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6639b70a7ce854b79c70d7e83f16b5dc0137cc914f3d7d03803b513ecc67ac" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "mach2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + +[[package]] +name = "macho-unwind-info" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4bdc8b0ce69932332cf76d24af69c3a155242af95c226b2ab6c2e371ed1149" +dependencies = [ + "thiserror 2.0.18", + "zerocopy", + "zerocopy-derive", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memfd" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" +dependencies = [ + "rustix 1.1.4", +] + +[[package]] +name = "memmap2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "more-asserts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" + +[[package]] +name = "munge" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "rand", + "serde", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "crc32fast", + "flate2", + "hashbrown 0.14.5", + "indexmap 2.13.1", + "memchr", + "ruzstd", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "crc32fast", + "hashbrown 0.15.5", + "indexmap 2.13.1", + "memchr", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3852766467df634d74f0b2d7819bf8dc483a0eb2e3b0f50f756f9cfe8b0d18d8" +dependencies = [ + "ar_archive_writer", + "cc", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive 0.1.4", +] + +[[package]] +name = "ptr_meta" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" +dependencies = [ + "ptr_meta_derive 0.3.1", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pulley-interpreter" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3325791708ad50580aeacfcce06cb5e462c9ba7a2368e109cb2012b944b70e" +dependencies = [ + "cranelift-bitset 0.118.0", + "log", + "wasmtime-math", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rancor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee" +dependencies = [ + "ptr_meta 0.3.1", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "regalloc2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +dependencies = [ + "hashbrown 0.13.2", + "log", + "rustc-hash 1.1.0", + "slice-group-by", + "smallvec", +] + +[[package]] +name = "regalloc2" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc06e6b318142614e4a48bc725abbf08ff166694835c43c9dae5a9009704639a" +dependencies = [ + "allocator-api2", + "bumpalo", + "hashbrown 0.15.5", + "log", + "rustc-hash 2.1.2", + "smallvec", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "region" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach2", + "windows-sys 0.52.0", +] + +[[package]] +name = "rend" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6" +dependencies = [ + "bytecheck 0.8.2", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rkyv" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73389e0c99e664f919275ab5b5b0471391fe9a8de61e1dff9b1eaf56a90f16e3" +dependencies = [ + "bytecheck 0.8.2", + "bytes", + "hashbrown 0.17.1", + "indexmap 2.13.1", + "munge", + "ptr_meta 0.3.1", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2ed0b54125315fb36bd021e82d314d1c126548f871634b483f46b31d13cac6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ruzstd" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +dependencies = [ + "byteorder", + "derive_more 0.99.20", + "twox-hash", +] + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.117", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "self_cell" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_with" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" +dependencies = [ + "base64 0.22.1", + "bs58", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.13.1", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "time", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shared-buffer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" +dependencies = [ + "bytes", + "memmap2", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tar" +version = "0.4.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c17d80feb7334b40c484e45ed1a5273dfd8bfda537c3be2e74a06a6686f327" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcef1a61bdb119096e153208ec5cbec23944ce8bca13be5c7f60c634f7403935" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap 2.13.1", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trait-variant" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "url", + "webpki-roots 0.26.11", +] + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.226.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d81b727619aec227dce83e7f7420d4e56c79acd044642a356ea045b98d4e13" +dependencies = [ + "leb128fmt", + "wasmparser 0.226.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.246.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61fb705ce81adde29d2a8e99d87995e39a6e927358c91398f374474746070ef7" +dependencies = [ + "leb128fmt", + "wasmparser 0.246.2", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.1", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasmer" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d85671948f8886a1cc946141c0b688a5617603c103699a5fceeebeb4e75b0b6" +dependencies = [ + "bindgen", + "bytes", + "cfg-if", + "cmake", + "derive_more 2.1.1", + "indexmap 2.13.1", + "js-sys", + "more-asserts", + "paste", + "rustc-demangle", + "serde", + "serde-wasm-bindgen", + "shared-buffer", + "tar", + "target-lexicon 0.12.16", + "thiserror 1.0.69", + "tracing", + "wasm-bindgen", + "wasmer-compiler", + "wasmer-compiler-cranelift", + "wasmer-derive", + "wasmer-types", + "wasmer-vm", + "wasmparser 0.224.1", + "wat", + "windows-sys 0.59.0", +] + +[[package]] +name = "wasmer-compiler" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4946475adc0af265af8f10aadf4d4a3c64845bcd3801c655bdd81ce5e3ee869b" +dependencies = [ + "backtrace", + "bytes", + "cfg-if", + "enum-iterator", + "enumset", + "leb128", + "libc", + "macho-unwind-info", + "memmap2", + "more-asserts", + "object 0.32.2", + "region", + "rkyv", + "self_cell", + "shared-buffer", + "smallvec", + "target-lexicon 0.12.16", + "thiserror 1.0.69", + "wasmer-types", + "wasmer-vm", + "wasmparser 0.224.1", + "windows-sys 0.59.0", + "xxhash-rust", +] + +[[package]] +name = "wasmer-compiler-cranelift" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780f9c2050941b4e3f6bb82d32bd796a6c1750d2f97cbd892f07b384bb6af6f8" +dependencies = [ + "cranelift-codegen 0.110.2", + "cranelift-entity 0.110.2", + "cranelift-frontend 0.110.2", + "gimli 0.28.1", + "itertools 0.12.1", + "more-asserts", + "rayon", + "smallvec", + "target-lexicon 0.12.16", + "tracing", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-derive" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546f3380840cd63fdcc390f04cd19002f2dfa19b4691b77ecbd27642bd93452" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wasmer-types" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a4027ce165e8dc776dc5e2a3231a96983e6dc7330efd97b793cfc4e973ad0c" +dependencies = [ + "bytecheck 0.6.12", + "enum-iterator", + "enumset", + "getrandom 0.2.17", + "hex", + "indexmap 2.13.1", + "more-asserts", + "rkyv", + "sha2", + "target-lexicon 0.12.16", + "thiserror 1.0.69", + "xxhash-rust", +] + +[[package]] +name = "wasmer-vm" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c37d5be291eea00a00d077ce3a427bb3074709ee386ec358f18f0b7da33be01" +dependencies = [ + "backtrace", + "cc", + "cfg-if", + "corosensei", + "crossbeam-queue", + "dashmap", + "enum-iterator", + "fnv", + "indexmap 2.13.1", + "libc", + "libunwind", + "mach2", + "memoffset", + "more-asserts", + "region", + "rustversion", + "scopeguard", + "thiserror 1.0.69", + "wasmer-types", + "windows-sys 0.59.0", +] + +[[package]] +name = "wasmparser" +version = "0.224.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f17a5917c2ddd3819e84c661fae0d6ba29d7b9c1f0e96c708c65a9c4188e11" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "wasmparser" +version = "0.226.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc28600dcb2ba68d7e5f1c3ba4195c2bddc918c0243fd702d0b6dbd05689b681" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.1", + "semver", + "serde", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.1", + "semver", +] + +[[package]] +name = "wasmparser" +version = "0.246.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71cde4757396defafd25417cfb36aa3161027d06d865b0c24baaae229aac005d" +dependencies = [ + "bitflags 2.11.0", + "indexmap 2.13.1", + "semver", +] + +[[package]] +name = "wasmprinter" +version = "0.226.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "753a0516fa6c01756ee861f36878dfd9875f273aea9409d9ea390a333c5bcdc2" +dependencies = [ + "anyhow", + "termcolor", + "wasmparser 0.226.0", +] + +[[package]] +name = "wasmtime" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fe78033c72da8741e724d763daf1375c93a38bfcea99c873ee4415f6098c3f" +dependencies = [ + "addr2line 0.24.2", + "anyhow", + "async-trait", + "bitflags 2.11.0", + "bumpalo", + "cc", + "cfg-if", + "encoding_rs", + "fxprof-processed-profile", + "gimli 0.31.1", + "hashbrown 0.15.5", + "indexmap 2.13.1", + "ittapi", + "libc", + "log", + "mach2", + "memfd", + "object 0.36.7", + "once_cell", + "paste", + "postcard", + "psm", + "pulley-interpreter", + "rayon", + "rustix 0.38.44", + "semver", + "serde", + "serde_derive", + "serde_json", + "smallvec", + "sptr", + "target-lexicon 0.13.5", + "trait-variant", + "wasm-encoder 0.226.0", + "wasmparser 0.226.0", + "wasmtime-asm-macros", + "wasmtime-cache", + "wasmtime-component-macro", + "wasmtime-component-util", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-math", + "wasmtime-slab", + "wasmtime-versioned-export-macros", + "wasmtime-winch", + "wat", + "windows-sys 0.59.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47f3d44ae977d70ccf80938b371d5ec60b6adedf60800b9e8dd1223bb69f4cbc" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-cache" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e209505770c7f38725513dba37246265fa6f724c30969de1e9d2a9e6c8f55099" +dependencies = [ + "anyhow", + "base64 0.21.7", + "directories-next", + "log", + "postcard", + "rustix 0.38.44", + "serde", + "serde_derive", + "sha2", + "toml", + "windows-sys 0.59.0", + "zstd", +] + +[[package]] +name = "wasmtime-component-macro" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397e68ee29eb072d8d8741c9d2c971a284cd1bc960ebf2c1f6a33ea6ba16d6e1" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasmtime-component-util", + "wasmtime-wit-bindgen", + "wit-parser 0.226.0", +] + +[[package]] +name = "wasmtime-component-util" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f292ef5eb2cf3d414c2bde59c7fa0feeba799c8db9a8c5a656ad1d1a1d05e10b" + +[[package]] +name = "wasmtime-cranelift" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52fc12eb8ea695a30007a4849a5fd56209dd86a15579e92e0c27c27122818505" +dependencies = [ + "anyhow", + "cfg-if", + "cranelift-codegen 0.118.0", + "cranelift-control 0.118.0", + "cranelift-entity 0.118.0", + "cranelift-frontend 0.118.0", + "cranelift-native", + "gimli 0.31.1", + "itertools 0.12.1", + "log", + "object 0.36.7", + "pulley-interpreter", + "smallvec", + "target-lexicon 0.13.5", + "thiserror 1.0.69", + "wasmparser 0.226.0", + "wasmtime-environ", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-environ" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b6b4bf08e371edf262cccb62de10e214bd4aaafaa069f1cd49c9c1c3a5ae8e4" +dependencies = [ + "anyhow", + "cpp_demangle", + "cranelift-bitset 0.118.0", + "cranelift-entity 0.118.0", + "gimli 0.31.1", + "indexmap 2.13.1", + "log", + "object 0.36.7", + "postcard", + "rustc-demangle", + "semver", + "serde", + "serde_derive", + "smallvec", + "target-lexicon 0.13.5", + "wasm-encoder 0.226.0", + "wasmparser 0.226.0", + "wasmprinter", + "wasmtime-component-util", +] + +[[package]] +name = "wasmtime-fiber" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8828d7d8fbe90d087a9edea9223315caf7eb434848896667e5d27889f1173" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "rustix 0.38.44", + "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", + "windows-sys 0.59.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9eff86dedd48b023199de2d266f5d3e37bc7c5bafdc1e3e3057214649ecf5a" +dependencies = [ + "cc", + "object 0.36.7", + "rustix 0.38.44", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a54f6c6c7e9d7eeee32dfcc10db7f29d505ee7dd28d00593ea241d5f70698e64" +dependencies = [ + "anyhow", + "cfg-if", + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "wasmtime-math" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1108aad2e6965698f9207ea79b80eda2b3dcc57dcb69f4258296d4664ae32cd" +dependencies = [ + "libm", +] + +[[package]] +name = "wasmtime-slab" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d6a321317281b721c5530ef733e8596ecc6065035f286ccd155b3fa8e0ab2f" + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5732a5c86efce7bca121a61d8c07875f6b85c1607aa86753b40f7f8bd9d3a780" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "wasmtime-winch" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aa4741ee66a52e2f0ec5f79040017123ba47d2dff9d994b35879cc2b7f468d4" +dependencies = [ + "anyhow", + "cranelift-codegen 0.118.0", + "gimli 0.31.1", + "object 0.36.7", + "target-lexicon 0.13.5", + "wasmparser 0.226.0", + "wasmtime-cranelift", + "wasmtime-environ", + "winch-codegen", +] + +[[package]] +name = "wasmtime-wit-bindgen" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505c13fa0cac6c43e805347acf1e916c8de54e3790f2c22873c5692964b09b62" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.13.1", + "wit-parser 0.226.0", +] + +[[package]] +name = "wast" +version = "246.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe3fe8e3bf88ad96d031b4181ddbd64634b17cb0d06dfc3de589ef43591a9a62" +dependencies = [ + "bumpalo", + "leb128fmt", + "memchr", + "unicode-width", + "wasm-encoder 0.246.2", +] + +[[package]] +name = "wat" +version = "1.246.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd7fda1199b94fff395c2d19a153f05dbe7807630316fa9673367666fd2ad8c" +dependencies = [ + "wast", +] + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.6", +] + +[[package]] +name = "webpki-roots" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winch-codegen" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f05457f74ec3c94d5c5caac06b84fd8d9d4d7fa21419189845ed245a53477" +dependencies = [ + "anyhow", + "cranelift-codegen 0.118.0", + "gimli 0.31.1", + "regalloc2 0.11.2", + "smallvec", + "target-lexicon 0.13.5", + "thiserror 1.0.69", + "wasmparser 0.226.0", + "wasmtime-cranelift", + "wasmtime-environ", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser 0.244.0", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.13.1", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap 2.13.1", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.244.0", + "wasm-metadata", + "wasmparser 0.244.0", + "wit-parser 0.244.0", +] + +[[package]] +name = "wit-parser" +version = "0.226.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33f007722bfd43a2978c5b8b90f02c927dddf0f11c5f5b50929816b3358718cd" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.1", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.226.0", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.1", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.244.0", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix 1.1.4", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0c168bc --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,81 @@ +[workspace] +resolver = "3" +members = [ + "crates/circomkit-core", + "crates/circomkit-witness", + "crates/circomkit-prove", + "crates/circomkit-test", + "crates/circomkit", + "crates/circomkit-cli", +] + +[workspace.package] +version = "0.1.0" +edition = "2024" +license = "MIT" +repository = "https://github.com/erhant/circomkit" +authors = ["Erhan Tezcan"] + +[workspace.dependencies] +# Internal crates +circomkit-core = { path = "crates/circomkit-core" } +circomkit-witness = { path = "crates/circomkit-witness" } +circomkit-prove = { path = "crates/circomkit-prove" } +circomkit-test = { path = "crates/circomkit-test" } +circomkit = { path = "crates/circomkit" } + +# Serialization +serde = { version = "1", features = ["derive"] } +serde_json = "1" +schemars = "0.8" + +# Numeric +num-bigint = { version = "0.4", features = ["serde"] } +num-traits = "0.2" + +# Error handling +thiserror = "2" +anyhow = "1" + +# Logging +log = "0.4" +env_logger = "0.11" + +# CLI +clap = { version = "4", features = ["derive"] } + +# HTTP (PTAU download) +ureq = "2" + +# Temp files +tempfile = "3" + +# Regex +regex = "1" + +# WASM runtime (witness calculation) +wasmtime = "31" + +# Lambdaworks (proving) +lambdaworks-math = { git = "https://github.com/erhant/lambdaworks", branch = "erhant/fix-circom-adapter" } +lambdaworks-circom-adapter = { git = "https://github.com/erhant/lambdaworks", branch = "erhant/fix-circom-adapter" } +lambdaworks-groth16 = { git = "https://github.com/erhant/lambdaworks", branch = "erhant/fix-circom-adapter" } + +# Arkworks (proving) +ark-circom = { version = "0.6", default-features = false } +ark-bn254 = "0.6" +ark-groth16 = { version = "0.6", default-features = false, features = [ + "parallel", +] } +ark-ff = { version = "0.6", default-features = false, features = [ + "parallel", + "asm", +] } +ark-ec = { version = "0.6", default-features = false, features = ["parallel"] } +ark-relations = { version = "0.6", default-features = false } +ark-serialize = { version = "0.6", default-features = false } +ark-std = { version = "0.6", default-features = false, features = [ + "parallel", + "std", +] } +rand = "0.8" diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 4d2d5fb..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Erhan Tezcan - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 7db1487..0000000 --- a/README.md +++ /dev/null @@ -1,361 +0,0 @@ -

-

- Circomkit -

-

A simple-to-use & opinionated circuit development & testing toolkit.

-

- -

- - NPM - - - Workflow: Tests - - - - -

- -- [x] Simple CLI, abstracting away all paths with a simple config. -- [x] Provides type-safe testing utilities to check for circuit computations & soundness errors, with minimal boilerplate code! -- [x] Supports all protocols: `groth16`, `plonk`, and `fflonk`. -- [x] Automatically downloads phase-1 PTAU when using `bn128`. -- [x] Supports multiple exports such as a Solidity verifier contract and its calldata for some input, or JSON exports for R1CS and the witness file. - -## Installation - -Circomkit can be installed via: - -```sh -npm install circomkit -pnpm install circomkit -yarn add circomkit -bun add circomkit -``` - -You will also need [Circom](https://docs.circom.io), which can be installed following the instructions [here](https://docs.circom.io/getting-started/installation/). - -## Usage - -You can see available commands with: - -```sh -npx circomkit help -``` - -You can check out examples at the [circomkit-examples](https://github.com/erhant/circomkit-examples) repository, or within the [examples](./examples/) directory here. - -### Command Line Interface - -Actions that require a circuit name can be called as follows: - -```sh -# Compile the circuit -npx circomkit compile - -# Create the main component -npx circomkit instantiate - -# Create a Solidity verifier contract -npx circomkit contract - -# Clear circuit artifacts -npx circomkit clear - -# Circuit-specific setup -npx circomkit setup [ptau-path] - -# Create verification key -npx circomkit vkey [pkey-path] - -# Automatically download PTAU (for BN128) -npx circomkit ptau -``` - -> [!NOTE] -> -> Circuit-specific setup optionally takes the path to a PTAU file as argument. If not provided, it will automatically decide the PTAU to use with respect to constraint count, and download that for you! This feature only works for `bn128` prime, and has an upper-limit of at most $2^{28}$ constraints. - -Some actions such as generating a witness, generating a proof and verifying a proof require JSON inputs to provide the signal values. For that, we specifically create our input files under the `inputs` folder, and under the target circuit name there. For example, an input named `foo` for some circuit named `bar` would be at `inputs/bar/foo.json`. - -```sh -# Generate a witness -npx circomkit witness - -# Generate a proof -npx circomkit prove - -# Verify a proof with public signals -npx circomkit verify - -# Export Solidity calldata to console -npx circomkit calldata -``` - -You can also list the circuit templates and compiled instances with the command: - -```sh -npx circomkit list -``` - -### Circomkit Configurations - -Everything used by Circomkit can be optionally overridden by providing the selected fields in its constructor. Circomkit CLI does this automatically by checking out [`circomkit.json`](src/configs/index.ts#L56) and overriding the defaults with that. You can print the active configuration via the following command: - -```sh -npx circomkit config -``` - -You can edit any of the fields there to fit your needs. Most importantly, you can change the protocol to be `groth16`, `plonk` or `fflonk`; and you can change the underlying prime field to `bn128`, `bls12381` and `goldilocks`. - -> [!NOTE] -> -> Using a prime other than `bn128` makes things a bit harder in circuit-specific setup, as you will have to find the PTAU files yourself, whereas in `bn128` we can use [Perpetual Powers of Tau](https://github.com/privacy-scaling-explorations/perpetualpowersoftau). - - -### Circuit Configurations - -A circuit config within `circuits.json` looks like below, where the `key` is the circuit name to be used in commands, and the value is an object that describes the filename, template name, public signals and template parameters: - -```js -sudoku_9x9: { - file: 'sudoku', - template: 'Sudoku', - pubs: ['puzzle'], - params: [3], // sqrt(9) -} -``` - -> [!TIP] -> -> The `pubs` and `params` options can be omitted, in which case they will default to `[]`. - -### Using Circomkit in Code - -All CLI commands other than `init` can be used with the same name and arguments within Circomkit. Furthermore, you can provide configuration & inputs directly, instead of letting Circomkit read from `circuits.json` or from within the `inputs` folder. - -```ts -import {Circomkit} from 'circomkit'; - -const circomkit = new Circomkit({ - // custom configurations - protocol: 'plonk', -}); - -// artifacts output at `build/multiplier_3` directory -await circomkit.compile('multiplier_3', { - file: 'multiplier', - template: 'Multiplier', - params: [3], -}); - -// proof & public signals at `build/multiplier_3/my_input` directory -await circomkit.prove('multiplier_3', 'my_input', {in: [3, 5, 7]}); - -// verify with proof & public signals at `build/multiplier_3/my_input` -await circomkit.verify('multiplier_3', 'my_input'); -``` - -## Writing Tests - -Circomkit provides two tester utilities that use Chai assertions within, which may be used in a test suite such as Mocha. The key point of these utilities is to help reduce boilerplate code and let you simply worry about the inputs and outputs of a circuit. - -### Witness Tester - -The Witness tester extends `require('circom_tester').wasm` tool with type-safety and few assertion functions. It provides a very simple interface: - -- `expectPass(input)` checks if constraints & assertions are passing for an input -- `expectPass(input, output)` additionally checks if the outputs are matching -- `expectFail(input)` checks if any constraints / assertions are failing - -See an example below: - -```ts -describe('witness tester', () => { - // input signals and output signals can be given as type parameters - // this makes all functions type-safe! - let circuit: WitnessTester<['in'], ['out']>; - - beforeAll(async () => { - const circomkit = new Circomkit(); - circuit = await circomkit.WitnessTester(CIRCUIT_NAME, CIRCUIT_CONFIG); - }); - - it('should pass on correct input & output', async () => { - await circuit.expectPass(INPUT, OUTPUT); - }); - - it('should fail on wrong output', async () => { - await circuit.expectFail(INPUT, WRONG_OUTPUT); - }); - - it('should fail on bad input', async () => { - await circuit.expectFail(BAD_INPUT); - }); -}); -``` - -You can check if the number of constraints are correct using `expectConstraintCount`, as shown below: - -```ts -it('should have correct number of constraints', async () => { - // expects at least N constraints - await circuit.expectConstraintCount(N); - // expects exactly N constraints - await circuit.expectConstraintCount(N, true); -}); -``` - -If you want more control over the output signals, you can use the `compute` function. It takes in an input, and an array of output signal names used in the `main` component so that they can be extracted from the witness. - -```ts -it('should compute correctly', async () => { - const output = await circuit.compute(INPUT, ['out']); - expect(output).to.haveOwnProperty('out'); - expect(output.out).to.eq(BigInt(OUTPUT.out)); -}); -``` - -Finally, you can run tests on the witnesses too. This is most useful when you would like to check for soundness errors. - -- `expectConstraintPass(witness)` checks if constraints are passing for a witness -- `expectConstraintFail(witness)` checks if constraints are failing - -You can compute the witness via the `calculateWitness(input)` function. To test for soundness errors, you may edit the witness and see if constraints are failing. - -> -> -> Warning ->
-> -> Circomkit provides a nice utility for this purpose, called `editWitness(witness, symbols)`. You simply provide a dictionary of symbols to their new values, and it will edit the witness accordingly. See the example below: -> -> ```ts -> it('should pass on correct witness', async () => { -> const witness = await circuit.calculateWitness(INPUT); -> await circuit.expectConstraintPass(witness); -> }); -> -> it('should fail on fake witness', async () => { -> const witness = await circuit.calculateWitness(INPUT); -> const badWitness = await circuit.editWitness(witness, { -> 'main.signal': BigInt(1234), -> 'main.component.signal': BigInt('0xCAFE'), -> 'main.foo.bar[0]': BigInt('0b0101'), -> }); -> await circuit.expectConstraintFail(badWitness); -> }); -> ``` - -#### Using C Tester (Work in Progress ⌛) - -You can make use of the C-tester as well, which performs much better for larger circuits than the WASM alternative. - -There may be some prerequisites to compile, and we have an [issue on this](https://github.com/erhant/circomkit/issues/88) right now until we can have a complete setup guide. - -### Proof Tester - -As an alternative to simulate generating a proof and verifying it, you can use Proof Tester. The proof tester makes use of WASM file, prover key and verifier key in the background. It will use the underlying Circomkit configuration to look for those files, and it can generate them automatically if they do not exist. An example using Plonk protocol is given below. Notice how we create the necessary files before creating the tester, as they are required for proof generation and verification. - -```ts -describe('proof tester', () => { - // input signals and output signals can be given as type parameters - // this makes all functions type-safe! - let circuit: ProofTester<['in']>; - const protocol = 'plonk'; - - beforeAll(async () => { - const circomkit = new Circomkit({protocol}); - circomkit.instantiate(CIRCUIT_NAME, CIRCUIT_CONFIG); - await circomkit.setup(CIRCUIT_NAME, PTAU_PATH); - circuit = await circomkit.ProofTester(CIRCUIT_NAME, protocol); - }); - - it('should verify a proof correctly', async () => { - const {proof, publicSignals} = await circuit.prove(INPUT); - await circuit.expectPass(proof, publicSignals); - }); - - it('should NOT verify a proof with invalid public signals', async () => { - const {proof} = await circuit.prove(INPUT); - await circuit.expectFail(proof, BAD_PUBLIC_SIGNALS); - }); -}); -``` - -### Type-Safety - -You may notice that there are optional template parameters in both testers: `WitnessTester` and `ProofTester`. These template parameters take in an array of strings corresponding to signal names. For example, if your circuit has two input signals `in1, in2` and an output `out`, you may instantiate the tester as `WitnessTester<['in1', 'in2'], ['out']>`. In doing so, you will get type-checking on all inputs and outputs required by the tester. - -## File Structure - -Circomkit with its default configuration follows an _opinionated file structure_, abstracting away the pathing and orientation behind the scenes. All of these can be customized by overriding the respective settings in `circomkit.json`. - -An example structure is shown below. Suppose there is a generic circuit for a Sudoku solution knowledge proof written under `circuits` folder. When instantiated, a `main` component for a 9x9 board is created under `circuits/main`. The solution along with it's puzzle is stored as a JSON object under `inputs/sudoku_9x9`. You can see the respective artifacts under `build` directory. In particular, we see `groth16` prefix on some files, indicating that Groth16 protocol was used to create them. - -```ml -circomkit -├── circuits.json - "circuit configurations" -├── circomkit.json - "circomkit configurations" -│ -├── circuits - "circuit codes are here" -│ ├── main - "main components will be here" -│ │ └── sudoku_9x9.circom - "auto-generated circuit instance" -│ └── sudoku.circom - "circuit template" -│ -├── inputs - "circuit inputs are here" -│ └── sudoku_9x9 - "folder name is the circuit instance name" -│ └── my_solution.json - "file name is the input name" -│ -├── ptau - "PTAU files are here" -│ └── powersOfTau28_hez_final_08.ptau -│ -└── build - "build artifacts are stored here" - └── sudoku_9x9 - "folder name is the circuit instance name" - ├── sudoku_9x9_js - "WASM outputs" - │ │── generate_witness.js - │ │── witness_calculator.js - │ └── sudoku_9x9.wasm - │ - ├── my_solution - "folder name is the input name" - │ │── groth16_proof.json - "proofs are created per protocol" - │ │── public.json - │ └── witness.wtns - │ - ├── sudoku_9x9.r1cs - ├── sudoku_9x9.sym - "symbol file, used by tests" - │ - ├── groth16_pkey.zkey - "proving key per protocol" - ├── groth16_vkey.json - "verification key per protocol" - └── groth16_verifier.sol - "verifier contract" - -``` - -## Testing - -Run all tests via: - -```sh -pnpm test -``` - -> [!TIP] -> -> You can also use the CLI while developing Circomkit locally via `pnpm cli` as if you are using `npx circomkit`. This is useful for hands-on testing stuff. - -## Styling - -Circomkit uses [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html). - -```sh -# check the formatting -pnpm format - -# lint everything -pnpm lint -``` - -## Acknowledgements - -We wholeheartedly thank [BuidlGuild](https://buidlguidl.com/) & [Austin Griffith](https://twitter.com/austingriffith) for providing Circomkit with an [Ecosystem Impact Grant](https://grants.buidlguidl.com/)! diff --git a/circomkit.json b/circomkit.json deleted file mode 100644 index 57ae5b6..0000000 --- a/circomkit.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": "2.1.4", - "verbose": true, - "prime": "bn128", - "optimization": 1, - "protocol": "groth16", - "circuits": "./tests/circuits.json", - "dirPtau": "./tests/ptau", - "dirCircuits": "./tests/circuits", - "dirInputs": "./tests/inputs", - "dirBuild": "./tests/build" -} diff --git a/crates/circomkit-cli/Cargo.toml b/crates/circomkit-cli/Cargo.toml new file mode 100644 index 0000000..761c31d --- /dev/null +++ b/crates/circomkit-cli/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "circomkit-cli" +description = "CLI for Circomkit" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[[bin]] +name = "circomkit" +path = "src/main.rs" + +[dependencies] +circomkit.workspace = true +clap.workspace = true +anyhow.workspace = true +env_logger.workspace = true +log.workspace = true +serde_json.workspace = true +regex.workspace = true + +[features] +default = [] +# Native proving backends (forwarded to circomkit). +prove-arkworks = ["circomkit/prove-arkworks"] +prove-lambdaworks = ["circomkit/prove-lambdaworks"] diff --git a/crates/circomkit-cli/src/main.rs b/crates/circomkit-cli/src/main.rs new file mode 100644 index 0000000..8b52a1c --- /dev/null +++ b/crates/circomkit-cli/src/main.rs @@ -0,0 +1,289 @@ +use std::path::PathBuf; + +use anyhow::{Context, Result}; +use clap::{Parser, Subcommand}; + +use circomkit::Circomkit; + +#[derive(Parser)] +#[command( + name = "circomkit", + about = "Circom testing & development toolkit", + version +)] +struct Cli { + /// Path to circomkit.json config file + #[arg(long, default_value = "./circomkit.json")] + config: PathBuf, + + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Print the effective configuration + Config, + + /// List all configured circuits + List, + + /// Compile circuit(s); supports regex patterns to match multiple circuits + Compile { + /// Circuit name or regex pattern (e.g. "multiplier.*") + #[arg(default_value = ".*")] + pattern: String, + }, + + /// Generate main component file + Instantiate { + /// Circuit name + circuit: String, + }, + + /// Print circuit info (wires, constraints, etc.) + Info { + /// Circuit name + circuit: String, + }, + + /// Remove build artifacts for a circuit + Clear { + /// Circuit name + circuit: String, + }, + + /// Run trusted setup + Setup { + /// Circuit name + circuit: String, + /// Path to PTAU file (auto-downloads if omitted) + #[arg(long)] + ptau: Option, + }, + + /// Download PTAU file for a circuit + Ptau { + /// Circuit name + circuit: String, + }, + + /// Export verification key + Vkey { + /// Circuit name + circuit: String, + }, + + /// Export Solidity verifier contract + Contract { + /// Circuit name + circuit: String, + }, + + /// Compute witness + Witness { + /// Circuit name + circuit: String, + /// Input name (loads from inputs/{circuit}/{input}.json) + input: String, + }, + + /// Generate a proof + Prove { + /// Circuit name + circuit: String, + /// Input name + input: String, + }, + + /// Verify a proof + Verify { + /// Circuit name + circuit: String, + /// Input name + input: String, + }, + + /// Export calldata for Solidity verifier + Calldata { + /// Circuit name + circuit: String, + /// Input name + input: String, + /// Pretty-print Solidity-compatible output + #[arg(long)] + pretty: bool, + }, + + /// Export JSON + Json { + #[command(subcommand)] + target: JsonTarget, + }, +} + +#[derive(Subcommand)] +enum JsonTarget { + /// Export R1CS as JSON + R1cs { + /// Circuit name + circuit: String, + }, +} + +fn main() -> Result<()> { + env_logger::init(); + let cli = Cli::parse(); + + let ck = Circomkit::from_file(&cli.config) + .with_context(|| format!("failed to load config from {}", cli.config.display()))?; + + match cli.command { + Commands::Config => { + println!("{}", serde_json::to_string_pretty(&ck.config)?); + } + + Commands::List => { + if ck.config.circuits.is_empty() { + println!("No circuits configured."); + } else { + let mut names: Vec<_> = ck.config.circuits.keys().collect(); + names.sort(); + for name in names { + let config = &ck.config.circuits[name]; + let params = if config.params.is_empty() { + String::new() + } else { + format!( + "({})", + config + .params + .iter() + .map(|p| p.to_string()) + .collect::>() + .join(", ") + ) + }; + println!(" {name}: {}{params} ({})", config.template, config.file); + } + } + } + + Commands::Compile { pattern } => { + let re = regex::Regex::new(&pattern) + .with_context(|| format!("invalid regex pattern: {pattern}"))?; + + let mut matched = false; + let mut names: Vec<_> = ck.config.circuits.keys().collect(); + names.sort(); + + for name in names { + if re.is_match(name) { + let out = ck.compile(name)?; + println!("compiled {name} to {}", out.display()); + matched = true; + } + } + + if !matched { + anyhow::bail!("no circuits matched pattern '{pattern}'"); + } + } + + Commands::Instantiate { circuit } => { + let path = ck.instantiate(&circuit)?; + println!("instantiated at {}", path.display()); + } + + Commands::Info { circuit } => { + let info = ck.info(&circuit)?; + println!("Circuit: {circuit}"); + println!(" Wires: {}", info.wires); + println!(" Constraints: {}", info.constraints); + println!(" Public inputs: {}", info.public_inputs); + println!(" Private inputs: {}", info.private_inputs); + println!(" Public outputs: {}", info.public_outputs); + println!(" Labels: {}", info.labels); + if let Some(prime) = info.prime_name { + println!(" Prime: {prime}"); + } + if info.uses_custom_gates { + println!(" Custom gates: yes"); + } + } + + Commands::Clear { circuit } => { + ck.clear(&circuit)?; + println!("cleared {circuit}"); + } + + Commands::Setup { circuit, ptau } => { + let out = ck.setup(&circuit, ptau.as_deref())?; + println!("pkey: {}", out.pkey_path.display()); + println!("vkey: {}", out.vkey_path.display()); + } + + Commands::Ptau { circuit } => { + let path = ck.ptau(&circuit)?; + println!("ptau: {}", path.display()); + } + + Commands::Vkey { circuit } => { + let path = ck.vkey(&circuit)?; + println!("vkey: {}", path.display()); + } + + Commands::Contract { circuit } => { + let path = ck.contract(&circuit)?; + println!("contract: {}", path.display()); + } + + Commands::Witness { circuit, input } => { + let path = ck.witness(&circuit, &input, None)?; + println!("witness: {}", path.display()); + } + + Commands::Prove { circuit, input } => { + let path = ck.prove(&circuit, &input, None)?; + println!("proof: {}", path.display()); + } + + Commands::Verify { circuit, input } => { + let ok = ck.verify(&circuit, &input)?; + if ok { + println!("OK! Proof is valid."); + } else { + println!("INVALID. Proof verification failed."); + std::process::exit(1); + } + } + + Commands::Calldata { + circuit, + input, + pretty, + } => { + let calldata = ck.calldata(&circuit, &input, pretty)?; + println!("{calldata}"); + } + + Commands::Json { target } => match target { + JsonTarget::R1cs { circuit } => { + let info = ck.info(&circuit)?; + println!( + "{}", + serde_json::to_string_pretty(&serde_json::json!({ + "wires": info.wires, + "constraints": info.constraints, + "publicInputs": info.public_inputs, + "privateInputs": info.private_inputs, + "publicOutputs": info.public_outputs, + "labels": info.labels, + }))? + ); + } + }, + } + + Ok(()) +} diff --git a/crates/circomkit-core/Cargo.toml b/crates/circomkit-core/Cargo.toml new file mode 100644 index 0000000..0383532 --- /dev/null +++ b/crates/circomkit-core/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "circomkit-core" +description = "Core types, config, pathing, parsing, and compilation for Circomkit" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +serde.workspace = true +serde_json.workspace = true +schemars.workspace = true +num-bigint.workspace = true +num-traits.workspace = true +thiserror.workspace = true +log.workspace = true + +[features] +default = ["download"] +download = ["dep:ureq"] + +[dependencies.ureq] +workspace = true +optional = true diff --git a/crates/circomkit-core/src/config/circomkit.rs b/crates/circomkit-core/src/config/circomkit.rs new file mode 100644 index 0000000..4097ecd --- /dev/null +++ b/crates/circomkit-core/src/config/circomkit.rs @@ -0,0 +1,202 @@ +use std::collections::HashMap; +use std::path::Path; + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use super::circuit::CircuitConfig; +use super::compiler::CompilerConfig; +use super::prover::ProverConfig; +use super::witness::WitnessConfig; +use crate::enums::{LogLevel, Protocol}; +use crate::error::{CoreError, Result}; + +/// Top-level circomkit configuration. +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(default, rename_all = "camelCase")] +pub struct CircomkitConfig { + /// Prover settings. + pub prover: ProverConfig, + /// Compiler settings. + pub compiler: CompilerConfig, + /// Witness generation settings. + pub witness: WitnessConfig, + /// Circuit definitions, keyed by circuit name. + pub circuits: HashMap, + /// Circom version for pragma. + pub version: String, + /// Log level. + pub log_level: LogLevel, +} + +impl Default for CircomkitConfig { + fn default() -> Self { + Self { + prover: ProverConfig::default(), + compiler: CompilerConfig::default(), + witness: WitnessConfig::default(), + circuits: HashMap::new(), + version: "2.1.0".to_string(), + log_level: LogLevel::default(), + } + } +} + +/// A circuit config with global settings resolved (overrides merged). +#[derive(Debug, Clone)] +pub struct ResolvedCircuitConfig { + pub circuit: CircuitConfig, + pub prover: ProverConfig, + pub compiler: CompilerConfig, + pub version: String, +} + +impl CircomkitConfig { + /// Load config from a JSON file, falling back to defaults for missing fields. + /// + /// Automatically detects the legacy Circomkit v0.3 flat config format + /// and converts it to the new nested format. + pub fn from_file(path: &Path) -> Result { + if !path.exists() { + return Ok(Self::default()); + } + let contents = std::fs::read_to_string(path)?; + let value: serde_json::Value = serde_json::from_str(&contents)?; + + let config = if super::legacy::is_legacy_format(&value) { + log::info!("detected legacy Circomkit v0.3 config format, converting..."); + let config_dir = path.parent().unwrap_or(Path::new(".")); + super::legacy::from_legacy(&value, config_dir)? + } else { + serde_json::from_value(value)? + }; + + config.validate()?; + Ok(config) + } + + /// Validate the configuration. + pub fn validate(&self) -> Result<()> { + if self.prover.protocol == Protocol::Plonk && self.compiler.optimization != 1 { + return Err(CoreError::PlonkOptimization); + } + Ok(()) + } + + /// Resolve a circuit config by name, merging per-circuit overrides with global settings. + pub fn resolve_circuit(&self, name: &str) -> Result { + let circuit = self + .circuits + .get(name) + .ok_or_else(|| CoreError::CircuitNotFound(name.to_string()))?; + + let mut prover = self.prover.clone(); + let mut compiler = self.compiler.clone(); + let mut version = self.version.clone(); + + if let Some(overrides) = &circuit.overrides { + if let Some(p) = &overrides.prover { + p.merge_into(&mut prover); + } + if let Some(c) = &overrides.compiler { + c.merge_into(&mut compiler); + } + if let Some(v) = &overrides.version { + version = v.clone(); + } + } + + Ok(ResolvedCircuitConfig { + circuit: circuit.clone(), + prover, + compiler, + version, + }) + } + + /// Generate the JSON Schema for this config. + pub fn json_schema() -> schemars::schema::RootSchema { + schemars::schema_for!(CircomkitConfig) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::config::circuit::{CircuitOverrides, PartialCompilerConfig}; + use crate::enums::Prime; + + #[test] + fn default_config_is_valid() { + let config = CircomkitConfig::default(); + assert!(config.validate().is_ok()); + } + + #[test] + fn plonk_requires_opt_1() { + let mut config = CircomkitConfig::default(); + config.prover.protocol = Protocol::Plonk; + config.compiler.optimization = 0; + assert!(config.validate().is_err()); + } + + #[test] + fn circuit_overrides_merge() { + let mut config = CircomkitConfig::default(); + config.circuits.insert( + "test".to_string(), + CircuitConfig { + file: "test".to_string(), + template: "Test".to_string(), + pubs: vec![], + params: vec![], + uses_custom_templates: false, + overrides: Some(CircuitOverrides { + compiler: Some(PartialCompilerConfig { + optimization: Some(2), + ..Default::default() + }), + ..Default::default() + }), + }, + ); + + let resolved = config.resolve_circuit("test").unwrap(); + assert_eq!(resolved.compiler.optimization, 2); + assert_eq!(resolved.compiler.prime, Prime::Bn128); + } + + #[test] + fn circuit_not_found() { + let config = CircomkitConfig::default(); + assert!(config.resolve_circuit("nonexistent").is_err()); + } + + #[test] + fn roundtrip_json() { + let config = CircomkitConfig::default(); + let json = serde_json::to_string_pretty(&config).unwrap(); + let parsed: CircomkitConfig = serde_json::from_str(&json).unwrap(); + assert_eq!(parsed.version, config.version); + assert_eq!(parsed.prover.protocol, config.prover.protocol); + } + + #[test] + fn json_schema_generates() { + let schema = CircomkitConfig::json_schema(); + let json = serde_json::to_string_pretty(&schema).unwrap(); + assert!(json.contains("CircomkitConfig")); + } + + #[test] + #[ignore = "run manually to generate schema: cargo test -p circomkit-core generate_schema -- --ignored"] + fn generate_schema() { + let schema = CircomkitConfig::json_schema(); + let json = serde_json::to_string_pretty(&schema).unwrap(); + let out_path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../..") + .join("schema.json"); + std::fs::write(&out_path, &json).unwrap(); + println!("schema written to {}", out_path.display()); + } +} diff --git a/crates/circomkit-core/src/config/circuit.rs b/crates/circomkit-core/src/config/circuit.rs new file mode 100644 index 0000000..76fc5c2 --- /dev/null +++ b/crates/circomkit-core/src/config/circuit.rs @@ -0,0 +1,69 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use super::compiler::CompilerConfig; +use super::overrides::partial_config; +use super::prover::ProverConfig; +use crate::enums::{Prime, Protocol, ProvingBackendKind}; + +/// Per-circuit configuration. +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct CircuitConfig { + /// Path to the circuit template file (relative to `src_dir`, without extension). + pub file: String, + /// Name of the circom template to instantiate. + pub template: String, + /// Public input signal names. + #[serde(default)] + pub pubs: Vec, + /// Template parameters. + #[serde(default)] + pub params: Vec, + /// Whether the circuit uses custom templates (custom pragma). + #[serde(default)] + pub uses_custom_templates: bool, + /// Per-circuit config overrides. + #[serde(default)] + pub overrides: Option, +} + +/// Per-circuit overrides that merge on top of global config. +#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)] +#[serde(default, rename_all = "camelCase")] +pub struct CircuitOverrides { + pub prover: Option, + pub compiler: Option, + pub version: Option, +} + +partial_config! { + #[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)] + #[serde(default, rename_all = "camelCase")] + pub struct PartialProverConfig merges into ProverConfig { + pub protocol: Protocol, + pub backend: ProvingBackendKind, + pub verbose: bool, + pub ptau_dir: std::path::PathBuf, + pub input_dir: std::path::PathBuf + } +} + +partial_config! { + #[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)] + #[serde(default, rename_all = "camelCase")] + pub struct PartialCompilerConfig merges into CompilerConfig { + pub prime: Prime, + pub src_dir: std::path::PathBuf, + pub out_dir: std::path::PathBuf, + pub optimization: u32, + pub verbose: bool, + pub wasm: bool, + pub sym: bool, + pub r1cs: bool, + pub c: bool, + pub inspect: bool, + pub circom_path: String, + pub recompile: bool + } +} diff --git a/crates/circomkit-core/src/config/compiler.rs b/crates/circomkit-core/src/config/compiler.rs new file mode 100644 index 0000000..9824926 --- /dev/null +++ b/crates/circomkit-core/src/config/compiler.rs @@ -0,0 +1,60 @@ +use std::path::PathBuf; + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::enums::Prime; + +/// Compiler configuration. +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(default, rename_all = "camelCase")] +pub struct CompilerConfig { + /// Prime field for circuit compilation. + pub prime: Prime, + /// Source directory for circuit templates. + pub src_dir: PathBuf, + /// Output directory for build artifacts. + pub out_dir: PathBuf, + /// Include paths for circom (e.g. `node_modules`). + pub include: Vec, + /// Optimization level (0, 1, 2, or higher for O2round). + pub optimization: u32, + /// Whether circom should output verbose logs. + pub verbose: bool, + /// Generate WASM witness calculator. + pub wasm: bool, + /// Generate symbol file. + pub sym: bool, + /// Generate R1CS file. + pub r1cs: bool, + /// Generate C witness calculator. + pub c: bool, + /// Run constraint inspection during compilation. + pub inspect: bool, + /// Path to the circom binary. + pub circom_path: String, + /// Force recompilation even if build artifacts are up-to-date. + /// When `false` (default), compilation is skipped if the R1CS file exists + /// and is newer than the source `.circom` file. + pub recompile: bool, +} + +impl Default for CompilerConfig { + fn default() -> Self { + Self { + prime: Prime::Bn128, + src_dir: PathBuf::from("./circuits"), + out_dir: PathBuf::from("./build"), + include: vec![PathBuf::from("./node_modules")], + optimization: 1, + verbose: true, + wasm: true, + sym: true, + r1cs: true, + c: false, + inspect: true, + circom_path: "circom".to_string(), + recompile: false, + } + } +} diff --git a/crates/circomkit-core/src/config/legacy.rs b/crates/circomkit-core/src/config/legacy.rs new file mode 100644 index 0000000..0af1661 --- /dev/null +++ b/crates/circomkit-core/src/config/legacy.rs @@ -0,0 +1,245 @@ +//! Backwards compatibility for the original Circomkit v0.3 config format. +//! +//! The old format is a flat JSON with fields like `dirCircuits`, `dirBuild`, +//! `groth16numContributions`, etc., and a `circuits` field pointing to a +//! separate JSON file containing the circuit definitions. + +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +use serde::Deserialize; + +use super::circomkit::CircomkitConfig; +use super::circuit::CircuitConfig; +use super::compiler::CompilerConfig; +use super::prover::{Groth16Options, ProverConfig}; +use super::witness::WitnessConfig; +use crate::enums::{LogLevel, Prime, Protocol, ProvingBackendKind, WitnessBackend}; +use crate::error::Result; + +/// The original Circomkit v0.3 flat config format. +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct LegacyConfig { + #[serde(default = "default_protocol")] + protocol: Protocol, + #[serde(default = "default_prime")] + prime: Prime, + #[serde(default = "default_version")] + version: String, + + /// Path to a separate circuits.json file. + #[serde(default = "default_circuits_path")] + circuits: String, + + #[serde(default = "default_dir_circuits")] + dir_circuits: PathBuf, + #[serde(default = "default_dir_inputs")] + dir_inputs: PathBuf, + #[serde(default = "default_dir_ptau")] + dir_ptau: PathBuf, + #[serde(default = "default_dir_build")] + dir_build: PathBuf, + #[serde(default = "default_circom_path")] + circom_path: String, + + #[serde(default)] + optimization: Option, + #[serde(default = "default_true")] + inspect: bool, + #[serde(default = "default_include")] + include: Vec, + #[serde(default = "default_true")] + verbose: bool, + #[serde(default = "default_log_level")] + log_level: LogLevel, + + #[serde(default)] + c_witness: bool, + #[serde(default = "default_true")] + wasm_witness: bool, + + #[serde(default = "default_one")] + groth16num_contributions: u32, + #[serde(default)] + groth16ask_for_entropy: bool, +} + +fn default_protocol() -> Protocol { + Protocol::Groth16 +} +fn default_prime() -> Prime { + Prime::Bn128 +} +fn default_version() -> String { + "2.1.0".to_string() +} +fn default_circuits_path() -> String { + "./circuits.json".to_string() +} +fn default_dir_circuits() -> PathBuf { + PathBuf::from("./circuits") +} +fn default_dir_inputs() -> PathBuf { + PathBuf::from("./inputs") +} +fn default_dir_ptau() -> PathBuf { + PathBuf::from("./ptau") +} +fn default_dir_build() -> PathBuf { + PathBuf::from("./build") +} +fn default_circom_path() -> String { + "circom".to_string() +} +fn default_include() -> Vec { + vec![PathBuf::from("./node_modules")] +} +fn default_log_level() -> LogLevel { + LogLevel::Info +} +fn default_true() -> bool { + true +} +fn default_one() -> u32 { + 1 +} + +/// Detect whether a JSON value is in legacy format. +/// +/// Legacy configs have top-level `dirCircuits` or `dirBuild` fields. +/// New configs have a nested `compiler` object. +pub fn is_legacy_format(value: &serde_json::Value) -> bool { + value.get("dirCircuits").is_some() + || value.get("dirBuild").is_some() + || value.get("dirPtau").is_some() + || value.get("dirInputs").is_some() + || (value.get("circuits").is_some_and(|v| v.is_string())) +} + +/// Convert a legacy config JSON into a new `CircomkitConfig`. +/// +/// If the legacy config has a `circuits` field pointing to a file path, +/// the circuits are loaded from that file (resolved relative to `config_dir`). +pub fn from_legacy(value: &serde_json::Value, config_dir: &Path) -> Result { + let legacy: LegacyConfig = serde_json::from_value(value.clone())?; + + // Load circuits from the external file + let circuits = load_legacy_circuits(&legacy.circuits, config_dir)?; + + let optimization = legacy.optimization.unwrap_or(1); + + Ok(CircomkitConfig { + prover: ProverConfig { + protocol: legacy.protocol, + backend: ProvingBackendKind::Snarkjs, + verbose: legacy.verbose, + ptau_dir: legacy.dir_ptau, + input_dir: legacy.dir_inputs, + groth16: Groth16Options { + num_contributions: legacy.groth16num_contributions, + ask_for_entropy: legacy.groth16ask_for_entropy, + }, + }, + compiler: CompilerConfig { + prime: legacy.prime, + src_dir: legacy.dir_circuits, + out_dir: legacy.dir_build, + include: legacy.include, + optimization, + verbose: legacy.verbose, + wasm: legacy.wasm_witness, + sym: true, + r1cs: true, + c: legacy.c_witness, + inspect: legacy.inspect, + circom_path: legacy.circom_path, + recompile: false, + }, + witness: WitnessConfig { + calculator: if legacy.wasm_witness { + WitnessBackend::Wasm + } else { + WitnessBackend::C + }, + }, + circuits, + version: legacy.version, + log_level: legacy.log_level, + }) +} + +/// Load circuit configs from a separate JSON file (the v0.3 pattern). +fn load_legacy_circuits( + circuits_path: &str, + config_dir: &Path, +) -> Result> { + let resolved = config_dir.join(circuits_path); + if !resolved.exists() { + log::warn!("legacy circuits file not found: {}", resolved.display()); + return Ok(HashMap::new()); + } + + let contents = std::fs::read_to_string(&resolved)?; + let circuits: HashMap = serde_json::from_str(&contents)?; + Ok(circuits) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn detect_legacy_format() { + let legacy = serde_json::json!({ + "protocol": "groth16", + "prime": "bn128", + "dirCircuits": "./circuits", + "dirBuild": "./build", + "circuits": "./circuits.json" + }); + assert!(is_legacy_format(&legacy)); + + let new = serde_json::json!({ + "compiler": { "prime": "bn128" }, + "prover": { "protocol": "groth16" }, + "circuits": { "mul": { "file": "mul", "template": "Mul" } } + }); + assert!(!is_legacy_format(&new)); + } + + #[test] + fn convert_legacy_config() { + let legacy = serde_json::json!({ + "protocol": "groth16", + "prime": "bn128", + "version": "2.1.4", + "verbose": false, + "optimization": 2, + "dirCircuits": "./src/circuits", + "dirInputs": "./src/inputs", + "dirPtau": "./ptau", + "dirBuild": "./out", + "circuits": "./circuits.json", + "groth16numContributions": 3, + "groth16askForEntropy": true, + "cWitness": true, + "wasmWitness": false + }); + + // Use a temp dir so we don't need an actual circuits.json + let config = from_legacy(&legacy, Path::new("/nonexistent")).unwrap(); + + assert_eq!(config.prover.protocol, Protocol::Groth16); + assert_eq!(config.compiler.prime, Prime::Bn128); + assert_eq!(config.compiler.optimization, 2); + assert_eq!(config.compiler.src_dir, PathBuf::from("./src/circuits")); + assert_eq!(config.compiler.out_dir, PathBuf::from("./out")); + assert_eq!(config.prover.ptau_dir, PathBuf::from("./ptau")); + assert_eq!(config.prover.groth16.num_contributions, 3); + assert!(config.prover.groth16.ask_for_entropy); + assert!(config.compiler.c); + assert!(!config.compiler.wasm); + assert_eq!(config.version, "2.1.4"); + } +} diff --git a/crates/circomkit-core/src/config/mod.rs b/crates/circomkit-core/src/config/mod.rs new file mode 100644 index 0000000..b145819 --- /dev/null +++ b/crates/circomkit-core/src/config/mod.rs @@ -0,0 +1,13 @@ +mod circomkit; +mod circuit; +mod compiler; +pub mod legacy; +mod overrides; +mod prover; +mod witness; + +pub use circomkit::{CircomkitConfig, ResolvedCircuitConfig}; +pub use circuit::{CircuitConfig, CircuitOverrides, PartialCompilerConfig, PartialProverConfig}; +pub use compiler::CompilerConfig; +pub use prover::{Groth16Options, ProverConfig}; +pub use witness::WitnessConfig; diff --git a/crates/circomkit-core/src/config/overrides.rs b/crates/circomkit-core/src/config/overrides.rs new file mode 100644 index 0000000..2843711 --- /dev/null +++ b/crates/circomkit-core/src/config/overrides.rs @@ -0,0 +1,34 @@ +/// Macro to generate partial config structs where every field is `Option`. +/// Used for per-circuit config overrides. +macro_rules! partial_config { + ( + $(#[$meta:meta])* + pub struct $name:ident merges into $base:ty { + $( + $(#[$field_meta:meta])* + pub $field:ident : $ty:ty + ),* $(,)? + } + ) => { + $(#[$meta])* + pub struct $name { + $( + $(#[$field_meta])* + pub $field: Option<$ty>, + )* + } + + impl $name { + /// Merge non-None fields into the base config. + pub fn merge_into(&self, base: &mut $base) { + $( + if let Some(v) = &self.$field { + base.$field = v.clone(); + } + )* + } + } + }; +} + +pub(crate) use partial_config; diff --git a/crates/circomkit-core/src/config/prover.rs b/crates/circomkit-core/src/config/prover.rs new file mode 100644 index 0000000..c6b7879 --- /dev/null +++ b/crates/circomkit-core/src/config/prover.rs @@ -0,0 +1,56 @@ +use std::path::PathBuf; + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::enums::{Protocol, ProvingBackendKind}; + +/// Groth16-specific prover options. +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(default, rename_all = "camelCase")] +pub struct Groth16Options { + /// Number of phase-2 contributions. + pub num_contributions: u32, + /// Whether to prompt for entropy during contributions. + pub ask_for_entropy: bool, +} + +impl Default for Groth16Options { + fn default() -> Self { + Self { + num_contributions: 1, + ask_for_entropy: false, + } + } +} + +/// Prover configuration. +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(default, rename_all = "camelCase")] +pub struct ProverConfig { + /// Proof protocol to use. + pub protocol: Protocol, + /// Proving backend. + pub backend: ProvingBackendKind, + /// Whether snarkjs should log verbosely. + pub verbose: bool, + /// Directory for Powers of Tau files. + pub ptau_dir: PathBuf, + /// Directory for circuit input JSON files. + pub input_dir: PathBuf, + /// Groth16-specific options. + pub groth16: Groth16Options, +} + +impl Default for ProverConfig { + fn default() -> Self { + Self { + protocol: Protocol::Groth16, + backend: ProvingBackendKind::default(), + verbose: true, + ptau_dir: PathBuf::from("./ptau"), + input_dir: PathBuf::from("./inputs"), + groth16: Groth16Options::default(), + } + } +} diff --git a/crates/circomkit-core/src/config/witness.rs b/crates/circomkit-core/src/config/witness.rs new file mode 100644 index 0000000..4de58f1 --- /dev/null +++ b/crates/circomkit-core/src/config/witness.rs @@ -0,0 +1,12 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::enums::WitnessBackend; + +/// Witness generation configuration. +#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)] +#[serde(default, rename_all = "camelCase")] +pub struct WitnessConfig { + /// Which witness calculator backend to use. + pub calculator: WitnessBackend, +} diff --git a/crates/circomkit-core/src/enums.rs b/crates/circomkit-core/src/enums.rs new file mode 100644 index 0000000..b530b00 --- /dev/null +++ b/crates/circomkit-core/src/enums.rs @@ -0,0 +1,97 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::fmt; + +/// Zero-knowledge proof protocol. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum Protocol { + Groth16, + Plonk, + Fflonk, +} + +impl fmt::Display for Protocol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Groth16 => write!(f, "groth16"), + Self::Plonk => write!(f, "plonk"), + Self::Fflonk => write!(f, "fflonk"), + } + } +} + +/// Finite field / elliptic curve prime. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum Prime { + Bn128, + Bls12381, + Goldilocks, + Grumpkin, + Pallas, + Vesta, + Secq256r1, +} + +impl fmt::Display for Prime { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Bn128 => write!(f, "bn128"), + Self::Bls12381 => write!(f, "bls12381"), + Self::Goldilocks => write!(f, "goldilocks"), + Self::Grumpkin => write!(f, "grumpkin"), + Self::Pallas => write!(f, "pallas"), + Self::Vesta => write!(f, "vesta"), + Self::Secq256r1 => write!(f, "secq256r1"), + } + } +} + +/// Witness calculator backend. +/// TODO: should be at circomkit-witness? +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum WitnessBackend { + #[default] + Wasm, + C, +} + +/// Proving backend kind. +/// TODO: should be at circomkit-prove? +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum ProvingBackendKind { + #[default] + Snarkjs, + Arkworks, + Lambdaworks, +} + +/// Log level for circomkit operations. +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum LogLevel { + Trace, + Debug, + #[default] + Info, + Warn, + Error, + Silent, +} + +impl LogLevel { + /// Convert to `log::LevelFilter`. + pub fn to_level_filter(self) -> log::LevelFilter { + match self { + Self::Trace => log::LevelFilter::Trace, + Self::Debug => log::LevelFilter::Debug, + Self::Info => log::LevelFilter::Info, + Self::Warn => log::LevelFilter::Warn, + Self::Error => log::LevelFilter::Error, + Self::Silent => log::LevelFilter::Off, + } + } +} diff --git a/crates/circomkit-core/src/error.rs b/crates/circomkit-core/src/error.rs new file mode 100644 index 0000000..1efe7ba --- /dev/null +++ b/crates/circomkit-core/src/error.rs @@ -0,0 +1,52 @@ +use std::path::PathBuf; + +/// Core error type for circomkit-core operations. +#[derive(Debug, thiserror::Error)] +pub enum CoreError { + #[error("circuit '{0}' not found in config")] + CircuitNotFound(String), + + #[error("invalid protocol '{0}': expected groth16, plonk, or fflonk")] + InvalidProtocol(String), + + #[error("invalid prime '{0}'")] + InvalidPrime(String), + + #[error("invalid R1CS file: {0}")] + InvalidR1cs(String), + + #[error("invalid witness file: {0}")] + InvalidWitness(String), + + #[error("invalid symbols file: {0}")] + InvalidSymbols(String), + + #[error("compilation failed: {0}")] + CompilationFailed(String), + + #[error("PLONK protocol requires optimization level 1")] + PlonkOptimization, + + #[error("PTAU not found and auto-download is unavailable for prime '{0}'")] + PtauUnavailable(String), + + #[error("PTAU download failed: {0}")] + PtauDownloadFailed(String), + + #[error("file not found: {}", .0.display())] + FileNotFound(PathBuf), + + #[error("signal not found: {0}")] + SignalNotFound(String), + + #[error("config validation failed: {0}")] + ConfigValidation(String), + + #[error(transparent)] + Io(#[from] std::io::Error), + + #[error(transparent)] + Json(#[from] serde_json::Error), +} + +pub type Result = std::result::Result; diff --git a/crates/circomkit-core/src/functions/calldata.rs b/crates/circomkit-core/src/functions/calldata.rs new file mode 100644 index 0000000..e4d7e80 --- /dev/null +++ b/crates/circomkit-core/src/functions/calldata.rs @@ -0,0 +1,182 @@ +use num_bigint::BigInt; + +use crate::error::{CoreError, Result}; + +/// Generate calldata string from a proof and public signals. +/// +/// Dispatches to the appropriate protocol-specific formatter based on the +/// `protocol` field in the proof JSON. +pub fn get_calldata(proof: &serde_json::Value, pubs: &[String], pretty: bool) -> Result { + let protocol = proof["protocol"] + .as_str() + .ok_or_else(|| CoreError::InvalidR1cs("proof missing 'protocol' field".to_string()))?; + + let pubs_calldata = public_signals_calldata(pubs, pretty); + + let proof_calldata = match protocol { + "groth16" => groth16_calldata(proof, pretty), + "plonk" => plonk_calldata(proof, pretty), + "fflonk" => fflonk_calldata(proof, pretty), + _ => return Err(CoreError::InvalidProtocol(protocol.to_string())), + }; + + Ok(format!("\n{proof_calldata}\n\n{pubs_calldata}\n")) +} + +fn public_signals_calldata(pubs: &[String], pretty: bool) -> String { + let pubs256 = values_to_padded_uint256s(pubs); + if pretty { + format!( + "uint[{}] memory pubs = [\n {}\n];", + pubs.len(), + pubs256.join(",\n ") + ) + } else { + let quoted: Vec = pubs256.iter().map(|s| format!("\"{s}\"")).collect(); + format!("[{}]", quoted.join(",")) + } +} + +fn groth16_calldata(proof: &serde_json::Value, pretty: bool) -> String { + let p_a = values_to_padded_uint256s(&extract_strs(&proof["pi_a"], 2)); + // Note: pB indices are reversed for Ethereum compatibility + let p_b0 = values_to_padded_uint256s(&[ + extract_str(&proof["pi_b"][0][1]), + extract_str(&proof["pi_b"][0][0]), + ]); + let p_b1 = values_to_padded_uint256s(&[ + extract_str(&proof["pi_b"][1][1]), + extract_str(&proof["pi_b"][1][0]), + ]); + let p_c = values_to_padded_uint256s(&extract_strs(&proof["pi_c"], 2)); + + if pretty { + [ + format!("uint[2] memory pA = [\n {}\n];", p_a.join(",\n ")), + format!( + "uint[2][2] memory pB = [\n [\n {}\n ],\n [\n {}\n ]\n];", + p_b0.join(",\n "), + p_b1.join(",\n ") + ), + format!("uint[2] memory pC = [\n {}\n];", p_c.join(",\n ")), + ] + .join("\n") + } else { + [ + format!("[{}]", with_quotes(&p_a).join(", ")), + format!( + "[[{}], [{}]]", + with_quotes(&p_b0).join(", "), + with_quotes(&p_b1).join(", ") + ), + format!("[{}]", with_quotes(&p_c).join(", ")), + ] + .join("\n") + } +} + +fn plonk_calldata(proof: &serde_json::Value, pretty: bool) -> String { + let vals = values_to_padded_uint256s(&[ + extract_str(&proof["A"][0]), + extract_str(&proof["A"][1]), + extract_str(&proof["B"][0]), + extract_str(&proof["B"][1]), + extract_str(&proof["C"][0]), + extract_str(&proof["C"][1]), + extract_str(&proof["Z"][0]), + extract_str(&proof["Z"][1]), + extract_str(&proof["T1"][0]), + extract_str(&proof["T1"][1]), + extract_str(&proof["T2"][0]), + extract_str(&proof["T2"][1]), + extract_str(&proof["T3"][0]), + extract_str(&proof["T3"][1]), + extract_str(&proof["Wxi"][0]), + extract_str(&proof["Wxi"][1]), + extract_str(&proof["Wxiw"][0]), + extract_str(&proof["Wxiw"][1]), + extract_str(&proof["eval_a"]), + extract_str(&proof["eval_b"]), + extract_str(&proof["eval_c"]), + extract_str(&proof["eval_s1"]), + extract_str(&proof["eval_s2"]), + extract_str(&proof["eval_zw"]), + ]); + + if pretty { + format!( + "uint[24] memory proof = [\n {}\n];", + vals.join(",\n ") + ) + } else { + format!("[{}]", with_quotes(&vals).join(",")) + } +} + +fn fflonk_calldata(proof: &serde_json::Value, pretty: bool) -> String { + let vals = values_to_padded_uint256s(&[ + extract_str(&proof["polynomials"]["C1"][0]), + extract_str(&proof["polynomials"]["C1"][1]), + extract_str(&proof["polynomials"]["C2"][0]), + extract_str(&proof["polynomials"]["C2"][1]), + extract_str(&proof["polynomials"]["W1"][0]), + extract_str(&proof["polynomials"]["W1"][1]), + extract_str(&proof["polynomials"]["W2"][0]), + extract_str(&proof["polynomials"]["W2"][1]), + extract_str(&proof["evaluations"]["ql"]), + extract_str(&proof["evaluations"]["qr"]), + extract_str(&proof["evaluations"]["qm"]), + extract_str(&proof["evaluations"]["qo"]), + extract_str(&proof["evaluations"]["qc"]), + extract_str(&proof["evaluations"]["s1"]), + extract_str(&proof["evaluations"]["s2"]), + extract_str(&proof["evaluations"]["s3"]), + extract_str(&proof["evaluations"]["a"]), + extract_str(&proof["evaluations"]["b"]), + extract_str(&proof["evaluations"]["c"]), + extract_str(&proof["evaluations"]["z"]), + extract_str(&proof["evaluations"]["zw"]), + extract_str(&proof["evaluations"]["t1w"]), + extract_str(&proof["evaluations"]["t2w"]), + extract_str(&proof["evaluations"]["inv"]), + ]); + + if pretty { + format!( + "uint256[24] memory proof = [\n {}\n];", + vals.join(",\n ") + ) + } else { + format!("[{}]", with_quotes(&vals).join(",")) + } +} + +/// Convert decimal string values to 0x-prefixed, zero-padded 64-hex-char (uint256) strings. +fn values_to_padded_uint256s(values: &[String]) -> Vec { + values + .iter() + .map(|v| { + let n = v + .parse::() + .unwrap_or_else(|_| panic!("invalid decimal value: {v}")); + let hex = format!("{:064x}", n); + assert!(hex.len() == 64, "uint256 overflow for value: {v}"); + format!("0x{hex}") + }) + .collect() +} + +fn with_quotes(vals: &[String]) -> Vec { + vals.iter().map(|v| format!("\"{v}\"")).collect() +} + +fn extract_str(value: &serde_json::Value) -> String { + value + .as_str() + .map(|s| s.to_string()) + .unwrap_or_else(|| value.to_string().trim_matches('"').to_string()) +} + +fn extract_strs(value: &serde_json::Value, count: usize) -> Vec { + (0..count).map(|i| extract_str(&value[i])).collect() +} diff --git a/crates/circomkit-core/src/functions/compile.rs b/crates/circomkit-core/src/functions/compile.rs new file mode 100644 index 0000000..9499f93 --- /dev/null +++ b/crates/circomkit-core/src/functions/compile.rs @@ -0,0 +1,76 @@ +use std::path::Path; +use std::process::Command; + +use crate::config::CompilerConfig; +use crate::error::{CoreError, Result}; + +/// Output from the circom compilation process. +#[derive(Debug)] +pub struct CompileOutput { + pub stdout: String, + pub stderr: String, +} + +/// Compile a circuit by invoking the `circom` binary as a subprocess. +pub fn compile_circuit( + config: &CompilerConfig, + target_path: &Path, + out_dir: &Path, +) -> Result { + std::fs::create_dir_all(out_dir)?; + + let mut cmd = Command::new(&config.circom_path); + + // Required flags + cmd.arg(target_path); + cmd.args(["-p", &config.prime.to_string()]); + cmd.args(["-o", &out_dir.to_string_lossy()]); + + // Optional output flags + if config.r1cs { + cmd.arg("--r1cs"); + } + if config.sym { + cmd.arg("--sym"); + } + if config.wasm { + cmd.arg("--wasm"); + } + if config.c { + cmd.arg("--c"); + } + if config.verbose { + cmd.arg("--verbose"); + } + if config.inspect { + cmd.arg("--inspect"); + } + + // Include paths + for inc in &config.include { + cmd.args(["-l", &inc.to_string_lossy()]); + } + + // Optimization level + if config.optimization > 2 { + cmd.arg(format!("--O2round {}", config.optimization)); + } else { + cmd.arg(format!("--O{}", config.optimization)); + } + + log::debug!("running: {:?}", cmd); + + let output = cmd.output()?; + + let stdout = String::from_utf8_lossy(&output.stdout).to_string(); + let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + + if !output.status.success() { + return Err(CoreError::CompilationFailed(format!( + "circom exited with {}\nstderr: {stderr}", + output.status + ))); + } + + Ok(CompileOutput { stdout, stderr }) +} diff --git a/crates/circomkit-core/src/functions/instantiate.rs b/crates/circomkit-core/src/functions/instantiate.rs new file mode 100644 index 0000000..dff757e --- /dev/null +++ b/crates/circomkit-core/src/functions/instantiate.rs @@ -0,0 +1,114 @@ +use std::path::Path; + +use crate::config::CircuitConfig; +use crate::error::Result; + +/// Generate the circom source code for a main component. +/// +/// The generated file includes the pragma, an include directive +/// (relative from `main/` up to the circuit file), and the +/// `component main` declaration. +pub fn make_circuit_source(config: &CircuitConfig, version: &str) -> String { + let mut source = String::new(); + + source.push_str("// auto-generated by circomkit\n"); + source.push_str(&format!("pragma circom {version};\n")); + + if config.uses_custom_templates { + source.push_str("pragma custom_templates;\n"); + } + + source.push_str(&format!("include \"../{}.circom\";\n\n", config.file)); + + // component main declaration + source.push_str("component main"); + + if !config.pubs.is_empty() { + source.push_str(&format!(" {{public[{}]}}", config.pubs.join(", "))); + } + + source.push_str(&format!( + " = {}({});\n", + config.template, + config + .params + .iter() + .map(|p| p.to_string()) + .collect::>() + .join(", ") + )); + + source +} + +/// Write the main component circom file to disk. +/// +/// Creates the target directory if it doesn't exist. +pub fn instantiate_circuit( + config: &CircuitConfig, + target_path: &Path, + version: &str, +) -> Result<()> { + let source = make_circuit_source(config, version); + + if let Some(parent) = target_path.parent() { + std::fs::create_dir_all(parent)?; + } + + std::fs::write(target_path, source)?; + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn basic_circuit_source() { + let config = CircuitConfig { + file: "multiplier".to_string(), + template: "Multiplier".to_string(), + pubs: vec![], + params: vec![serde_json::json!(3)], + uses_custom_templates: false, + overrides: None, + }; + + let source = make_circuit_source(&config, "2.1.0"); + assert!(source.contains("pragma circom 2.1.0;")); + assert!(source.contains("include \"../multiplier.circom\";")); + assert!(source.contains("component main = Multiplier(3);")); + assert!(!source.contains("custom_templates")); + } + + #[test] + fn circuit_with_public_signals() { + let config = CircuitConfig { + file: "arrays".to_string(), + template: "Arrays".to_string(), + pubs: vec!["in1D".to_string(), "in2D".to_string()], + params: vec![serde_json::json!(2), serde_json::json!(3)], + uses_custom_templates: false, + overrides: None, + }; + + let source = make_circuit_source(&config, "2.1.0"); + assert!(source.contains("{public[in1D, in2D]}")); + assert!(source.contains("= Arrays(2, 3);")); + } + + #[test] + fn circuit_with_custom_templates() { + let config = CircuitConfig { + file: "custom".to_string(), + template: "Custom".to_string(), + pubs: vec![], + params: vec![], + uses_custom_templates: true, + overrides: None, + }; + + let source = make_circuit_source(&config, "2.1.0"); + assert!(source.contains("pragma custom_templates;")); + } +} diff --git a/crates/circomkit-core/src/functions/mod.rs b/crates/circomkit-core/src/functions/mod.rs new file mode 100644 index 0000000..a8020cc --- /dev/null +++ b/crates/circomkit-core/src/functions/mod.rs @@ -0,0 +1,11 @@ +mod calldata; +mod compile; +mod instantiate; +mod symbols; + +pub use calldata::get_calldata; +pub use compile::{CompileOutput, compile_circuit}; +pub use instantiate::{instantiate_circuit, make_circuit_source}; +pub use symbols::{ + edit_witness, parse_symbols, parse_symbols_str, read_witness_raw, read_witness_signals, +}; diff --git a/crates/circomkit-core/src/functions/symbols.rs b/crates/circomkit-core/src/functions/symbols.rs new file mode 100644 index 0000000..0ec9fb7 --- /dev/null +++ b/crates/circomkit-core/src/functions/symbols.rs @@ -0,0 +1,180 @@ +use std::collections::HashMap; +use std::path::Path; + +use num_bigint::BigInt; + +use crate::error::{CoreError, Result}; +use crate::types::{CircuitSignals, SignalValue, SymbolInfo, Symbols, Witness}; + +/// Parse a `.sym` file into a symbol table. +/// +/// Each line has the format: `label_idx,var_idx,component_idx,symbol_name` +pub fn parse_symbols(path: &Path) -> Result { + let content = std::fs::read_to_string(path)?; + parse_symbols_str(&content) +} + +/// Parse symbols from a string. +pub fn parse_symbols_str(content: &str) -> Result { + let mut symbols = HashMap::new(); + + for line in content.lines() { + let line = line.trim(); + if line.is_empty() { + continue; + } + + let parts: Vec<&str> = line.splitn(4, ',').collect(); + if parts.len() < 4 { + return Err(CoreError::InvalidSymbols(format!("malformed line: {line}"))); + } + + let label_idx: usize = parts[0] + .parse() + .map_err(|_| CoreError::InvalidSymbols(format!("invalid label_idx: {}", parts[0])))?; + let var_idx: usize = parts[1] + .parse() + .map_err(|_| CoreError::InvalidSymbols(format!("invalid var_idx: {}", parts[1])))?; + let component_idx: usize = parts[2].parse().map_err(|_| { + CoreError::InvalidSymbols(format!("invalid component_idx: {}", parts[2])) + })?; + let name = parts[3].to_string(); + + symbols.insert( + name, + SymbolInfo { + label_idx, + var_idx, + component_idx, + }, + ); + } + + Ok(symbols) +} + +/// Read signal values from a witness using the symbol table. +/// +/// Handles both single signals (`main.out`) and array signals (`main.in`), +/// automatically collecting indexed entries like `main.in[0]`, `main.in[1]`, etc. +pub fn read_witness_signals( + witness: &Witness, + symbols: &Symbols, + signals: &[&str], +) -> Result { + let mut result = CircuitSignals::new(); + + for &signal in signals { + let full_name = format!("main.{signal}"); + + // Check for a direct match first + if let Some(info) = symbols.get(&full_name) { + result.insert( + signal.to_string(), + SignalValue::Single(witness[info.var_idx].clone()), + ); + continue; + } + + // Try to collect array entries: main.signal[0], main.signal[1], ... + let prefix = format!("{full_name}["); + let mut indexed: Vec<(usize, BigInt)> = Vec::new(); + + for (name, info) in symbols { + if let Some(idx) = name + .strip_prefix(&prefix) + .and_then(|rest| rest.strip_suffix(']')) + .and_then(|s| s.parse::().ok()) + { + indexed.push((idx, witness[info.var_idx].clone())); + } + } + + if indexed.is_empty() { + return Err(CoreError::SignalNotFound(signal.to_string())); + } + + indexed.sort_by_key(|(idx, _)| *idx); + let values: Vec = indexed + .into_iter() + .map(|(_, v)| SignalValue::Single(v)) + .collect(); + result.insert(signal.to_string(), SignalValue::Array(values)); + } + + Ok(result) +} + +/// Read raw symbol values from a witness by full symbol names. +pub fn read_witness_raw( + witness: &Witness, + symbols: &Symbols, + symbol_names: &[&str], +) -> Result> { + let mut result = HashMap::new(); + + for &name in symbol_names { + let info = symbols + .get(name) + .ok_or_else(|| CoreError::SignalNotFound(name.to_string()))?; + result.insert(name.to_string(), witness[info.var_idx].clone()); + } + + Ok(result) +} + +/// Edit witness values by symbol name (useful for soundness testing). +pub fn edit_witness( + witness: &Witness, + symbols: &Symbols, + overrides: &HashMap, +) -> Result { + let mut edited = witness.clone(); + + for (name, value) in overrides { + let info = symbols + .get(name) + .ok_or_else(|| CoreError::SignalNotFound(name.clone()))?; + edited[info.var_idx] = value.clone(); + } + + Ok(edited) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_sym_content() { + let content = "1,1,0,main.in[0]\n2,2,0,main.in[1]\n3,3,0,main.out\n"; + let symbols = parse_symbols_str(content).unwrap(); + + assert_eq!(symbols.len(), 3); + assert_eq!(symbols["main.out"].var_idx, 3); + assert_eq!(symbols["main.in[0]"].var_idx, 1); + } + + #[test] + fn read_signals_single_and_array() { + let content = "1,1,0,main.in[0]\n2,2,0,main.in[1]\n3,3,0,main.out\n"; + let symbols = parse_symbols_str(content).unwrap(); + let witness: Witness = vec![ + BigInt::from(0), + BigInt::from(3), + BigInt::from(5), + BigInt::from(15), + ]; + + let signals = read_witness_signals(&witness, &symbols, &["in", "out"]).unwrap(); + + assert_eq!(signals["out"], SignalValue::Single(BigInt::from(15))); + assert_eq!( + signals["in"], + SignalValue::Array(vec![ + SignalValue::Single(BigInt::from(3)), + SignalValue::Single(BigInt::from(5)), + ]) + ); + } +} diff --git a/crates/circomkit-core/src/lib.rs b/crates/circomkit-core/src/lib.rs new file mode 100644 index 0000000..9f2ca20 --- /dev/null +++ b/crates/circomkit-core/src/lib.rs @@ -0,0 +1,7 @@ +pub mod config; +pub mod enums; +pub mod error; +pub mod functions; +pub mod pathing; +pub mod types; +pub mod utils; diff --git a/crates/circomkit-core/src/pathing.rs b/crates/circomkit-core/src/pathing.rs new file mode 100644 index 0000000..49b54c5 --- /dev/null +++ b/crates/circomkit-core/src/pathing.rs @@ -0,0 +1,198 @@ +use std::path::PathBuf; + +use crate::config::CircomkitConfig; +use crate::enums::Protocol; + +/// Resolves all filesystem paths for circomkit artifacts. +#[derive(Debug, Clone)] +pub struct CircomkitPaths { + // TODO: can this be static perhaps? + // path lives as long as the Circomkit instance, so we can store refs instead of owned Paths if needed + src_dir: PathBuf, + out_dir: PathBuf, + input_dir: PathBuf, + ptau_dir: PathBuf, +} + +impl CircomkitPaths { + pub fn new(config: &CircomkitConfig) -> Self { + Self { + src_dir: config.compiler.src_dir.clone(), + out_dir: config.compiler.out_dir.clone(), + input_dir: config.prover.input_dir.clone(), + ptau_dir: config.prover.ptau_dir.clone(), + } + } + + // ---- Circuit-level paths ---- + + /// Build directory for a circuit: `{out_dir}/{circuit}` + pub fn circuit_dir(&self, circuit: &str) -> PathBuf { + self.out_dir.join(circuit) + } + + /// R1CS file: `{out_dir}/{circuit}/{circuit}.r1cs` + pub fn circuit_r1cs(&self, circuit: &str) -> PathBuf { + self.circuit_dir(circuit).join(format!("{circuit}.r1cs")) + } + + /// Symbol file: `{out_dir}/{circuit}/{circuit}.sym` + pub fn circuit_sym(&self, circuit: &str) -> PathBuf { + self.circuit_dir(circuit).join(format!("{circuit}.sym")) + } + + /// WASM file: `{out_dir}/{circuit}/{circuit}_js/{circuit}.wasm` + pub fn circuit_wasm(&self, circuit: &str) -> PathBuf { + self.circuit_dir(circuit) + .join(format!("{circuit}_js")) + .join(format!("{circuit}.wasm")) + } + + /// Main component source file: `{src_dir}/main/{circuit}.circom` + pub fn circuit_main(&self, circuit: &str) -> PathBuf { + self.src_dir.join("main").join(format!("{circuit}.circom")) + } + + /// Original circuit template source file: `{src_dir}/{file}.circom` + pub fn circuit_source(&self, file: &str) -> PathBuf { + self.src_dir.join(format!("{file}.circom")) + } + + /// C witness calculator directory: `{out_dir}/{circuit}/{circuit}_cpp` + pub fn circuit_c_dir(&self, circuit: &str) -> PathBuf { + self.circuit_dir(circuit).join(format!("{circuit}_cpp")) + } + + // ---- Protocol-dependent paths ---- + + /// Prover key: `{out_dir}/{circuit}/{protocol}_pkey.zkey` + pub fn pkey(&self, circuit: &str, protocol: Protocol) -> PathBuf { + self.circuit_dir(circuit) + .join(format!("{protocol}_pkey.zkey")) + } + + /// Verification key: `{out_dir}/{circuit}/{protocol}_vkey.json` + pub fn vkey(&self, circuit: &str, protocol: Protocol) -> PathBuf { + self.circuit_dir(circuit) + .join(format!("{protocol}_vkey.json")) + } + + /// Solidity verifier contract: `{out_dir}/{circuit}/{protocol}_verifier.sol` + pub fn verifier_sol(&self, circuit: &str, protocol: Protocol) -> PathBuf { + self.circuit_dir(circuit) + .join(format!("{protocol}_verifier.sol")) + } + + // ---- Input-dependent paths ---- + + /// Input-specific output directory: `{out_dir}/{circuit}/{input}` + pub fn input_dir(&self, circuit: &str, input: &str) -> PathBuf { + self.circuit_dir(circuit).join(input) + } + + /// Witness file: `{out_dir}/{circuit}/{input}/witness.wtns` + pub fn witness_path(&self, circuit: &str, input: &str) -> PathBuf { + self.input_dir(circuit, input).join("witness.wtns") + } + + /// Proof file: `{out_dir}/{circuit}/{input}/{protocol}_proof.json` + pub fn proof_path(&self, circuit: &str, input: &str, protocol: Protocol) -> PathBuf { + self.input_dir(circuit, input) + .join(format!("{protocol}_proof.json")) + } + + /// Public signals file: `{out_dir}/{circuit}/{input}/public.json` + pub fn public_signals_path(&self, circuit: &str, input: &str) -> PathBuf { + self.input_dir(circuit, input).join("public.json") + } + + // ---- Other paths ---- + + /// Input JSON file: `{input_dir}/{circuit}/{input}.json` + pub fn input_json(&self, circuit: &str, input: &str) -> PathBuf { + self.input_dir.join(circuit).join(format!("{input}.json")) + } + + /// PTAU file: `{ptau_dir}/{ptau_name}` + pub fn ptau(&self, ptau_name: &str) -> PathBuf { + self.ptau_dir.join(ptau_name) + } + + /// Intermediate zkey: `{out_dir}/{circuit}/{circuit}_{id}.zkey` + pub fn zkey(&self, circuit: &str, id: u32) -> PathBuf { + self.circuit_dir(circuit) + .join(format!("{circuit}_{id}.zkey")) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn test_config() -> CircomkitConfig { + CircomkitConfig::default() + } + + #[test] + fn circuit_artifact_paths() { + let paths = CircomkitPaths::new(&test_config()); + + assert_eq!( + paths.circuit_r1cs("mul"), + PathBuf::from("./build/mul/mul.r1cs") + ); + assert_eq!( + paths.circuit_sym("mul"), + PathBuf::from("./build/mul/mul.sym") + ); + assert_eq!( + paths.circuit_wasm("mul"), + PathBuf::from("./build/mul/mul_js/mul.wasm") + ); + assert_eq!( + paths.circuit_main("mul"), + PathBuf::from("./circuits/main/mul.circom") + ); + } + + #[test] + fn protocol_dependent_paths() { + let paths = CircomkitPaths::new(&test_config()); + + assert_eq!( + paths.pkey("mul", Protocol::Groth16), + PathBuf::from("./build/mul/groth16_pkey.zkey") + ); + assert_eq!( + paths.vkey("mul", Protocol::Plonk), + PathBuf::from("./build/mul/plonk_vkey.json") + ); + } + + #[test] + fn input_dependent_paths() { + let paths = CircomkitPaths::new(&test_config()); + + assert_eq!( + paths.witness_path("mul", "test"), + PathBuf::from("./build/mul/test/witness.wtns") + ); + assert_eq!( + paths.proof_path("mul", "test", Protocol::Groth16), + PathBuf::from("./build/mul/test/groth16_proof.json") + ); + assert_eq!( + paths.input_json("mul", "test"), + PathBuf::from("./inputs/mul/test.json") + ); + } + + #[test] + fn zkey_path() { + let paths = CircomkitPaths::new(&test_config()); + assert_eq!( + paths.zkey("mul", 0), + PathBuf::from("./build/mul/mul_0.zkey") + ); + } +} diff --git a/crates/circomkit-core/src/types/circuit.rs b/crates/circomkit-core/src/types/circuit.rs new file mode 100644 index 0000000..4c98d29 --- /dev/null +++ b/crates/circomkit-core/src/types/circuit.rs @@ -0,0 +1,160 @@ +use num_bigint::BigInt; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::collections::HashMap; + +/// A signal value: either a single field element or a nested array. +/// +/// When serialized to JSON, single values are written as decimal strings +/// (e.g. `"42"`) for compatibility with snarkjs. Arrays are regular JSON arrays. +/// Deserialization accepts both numbers and strings. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SignalValue { + Single(BigInt), + Array(Vec), +} + +impl Serialize for SignalValue { + fn serialize(&self, serializer: S) -> Result { + match self { + SignalValue::Single(v) => { + if let Ok(n) = i64::try_from(v) { + serializer.serialize_i64(n) + } else { + serializer.serialize_str(&v.to_string()) + } + } + SignalValue::Array(arr) => arr.serialize(serializer), + } + } +} + +impl<'de> Deserialize<'de> for SignalValue { + fn deserialize>(deserializer: D) -> Result { + let value = serde_json::Value::deserialize(deserializer)?; + signal_from_json(&value).map_err(serde::de::Error::custom) + } +} + +fn signal_from_json(value: &serde_json::Value) -> Result { + match value { + serde_json::Value::Number(n) => { + if let Some(i) = n.as_i64() { + Ok(SignalValue::Single(BigInt::from(i))) + } else if let Some(u) = n.as_u64() { + Ok(SignalValue::Single(BigInt::from(u))) + } else { + Err(format!("unsupported number: {n}")) + } + } + serde_json::Value::String(s) => s + .parse::() + .map(SignalValue::Single) + .map_err(|e| format!("invalid BigInt string '{s}': {e}")), + serde_json::Value::Array(arr) => { + let items: Result, _> = arr.iter().map(signal_from_json).collect(); + Ok(SignalValue::Array(items?)) + } + _ => Err(format!("unexpected JSON value for signal: {value}")), + } +} + +impl From for SignalValue { + fn from(v: i64) -> Self { + Self::Single(BigInt::from(v)) + } +} + +impl From for SignalValue { + fn from(v: u64) -> Self { + Self::Single(BigInt::from(v)) + } +} + +impl From for SignalValue { + fn from(v: i32) -> Self { + Self::Single(BigInt::from(v)) + } +} + +impl From for SignalValue { + fn from(v: u32) -> Self { + Self::Single(BigInt::from(v)) + } +} + +impl From for SignalValue { + fn from(v: BigInt) -> Self { + Self::Single(v) + } +} + +impl> From> for SignalValue { + fn from(v: Vec) -> Self { + Self::Array(v.into_iter().map(Into::into).collect()) + } +} + +impl + Clone> From<&[T]> for SignalValue { + fn from(v: &[T]) -> Self { + Self::Array(v.iter().cloned().map(Into::into).collect()) + } +} + +/// Circuit input/output signals: a map from signal name to value. +pub type CircuitSignals = HashMap; + +/// A witness: vector of field elements. +pub type Witness = Vec; + +/// Convenience macro for building `CircuitSignals`. +/// +/// # Examples +/// +/// ``` +/// use circomkit_core::signals; +/// +/// let s = signals! { +/// "in" => vec![3_i64, 5, 7], +/// "out" => 105_i64, +/// }; +/// ``` +#[macro_export] +macro_rules! signals { + ($($key:literal => $val:expr),* $(,)?) => {{ + let mut map = std::collections::HashMap::new(); + $(map.insert($key.to_string(), $crate::types::SignalValue::from($val));)* + map + }}; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn serialize_signals_as_json() { + let input = crate::signals! { + "in" => vec![2_i64, 3, 5], + "out" => 30_i64, + }; + let json = serde_json::to_string(&input).unwrap(); + assert!(json.contains("[2,3,5]") || json.contains("[2, 3, 5]")); + assert!(json.contains("30")); + assert!(!json.contains("BigInt")); + } + + #[test] + fn deserialize_signals_from_json() { + let json = r#"{"in": [2, 3, 5], "out": 30}"#; + let signals: CircuitSignals = serde_json::from_str(json).unwrap(); + assert_eq!(signals["out"], SignalValue::Single(BigInt::from(30))); + } + + #[test] + fn deserialize_string_signals() { + let json = r#"{"val": "12345678901234567890"}"#; + let signals: CircuitSignals = serde_json::from_str(json).unwrap(); + let expected = "12345678901234567890".parse::().unwrap(); + assert_eq!(signals["val"], SignalValue::Single(expected)); + } +} diff --git a/crates/circomkit-core/src/types/mod.rs b/crates/circomkit-core/src/types/mod.rs new file mode 100644 index 0000000..6e3dffa --- /dev/null +++ b/crates/circomkit-core/src/types/mod.rs @@ -0,0 +1,7 @@ +mod circuit; +mod r1cs; +mod symbols; + +pub use circuit::{CircuitSignals, SignalValue, Witness}; +pub use r1cs::{LinearCombination, R1CSConstraint, R1CSFile, R1CSInfo}; +pub use symbols::{SymbolInfo, Symbols}; diff --git a/crates/circomkit-core/src/types/r1cs.rs b/crates/circomkit-core/src/types/r1cs.rs new file mode 100644 index 0000000..1d06227 --- /dev/null +++ b/crates/circomkit-core/src/types/r1cs.rs @@ -0,0 +1,52 @@ +use std::collections::HashMap; + +use num_bigint::BigUint; + +use crate::enums::Prime; + +/// Information extracted from the R1CS binary header. +#[derive(Debug, Clone)] +pub struct R1CSInfo { + pub wires: u32, + pub constraints: u32, + pub private_inputs: u32, + pub public_inputs: u32, + pub public_outputs: u32, + pub uses_custom_gates: bool, + pub labels: u64, + pub prime: BigUint, + pub prime_name: Option, +} + +/// A single linear combination: mapping from wire index to coefficient. +pub type LinearCombination = HashMap; + +/// A single R1CS constraint: three linear combinations (A, B, C) such that A * B = C. +pub type R1CSConstraint = [LinearCombination; 3]; + +/// A fully-parsed R1CS file with generic field element type. +/// +/// The type parameter `T` is the field element type, determined by the +/// `chunk_to_elem` closure passed to [`parse_r1cs_bytes`](crate::utils::parse_r1cs_bytes). +/// This allows zero-cost abstraction over different backends (BigInt, arkworks, lambdaworks). +#[derive(Debug, Clone)] +pub struct R1CSFile { + /// Bytes per field element (typically 32). + pub n8: usize, + /// Field prime as raw little-endian bytes. + pub prime: BigUint, + /// Total number of variables (wires). + pub num_variables: usize, + /// Number of public outputs. + pub num_outputs: u32, + /// Number of public inputs (excludes the constant wire). + pub num_pub_inputs: u32, + /// Number of private inputs. + pub num_priv_inputs: u32, + /// Number of labels. + pub num_labels: u64, + /// Number of constraints. + pub num_constraints: usize, + /// Constraint list: each entry has three sparse linear combinations [A, B, C]. + pub constraints: Vec>, +} diff --git a/crates/circomkit-core/src/types/symbols.rs b/crates/circomkit-core/src/types/symbols.rs new file mode 100644 index 0000000..89f0baa --- /dev/null +++ b/crates/circomkit-core/src/types/symbols.rs @@ -0,0 +1,12 @@ +use std::collections::HashMap; + +/// Symbol table entry from a `.sym` file. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SymbolInfo { + pub label_idx: usize, + pub var_idx: usize, + pub component_idx: usize, +} + +/// Symbol table: maps full symbol names (e.g. `main.signal[0]`) to their metadata. +pub type Symbols = HashMap; diff --git a/crates/circomkit-core/src/utils/mod.rs b/crates/circomkit-core/src/utils/mod.rs new file mode 100644 index 0000000..c1bcad7 --- /dev/null +++ b/crates/circomkit-core/src/utils/mod.rs @@ -0,0 +1,11 @@ +mod primes; +mod ptau; +mod r1cs; +mod witness; + +pub use primes::{prime_from_value, prime_value}; +pub use ptau::{download_ptau, ptau_name_for_constraints, ptau_path_if_exists}; +pub use r1cs::{parse_r1cs_bytes, parse_r1cs_info, read_r1cs_file, read_r1cs_info}; +pub use witness::{ + parse_witness_bytes, parse_witness_file, parse_witness_to_elems, write_witness_file, +}; diff --git a/crates/circomkit-core/src/utils/primes.rs b/crates/circomkit-core/src/utils/primes.rs new file mode 100644 index 0000000..fae66aa --- /dev/null +++ b/crates/circomkit-core/src/utils/primes.rs @@ -0,0 +1,84 @@ +use num_bigint::BigUint; + +use crate::enums::Prime; + +/// Returns the field prime value for a given prime variant. +pub fn prime_value(prime: Prime) -> BigUint { + match prime { + Prime::Bn128 => BigUint::parse_bytes( + b"21888242871839275222246405745257275088548364400416034343698204186575808495617", + 10, + ) + .expect("valid bn128 prime"), + Prime::Bls12381 => BigUint::parse_bytes( + b"73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", + 16, + ) + .expect("valid bls12381 prime"), + Prime::Goldilocks => { + BigUint::parse_bytes(b"18446744069414584321", 10).expect("valid goldilocks prime") + } + Prime::Grumpkin => BigUint::parse_bytes( + b"21888242871839275222246405745257275088696311157297823662689037894645226208583", + 10, + ) + .expect("valid grumpkin prime"), + Prime::Pallas => BigUint::parse_bytes( + b"28948022309329048855892746252171976963363056481941560715954676764349967630337", + 10, + ) + .expect("valid pallas prime"), + Prime::Vesta => BigUint::parse_bytes( + b"28948022309329048855892746252171976963363056481941647379583120057206261314561", + 10, + ) + .expect("valid vesta prime"), + Prime::Secq256r1 => BigUint::parse_bytes( + b"115792089210356248762697446949407573530086143415290314195533631308867097853951", + 10, + ) + .expect("valid secq256r1 prime"), + } +} + +/// Attempts to identify a `Prime` variant from its field value. +pub fn prime_from_value(value: &BigUint) -> Option { + let primes = [ + Prime::Bn128, + Prime::Bls12381, + Prime::Goldilocks, + Prime::Grumpkin, + Prime::Pallas, + Prime::Vesta, + Prime::Secq256r1, + ]; + primes.into_iter().find(|p| prime_value(*p) == *value) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn roundtrip_all_primes() { + let primes = [ + Prime::Bn128, + Prime::Bls12381, + Prime::Goldilocks, + Prime::Grumpkin, + Prime::Pallas, + Prime::Vesta, + Prime::Secq256r1, + ]; + for p in primes { + let val = prime_value(p); + assert_eq!(prime_from_value(&val), Some(p), "roundtrip failed for {p}"); + } + } + + #[test] + fn unknown_prime_returns_none() { + let unknown = BigUint::from(42u32); + assert_eq!(prime_from_value(&unknown), None); + } +} diff --git a/crates/circomkit-core/src/utils/ptau.rs b/crates/circomkit-core/src/utils/ptau.rs new file mode 100644 index 0000000..338695c --- /dev/null +++ b/crates/circomkit-core/src/utils/ptau.rs @@ -0,0 +1,88 @@ +use std::path::{Path, PathBuf}; + +use crate::error::{CoreError, Result}; + +/// Base URL for Hermez PTAU files. +const PTAU_BASE_URL: &str = "https://storage.googleapis.com/zkevm/ptau"; + +/// Determine the PTAU file name for a given constraint count. +/// +/// Finds the smallest power of 2 such that `2^p >= constraints`, +/// then returns the corresponding PTAU filename. +pub fn ptau_name_for_constraints(constraints: u32) -> String { + let mut power = 1u32; + let mut exp = 0u32; + while power < constraints { + power = power.saturating_mul(2); + exp += 1; + } + // Minimum PTAU is 2^1 + exp = exp.max(1); + format!("powersOfTau28_hez_final_{exp:02}.ptau") +} + +/// Download a PTAU file if it doesn't already exist. +/// +/// Only available for BN128 prime. Returns the path to the PTAU file. +#[cfg(feature = "download")] +pub fn download_ptau(ptau_name: &str, ptau_dir: &Path) -> Result { + let ptau_path = ptau_dir.join(ptau_name); + + if ptau_path.exists() { + log::info!("PTAU already exists: {}", ptau_path.display()); + return Ok(ptau_path); + } + + std::fs::create_dir_all(ptau_dir)?; + + let url = format!("{PTAU_BASE_URL}/{ptau_name}"); + log::info!("downloading PTAU from {url}"); + + let response = ureq::get(&url) + .call() + .map_err(|e| CoreError::PtauDownloadFailed(e.to_string()))?; + + let mut reader = response.into_reader(); + let mut file = std::fs::File::create(&ptau_path)?; + std::io::copy(&mut reader, &mut file)?; + + log::info!("PTAU saved to {}", ptau_path.display()); + Ok(ptau_path) +} + +/// Check if a PTAU file exists at the expected path (without downloading). +pub fn ptau_path_if_exists(ptau_name: &str, ptau_dir: &Path) -> Option { + let path = ptau_dir.join(ptau_name); + path.exists().then_some(path) +} + +#[cfg(test)] +mod tests { + use super::*; + + // TODO: add ignored tests for `download_ptau` that actually download the file + + #[test] + fn ptau_naming() { + assert_eq!( + ptau_name_for_constraints(1), + "powersOfTau28_hez_final_01.ptau" + ); + assert_eq!( + ptau_name_for_constraints(2), + "powersOfTau28_hez_final_01.ptau" + ); + assert_eq!( + ptau_name_for_constraints(3), + "powersOfTau28_hez_final_02.ptau" + ); + assert_eq!( + ptau_name_for_constraints(1024), + "powersOfTau28_hez_final_10.ptau" + ); + assert_eq!( + ptau_name_for_constraints(1025), + "powersOfTau28_hez_final_11.ptau" + ); + } +} diff --git a/crates/circomkit-core/src/utils/r1cs.rs b/crates/circomkit-core/src/utils/r1cs.rs new file mode 100644 index 0000000..bac28f8 --- /dev/null +++ b/crates/circomkit-core/src/utils/r1cs.rs @@ -0,0 +1,245 @@ +use std::collections::HashMap; +use std::path::Path; + +use num_bigint::BigUint; + +use super::primes::prime_from_value; +use crate::error::{CoreError, Result}; +use crate::types::{R1CSFile, R1CSInfo}; + +/// Read circuit information from an R1CS binary file (header only). +/// +/// Follows the spec at . +pub fn read_r1cs_info(path: &Path) -> Result { + let buffer = std::fs::read(path)?; + parse_r1cs_info(&buffer) +} + +/// Parse R1CS info from a byte buffer. +pub fn parse_r1cs_info(buffer: &[u8]) -> Result { + let mut pos = 0; + + // Magic: "r1cs" (4 bytes) + if buffer.len() < 12 || &buffer[pos..pos + 4] != b"r1cs" { + return Err(CoreError::InvalidR1cs( + "missing 'r1cs' magic bytes".to_string(), + )); + } + pos += 4; + + // Version (4 bytes LE) + let version = read_u32(buffer, &mut pos); + if version != 1 { + return Err(CoreError::InvalidR1cs(format!( + "unsupported version: expected 1, got {version}" + ))); + } + + // Number of sections (4 bytes LE) + let n_sections = read_u32(buffer, &mut pos); + + let mut info = R1CSInfo { + wires: 0, + constraints: 0, + private_inputs: 0, + public_inputs: 0, + public_outputs: 0, + uses_custom_gates: false, + labels: 0, + prime: BigUint::ZERO, + prime_name: None, + }; + + for _ in 0..n_sections { + if pos + 12 > buffer.len() { + break; + } + + let section_type = read_u32(buffer, &mut pos); + let section_size = read_u64(buffer, &mut pos) as usize; + + if pos + section_size > buffer.len() { + return Err(CoreError::InvalidR1cs("section exceeds buffer".to_string())); + } + + match section_type { + // Header section + 1 => { + let field_size = read_u32(buffer, &mut pos) as usize; + + // Prime (field_size bytes, little-endian) + info.prime = BigUint::from_bytes_le(&buffer[pos..pos + field_size]); + pos += field_size; + + info.prime_name = prime_from_value(&info.prime); + + info.wires = read_u32(buffer, &mut pos); + info.public_outputs = read_u32(buffer, &mut pos); + info.public_inputs = read_u32(buffer, &mut pos); + info.private_inputs = read_u32(buffer, &mut pos); + info.labels = read_u64(buffer, &mut pos); + info.constraints = read_u32(buffer, &mut pos); + } + // Custom gates list (PLONK) + 4 => { + info.uses_custom_gates = read_u32(buffer, &mut pos) > 0; + // Skip the rest of this section + pos += section_size - 4; + } + // Skip other sections + _ => { + pos += section_size; + } + } + } + + Ok(info) +} + +/// Read and fully parse a binary `.r1cs` file, including constraints. +/// +/// The `chunk_to_elem` closure converts raw little-endian coefficient bytes (`n8` bytes) +/// into the target field element type `T`. This follows the same pattern as +/// [`parse_witness_to_elems`](super::witness::parse_witness_to_elems), enabling zero-cost +/// abstraction over different backends (BigInt, arkworks, lambdaworks). +pub fn read_r1cs_file(path: &Path, chunk_to_elem: impl Fn(&[u8]) -> T) -> Result> { + let buffer = std::fs::read(path)?; + parse_r1cs_bytes(&buffer, chunk_to_elem) +} + +/// Parse a full R1CS from a byte buffer, including constraints. +/// +/// See [`read_r1cs_file`] for details on the `chunk_to_elem` closure. +pub fn parse_r1cs_bytes( + buffer: &[u8], + chunk_to_elem: impl Fn(&[u8]) -> T, +) -> Result> { + let mut pos = 0; + + // Magic: "r1cs" (4 bytes) + if buffer.len() < 12 || &buffer[pos..pos + 4] != b"r1cs" { + return Err(CoreError::InvalidR1cs( + "missing 'r1cs' magic bytes".to_string(), + )); + } + pos += 4; + + // Version (4 bytes LE) + let version = read_u32(buffer, &mut pos); + if version != 1 { + return Err(CoreError::InvalidR1cs(format!( + "unsupported version: expected 1, got {version}" + ))); + } + + // Number of sections (4 bytes LE) + let n_sections = read_u32(buffer, &mut pos); + + // First pass: collect section offsets + let mut section_offsets: HashMap = HashMap::new(); + for _ in 0..n_sections { + if pos + 12 > buffer.len() { + return Err(CoreError::InvalidR1cs("unexpected end of file".to_string())); + } + let section_type = read_u32(buffer, &mut pos); + let section_size = read_u64(buffer, &mut pos) as usize; + if pos + section_size > buffer.len() { + return Err(CoreError::InvalidR1cs("section exceeds buffer".to_string())); + } + section_offsets.insert(section_type, (pos, section_size)); + pos += section_size; + } + + // Parse header (section 1) + let &(header_pos, _) = section_offsets + .get(&1) + .ok_or_else(|| CoreError::InvalidR1cs("missing header section".to_string()))?; + pos = header_pos; + + let n8 = read_u32(buffer, &mut pos) as usize; + let prime = BigUint::from_bytes_le(&buffer[pos..pos + n8]); + pos += n8; + + let num_variables = read_u32(buffer, &mut pos) as usize; + let num_outputs = read_u32(buffer, &mut pos); + let num_pub_inputs = read_u32(buffer, &mut pos); + let num_priv_inputs = read_u32(buffer, &mut pos); + let num_labels = read_u64(buffer, &mut pos); + let num_constraints = read_u32(buffer, &mut pos) as usize; + + // Parse constraints (section 2) + let &(constraint_pos, _) = section_offsets + .get(&2) + .ok_or_else(|| CoreError::InvalidR1cs("missing constraints section".to_string()))?; + pos = constraint_pos; + + let constraints = parse_constraints(buffer, &mut pos, num_constraints, n8, &chunk_to_elem)?; + + Ok(R1CSFile { + n8, + prime, + num_variables, + num_outputs, + num_pub_inputs, + num_priv_inputs, + num_labels, + num_constraints, + constraints, + }) +} + +/// Parse all constraints from the constraints section. +/// +/// Each constraint has three linear combinations (A, B, C). +/// Each linear combination is: count (u32), then count × (wire_index: u32, coefficient: n8 bytes LE). +fn parse_constraints( + buffer: &[u8], + pos: &mut usize, + num_constraints: usize, + n8: usize, + chunk_to_elem: &impl Fn(&[u8]) -> T, +) -> Result; 3]>> { + let mut constraints = Vec::with_capacity(num_constraints); + for _ in 0..num_constraints { + let a = parse_linear_combination(buffer, pos, n8, chunk_to_elem)?; + let b = parse_linear_combination(buffer, pos, n8, chunk_to_elem)?; + let c = parse_linear_combination(buffer, pos, n8, chunk_to_elem)?; + constraints.push([a, b, c]); + } + Ok(constraints) +} + +/// Parse a single linear combination: a sparse map from wire index to coefficient. +fn parse_linear_combination( + buffer: &[u8], + pos: &mut usize, + n8: usize, + chunk_to_elem: &impl Fn(&[u8]) -> T, +) -> Result> { + let n_terms = read_u32(buffer, pos) as usize; + let mut lc = HashMap::with_capacity(n_terms); + for _ in 0..n_terms { + let wire_idx = read_u32(buffer, pos) as usize; + if *pos + n8 > buffer.len() { + return Err(CoreError::InvalidR1cs( + "constraint coefficient exceeds buffer".to_string(), + )); + } + let coeff = chunk_to_elem(&buffer[*pos..*pos + n8]); + *pos += n8; + lc.insert(wire_idx, coeff); + } + Ok(lc) +} + +fn read_u32(buffer: &[u8], pos: &mut usize) -> u32 { + let val = u32::from_le_bytes(buffer[*pos..*pos + 4].try_into().unwrap()); + *pos += 4; + val +} + +fn read_u64(buffer: &[u8], pos: &mut usize) -> u64 { + let val = u64::from_le_bytes(buffer[*pos..*pos + 8].try_into().unwrap()); + *pos += 8; + val +} diff --git a/crates/circomkit-core/src/utils/witness.rs b/crates/circomkit-core/src/utils/witness.rs new file mode 100644 index 0000000..17ff0b3 --- /dev/null +++ b/crates/circomkit-core/src/utils/witness.rs @@ -0,0 +1,157 @@ +use std::io::Write; +use std::path::Path; + +use num_bigint::BigInt; +use num_traits::Signed; + +use super::primes::prime_value; +use crate::error::{CoreError, Result}; +use crate::types::Witness; + +/// Parse a binary `.wtns` file into witness elements. +/// +/// The witness file format (as generated by Circom witness calculators): +/// - Header: `"wtns"` magic (4 bytes), version (4 bytes LE), num sections (4 bytes LE) +/// - Section 1: field metadata — `n8` (4 bytes LE), prime `q` (n8 bytes LE), num witnesses (4 bytes LE) +/// - Section 2: witness data — `n8` bytes per element +pub fn parse_witness_file(path: &Path) -> Result { + let buffer = std::fs::read(path)?; + parse_witness_bytes(&buffer) +} + +/// Parse witness data from a byte buffer. +pub fn parse_witness_bytes(buffer: &[u8]) -> Result { + parse_witness_to_elems(buffer, BigInt::from_signed_bytes_le) + .map_err(|e| CoreError::InvalidWitness(e.to_string())) +} + +/// Generic witness parser that accepts a conversion function for each field element chunk. +pub fn parse_witness_to_elems( + buffer: &[u8], + chunk_to_elem: impl Fn(&[u8]) -> T, +) -> std::io::Result> { + let mut pos = 0; + + // Magic bytes: "wtns" + if buffer.len() < 12 || &buffer[pos..pos + 4] != b"wtns" { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid witness file: missing 'wtns' magic", + )); + } + pos += 4; + + // Version (4 bytes LE) + let _version = u32::from_le_bytes(buffer[pos..pos + 4].try_into().unwrap()); + pos += 4; + + // Number of sections (4 bytes LE) + let n_sections = u32::from_le_bytes(buffer[pos..pos + 4].try_into().unwrap()); + pos += 4; + + // Bytes per field element, set when we encounter section 1 + let mut n8: u32 = 0; + + for _ in 0..n_sections { + if pos + 12 > buffer.len() { + break; + } + + let section_id = u32::from_le_bytes(buffer[pos..pos + 4].try_into().unwrap()); + pos += 4; + + let section_length = u64::from_le_bytes(buffer[pos..pos + 8].try_into().unwrap()) as usize; + pos += 8; + + if pos + section_length > buffer.len() { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "section exceeds buffer length", + )); + } + + match section_id { + // Section 1: field metadata + 1 => { + n8 = u32::from_le_bytes(buffer[pos..pos + 4].try_into().unwrap()); + // Skip the rest (prime q + num witness values) + pos += section_length; + } + // Section 2: witness data + 2 => { + let elems: Vec = buffer[pos..pos + section_length] + .chunks(n8 as usize) + .map(&chunk_to_elem) + .collect(); + return Ok(elems); + } + // Skip unknown sections + _ => { + pos += section_length; + } + } + } + + Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "witness data section not found", + )) +} + +/// Write a witness to a binary `.wtns` file (version 2, BN128 prime). +/// +/// Uses 32 bytes per field element (n8 = 32), which is standard for BN128/BLS12-381. +/// +/// TODO: take prime as argument +pub fn write_witness_file(path: &Path, witness: &Witness) -> Result<()> { + let n8: u32 = 32; + let prime = prime_value(crate::enums::Prime::Bn128); + let prime_bytes = prime.to_bytes_le(); + + let witness_count = witness.len() as u32; + + let mut buf = Vec::new(); + + // Header + buf.write_all(b"wtns")?; + buf.write_all(&2u32.to_le_bytes())?; // version + buf.write_all(&2u32.to_le_bytes())?; // num sections + + // Section 1: field metadata + let section1_len: u64 = 4 + (n8 as u64) + 4; // n8 + prime + witness_count + buf.write_all(&1u32.to_le_bytes())?; // section id + buf.write_all(§ion1_len.to_le_bytes())?; + buf.write_all(&n8.to_le_bytes())?; + + // Prime (padded to n8 bytes) + let mut prime_buf = vec![0u8; n8 as usize]; + let len = prime_bytes.len().min(n8 as usize); + prime_buf[..len].copy_from_slice(&prime_bytes[..len]); + buf.write_all(&prime_buf)?; + + buf.write_all(&witness_count.to_le_bytes())?; + + // Section 2: witness data + let section2_len: u64 = (n8 as u64) * (witness_count as u64); + buf.write_all(&2u32.to_le_bytes())?; // section id + buf.write_all(§ion2_len.to_le_bytes())?; + + for elem in witness { + let mut elem_buf = vec![0u8; n8 as usize]; + let (_, bytes) = if elem.is_negative() { + // Shouldn't happen for valid witnesses, but handle gracefully + elem.to_bytes_le() + } else { + elem.to_bytes_le() + }; + let len = bytes.len().min(n8 as usize); + elem_buf[..len].copy_from_slice(&bytes[..len]); + buf.write_all(&elem_buf)?; + } + + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent)?; + } + std::fs::write(path, buf)?; + Ok(()) +} diff --git a/crates/circomkit-prove/Cargo.toml b/crates/circomkit-prove/Cargo.toml new file mode 100644 index 0000000..8ff2ccb --- /dev/null +++ b/crates/circomkit-prove/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "circomkit-prove" +description = "Proving backend trait and implementations for Circomkit" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +circomkit-core.workspace = true +thiserror.workspace = true +log.workspace = true +serde.workspace = true +serde_json.workspace = true +num-bigint.workspace = true +tempfile.workspace = true + +# Lambdaworks (optional) +lambdaworks-math = { workspace = true, optional = true } +lambdaworks-circom-adapter = { workspace = true, optional = true } +lambdaworks-groth16 = { workspace = true, optional = true } + +# Arkworks (optional) +ark-circom = { workspace = true, optional = true } +ark-bn254 = { workspace = true, optional = true } +ark-groth16 = { workspace = true, optional = true } +ark-ff = { workspace = true, optional = true } +ark-ec = { workspace = true, optional = true } +ark-relations = { workspace = true, optional = true } +ark-serialize = { workspace = true, optional = true } +ark-std = { workspace = true, optional = true } +rand = { workspace = true, optional = true } + +[features] +default = [] +prove-arkworks = [ + "ark-circom", "ark-bn254", "ark-groth16", "ark-ff", "ark-ec", + "ark-relations", "ark-serialize", "ark-std", "rand", +] +prove-lambdaworks = ["lambdaworks-math", "lambdaworks-circom-adapter", "lambdaworks-groth16"] diff --git a/crates/circomkit-prove/src/arkworks/convert.rs b/crates/circomkit-prove/src/arkworks/convert.rs new file mode 100644 index 0000000..4d71d01 --- /dev/null +++ b/crates/circomkit-prove/src/arkworks/convert.rs @@ -0,0 +1,24 @@ +use ark_bn254::{Bn254, Fr}; +use ark_groth16::Proof; + +/// Convert an Arkworks Groth16 proof + public inputs to snarkjs-compatible JSON. +pub fn proof_to_snarkjs_json( + proof: &Proof, + public_inputs: &[Fr], +) -> (serde_json::Value, Vec) { + let proof_json = serde_json::json!({ + "pi_a": [proof.a.x.to_string(), proof.a.y.to_string(), "1"], + "pi_b": [ + [proof.b.x.c0.to_string(), proof.b.x.c1.to_string()], + [proof.b.y.c0.to_string(), proof.b.y.c1.to_string()], + ["1", "0"] + ], + "pi_c": [proof.c.x.to_string(), proof.c.y.to_string(), "1"], + "protocol": "groth16", + "curve": "bn128" + }); + + let public_signals: Vec = public_inputs.iter().map(|s| s.to_string()).collect(); + + (proof_json, public_signals) +} diff --git a/crates/circomkit-prove/src/arkworks/core.rs b/crates/circomkit-prove/src/arkworks/core.rs new file mode 100644 index 0000000..72d66c8 --- /dev/null +++ b/crates/circomkit-prove/src/arkworks/core.rs @@ -0,0 +1,68 @@ +use std::fs::File; +use std::io::BufReader; +use std::path::Path; + +use ark_bn254::{Bn254, Fr}; +use ark_circom::circom::{R1CS, R1CSFile}; +use ark_circom::{CircomCircuit, CircomReduction, read_zkey}; +use ark_ff::PrimeField; +use ark_groth16::{Groth16, Proof, ProvingKey}; +use ark_relations::gr1cs::SynthesisError; +use ark_serialize::SerializationError; +use rand::thread_rng; + +use crate::error::ProveError; + +/// Load R1CS from a binary `.r1cs` file. +pub fn load_r1cs(r1cs_path: &Path) -> Result, ProveError> { + let reader = BufReader::new(File::open(r1cs_path)?); + R1CSFile::new(reader) + .map(Into::into) + .map_err(|e: SerializationError| { + ProveError::ProvingFailed(format!("failed to load R1CS: {e}")) + }) +} + +/// Load a proving key from a `.zkey` file. +pub fn load_proving_key(pkey_path: &Path) -> Result, ProveError> { + let mut reader = BufReader::new(File::open(pkey_path)?); + let (params, _) = read_zkey(&mut reader) + .map_err(|e| ProveError::ProvingFailed(format!("failed to load zkey: {e}")))?; + Ok(params) +} + +/// Load a witness from a binary `.wtns` file. +pub fn load_witness(wtns_path: &Path) -> Result, ProveError> { + let data = std::fs::read(wtns_path)?; + circomkit_core::utils::parse_witness_to_elems(&data, F::from_le_bytes_mod_order) + .map_err(|e| ProveError::ProvingFailed(format!("failed to load witness: {e}"))) +} + +/// Create a Groth16 proof from a circuit and proving key. +pub fn prove_circuit( + circuit: CircomCircuit, + pkey: &ProvingKey, +) -> Result, ProveError> { + Groth16::::create_random_proof_with_reduction( + circuit, + pkey, + &mut thread_rng(), + ) + .map_err(|e: SynthesisError| ProveError::ProvingFailed(format!("proof generation failed: {e}"))) +} + +/// Verify a Groth16 proof. +pub fn verify( + proof: &Proof, + public_inputs: &[Fr], + proving_key: &ProvingKey, +) -> Result { + Groth16::::verify_proof( + &ark_groth16::prepare_verifying_key(&proving_key.vk), + proof, + public_inputs, + ) + .map_err(|e: SynthesisError| { + ProveError::VerificationFailed(format!("verification failed: {e}")) + }) +} diff --git a/crates/circomkit-prove/src/arkworks/mod.rs b/crates/circomkit-prove/src/arkworks/mod.rs new file mode 100644 index 0000000..97f9b4a --- /dev/null +++ b/crates/circomkit-prove/src/arkworks/mod.rs @@ -0,0 +1,97 @@ +mod convert; +mod core; + +use std::path::Path; + +use ark_bn254::Fr; +use ark_circom::CircomCircuit; + +use circomkit_core::types::CircuitSignals; + +use crate::error::ProveError; +use crate::traits::ProvingBackend; +use crate::types::ProofOutput; + +use self::convert::proof_to_snarkjs_json; +use self::core::{load_proving_key, load_r1cs, load_witness, prove_circuit, verify}; + +/// Native Groth16 proving backend using Arkworks (BN254). +/// +/// Supports proving with existing witnesses and proving keys. +/// Setup is not yet supported natively — use `SnarkjsBackend` for setup. +pub struct ArkworksBackend; + +impl ProvingBackend for ArkworksBackend { + fn capabilities(&self) -> crate::capabilities::BackendCapabilities { + crate::capabilities::capabilities_for(circomkit_core::enums::ProvingBackendKind::Arkworks) + } + + fn full_prove( + &self, + _input: &CircuitSignals, + _wasm_path: &Path, + _pkey_path: &Path, + ) -> Result { + // full_prove requires witness calculation, which should be done + // by the caller using circomkit-witness, then calling `prove()`. + Err(ProveError::ProvingFailed( + "ArkworksBackend does not support full_prove; use circomkit-witness \ + for witness calculation, then call prove() with the witness file" + .to_string(), + )) + } + + fn prove( + &self, + witness_path: &Path, + r1cs_path: &Path, + pkey_path: &Path, + ) -> Result { + let wtns: Vec = load_witness(witness_path)?; + let pkey = load_proving_key(pkey_path)?; + + let mut r1cs = load_r1cs(r1cs_path)?; + // Disable wire mapping for WASM-generated witnesses. + // See: https://github.com/arkworks-rs/circom-compat/blob/master/src/circom/builder.rs#L82 + r1cs.wire_mapping = None; + + let circom = CircomCircuit { + r1cs, + witness: Some(wtns), + }; + + let public_inputs = circom + .get_public_inputs() + .ok_or_else(|| ProveError::ProvingFailed("could not extract public inputs".into()))?; + + let proof = prove_circuit(circom, &pkey)?; + + debug_assert!( + verify(&proof, &public_inputs, &pkey).unwrap_or(false), + "proof verification failed internally" + ); + + let (proof_json, public_signals) = proof_to_snarkjs_json(&proof, &public_inputs); + + Ok(ProofOutput { + proof: proof_json, + public_signals, + }) + } + + fn verify( + &self, + vkey: &serde_json::Value, + public_signals: &[String], + proof: &serde_json::Value, + ) -> Result { + // For native verification we'd need to deserialize the snarkjs JSON back + // into Arkworks types. For now, delegate to snarkjs for verification. + let _ = (vkey, public_signals, proof); + Err(ProveError::VerificationFailed( + "native Arkworks verification from snarkjs JSON not yet implemented; \ + use SnarkjsBackend for verification" + .to_string(), + )) + } +} diff --git a/crates/circomkit-prove/src/capabilities.rs b/crates/circomkit-prove/src/capabilities.rs new file mode 100644 index 0000000..7303b3c --- /dev/null +++ b/crates/circomkit-prove/src/capabilities.rs @@ -0,0 +1,163 @@ +//! Backend capability matrix. +//! +//! Each proving backend supports a different slice of the (protocol, curve) +//! space. snarkjs is the universal backend (all protocols, all primes), while +//! the native backends are specialized: +//! +//! | backend | protocols | curves | setup | native verify | +//! |-------------|--------------------------|------------------|--------------|---------------| +//! | snarkjs | groth16, plonk, fflonk | all 7 primes | yes | yes | +//! | lambdaworks | groth16 | bls12381 | on-the-fly | no | +//! | arkworks | groth16 | bn128 (BN254) | no (zkey) | no | +//! +//! These tables are the single source of truth used both to pick a backend +//! ([`crate::make_proving_backend`]) and to produce clear errors for +//! unsupported combinations. + +use circomkit_core::enums::{Prime, Protocol, ProvingBackendKind}; + +use crate::error::ProveError; + +/// Describes which proving features a backend supports. +#[derive(Debug, Clone)] +pub struct BackendCapabilities { + /// Human-readable backend name (matches [`ProvingBackendKind`]). + pub name: &'static str, + /// Protocols this backend can prove. + pub protocols: &'static [Protocol], + /// Primes (curves) this backend supports. + pub primes: &'static [Prime], + /// Whether the backend can run its own trusted setup. + pub supports_setup: bool, + /// Whether the backend can verify a snarkjs-format proof natively. + pub supports_native_verify: bool, + /// Whether the backend consumes a `.zkey` proving key + /// (`false` means it performs an on-the-fly setup instead). + pub uses_zkey: bool, +} + +impl BackendCapabilities { + /// Returns `true` if the backend supports the given protocol and curve. + pub fn supports(&self, protocol: Protocol, prime: Prime) -> bool { + self.protocols.contains(&protocol) && self.primes.contains(&prime) + } + + /// Returns an error describing exactly why a (protocol, curve) combination + /// is not supported, or `Ok(())` if it is. + pub fn ensure_supports(&self, protocol: Protocol, prime: Prime) -> Result<(), ProveError> { + if !self.protocols.contains(&protocol) { + return Err(ProveError::UnsupportedProtocol { + backend: self.name, + protocol, + supported: join_display(self.protocols), + }); + } + if !self.primes.contains(&prime) { + return Err(ProveError::UnsupportedCurve { + backend: self.name, + prime, + supported: join_display(self.primes), + }); + } + Ok(()) + } +} + +/// All primes snarkjs can prove over. +const ALL_PRIMES: &[Prime] = &[ + Prime::Bn128, + Prime::Bls12381, + Prime::Goldilocks, + Prime::Grumpkin, + Prime::Pallas, + Prime::Vesta, + Prime::Secq256r1, +]; + +/// Static capability table for a backend kind. +/// +/// This is available without constructing the backend, so a capability check +/// can run even when the corresponding backend feature is compiled out. +pub fn capabilities_for(kind: ProvingBackendKind) -> BackendCapabilities { + match kind { + ProvingBackendKind::Snarkjs => BackendCapabilities { + name: "snarkjs", + protocols: &[Protocol::Groth16, Protocol::Plonk, Protocol::Fflonk], + primes: ALL_PRIMES, + supports_setup: true, + supports_native_verify: true, + uses_zkey: true, + }, + ProvingBackendKind::Lambdaworks => BackendCapabilities { + name: "lambdaworks", + protocols: &[Protocol::Groth16], + primes: &[Prime::Bls12381], + supports_setup: true, + supports_native_verify: false, + uses_zkey: false, + }, + ProvingBackendKind::Arkworks => BackendCapabilities { + name: "arkworks", + protocols: &[Protocol::Groth16], + primes: &[Prime::Bn128], + supports_setup: false, + supports_native_verify: false, + uses_zkey: true, + }, + } +} + +fn join_display(items: &[T]) -> String { + items + .iter() + .map(ToString::to_string) + .collect::>() + .join(", ") +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn snarkjs_supports_everything() { + let caps = capabilities_for(ProvingBackendKind::Snarkjs); + assert!(caps.supports(Protocol::Groth16, Prime::Bn128)); + assert!(caps.supports(Protocol::Plonk, Prime::Bls12381)); + assert!(caps.supports(Protocol::Fflonk, Prime::Vesta)); + assert!( + caps.ensure_supports(Protocol::Plonk, Prime::Goldilocks) + .is_ok() + ); + } + + #[test] + fn lambdaworks_is_groth16_bls12381_only() { + let caps = capabilities_for(ProvingBackendKind::Lambdaworks); + assert!(caps.supports(Protocol::Groth16, Prime::Bls12381)); + // wrong protocol + assert!(matches!( + caps.ensure_supports(Protocol::Plonk, Prime::Bls12381), + Err(ProveError::UnsupportedProtocol { .. }) + )); + // wrong curve + assert!(matches!( + caps.ensure_supports(Protocol::Groth16, Prime::Bn128), + Err(ProveError::UnsupportedCurve { .. }) + )); + } + + #[test] + fn arkworks_is_groth16_bn128_only() { + let caps = capabilities_for(ProvingBackendKind::Arkworks); + assert!(caps.supports(Protocol::Groth16, Prime::Bn128)); + assert!(matches!( + caps.ensure_supports(Protocol::Groth16, Prime::Bls12381), + Err(ProveError::UnsupportedCurve { .. }) + )); + assert!(matches!( + caps.ensure_supports(Protocol::Fflonk, Prime::Bn128), + Err(ProveError::UnsupportedProtocol { .. }) + )); + } +} diff --git a/crates/circomkit-prove/src/error.rs b/crates/circomkit-prove/src/error.rs new file mode 100644 index 0000000..8568e4e --- /dev/null +++ b/crates/circomkit-prove/src/error.rs @@ -0,0 +1,48 @@ +use circomkit_core::enums::{Prime, Protocol}; + +/// Errors that can occur during proving operations. +#[derive(Debug, thiserror::Error)] +pub enum ProveError { + #[error("proving failed: {0}")] + ProvingFailed(String), + + #[error("verification failed: {0}")] + VerificationFailed(String), + + #[error("setup failed: {0}")] + SetupFailed(String), + + #[error("snarkjs subprocess failed: {0}")] + SnarkjsError(String), + + #[error("backend `{backend}` does not support protocol `{protocol}` (supported: {supported})")] + UnsupportedProtocol { + backend: &'static str, + protocol: Protocol, + supported: String, + }, + + #[error("backend `{backend}` does not support curve `{prime}` (supported: {supported})")] + UnsupportedCurve { + backend: &'static str, + prime: Prime, + supported: String, + }, + + #[error( + "backend `{backend}` is not enabled; rebuild circomkit-prove with the `{feature}` feature" + )] + BackendNotEnabled { + backend: &'static str, + feature: &'static str, + }, + + #[error(transparent)] + Core(#[from] circomkit_core::error::CoreError), + + #[error(transparent)] + Io(#[from] std::io::Error), + + #[error(transparent)] + Json(#[from] serde_json::Error), +} diff --git a/crates/circomkit-prove/src/lambdaworks/convert.rs b/crates/circomkit-prove/src/lambdaworks/convert.rs new file mode 100644 index 0000000..3787a54 --- /dev/null +++ b/crates/circomkit-prove/src/lambdaworks/convert.rs @@ -0,0 +1,55 @@ +use lambdaworks_groth16::Proof; +use lambdaworks_math::field::{element::FieldElement, traits::IsPrimeField}; +use num_bigint::BigUint; + +/// Convert a Lambdaworks `UnsignedInteger` hex representation to a decimal string. +/// +/// `representative().to_string()` returns `0x...` hex; snarkjs expects decimal. +fn to_decimal(hex_str: &str) -> String { + let hex = hex_str.strip_prefix("0x").unwrap_or(hex_str); + if hex.is_empty() || hex.chars().all(|c| c == '0') { + return "0".to_string(); + } + BigUint::parse_bytes(hex.as_bytes(), 16) + .expect("invalid hex from representative()") + .to_string() +} + +/// Convert a field element's representative to a decimal string. +fn field_to_dec(elem: &FieldElement) -> String { + to_decimal(&elem.representative().to_string()) +} + +/// Convert a Lambdaworks Groth16 proof to snarkjs-compatible JSON. +pub fn proof_to_snarkjs_json(proof: &Proof) -> serde_json::Value { + serde_json::json!({ + "pi_a": [ + field_to_dec(&proof.pi1.x()), + field_to_dec(&proof.pi1.y()), + "1" + ], + "pi_b": [ + [ + field_to_dec(&proof.pi2.x().value()[0]), + field_to_dec(&proof.pi2.x().value()[1]), + ], + [ + field_to_dec(&proof.pi2.y().value()[0]), + field_to_dec(&proof.pi2.y().value()[1]), + ], + ["1", "0"] + ], + "pi_c": [ + field_to_dec(&proof.pi3.x()), + field_to_dec(&proof.pi3.y()), + "1" + ], + "protocol": "groth16", + "curve": "bls12381" + }) +} + +/// Convert Lambdaworks field elements to decimal public signal strings. +pub fn public_inputs_to_strings(public_inputs: &[FieldElement]) -> Vec { + public_inputs.iter().map(|s| field_to_dec(s)).collect() +} diff --git a/crates/circomkit-prove/src/lambdaworks/mod.rs b/crates/circomkit-prove/src/lambdaworks/mod.rs new file mode 100644 index 0000000..49f3386 --- /dev/null +++ b/crates/circomkit-prove/src/lambdaworks/mod.rs @@ -0,0 +1,143 @@ +mod convert; + +use std::path::Path; + +use lambdaworks_circom_adapter::{CircomR1CS, circom_to_lambda}; +use lambdaworks_groth16::common::FrElement; +use lambdaworks_math::traits::ByteConversion; + +use circomkit_core::types::CircuitSignals; +use circomkit_core::utils::{parse_witness_to_elems, read_r1cs_file}; + +use crate::error::ProveError; +use crate::traits::ProvingBackend; +use crate::types::ProofOutput; + +use self::convert::{proof_to_snarkjs_json, public_inputs_to_strings}; + +/// Native Groth16 proving backend using Lambdaworks (BLS12-381). +/// +/// This backend performs trusted setup on-the-fly for each proof, since Lambdaworks +/// does not yet support loading pre-computed `.zkey` files. +/// +/// Supports both binary `.r1cs` and JSON `.r1cs.json` files. +pub struct LambdaworksBackend; + +impl ProvingBackend for LambdaworksBackend { + fn capabilities(&self) -> crate::capabilities::BackendCapabilities { + crate::capabilities::capabilities_for( + circomkit_core::enums::ProvingBackendKind::Lambdaworks, + ) + } + + fn full_prove( + &self, + _input: &CircuitSignals, + _wasm_path: &Path, + _pkey_path: &Path, + ) -> Result { + Err(ProveError::ProvingFailed( + "LambdaworksBackend does not support full_prove; use circomkit-witness \ + for witness calculation, then call prove() with the witness file" + .to_string(), + )) + } + + fn prove( + &self, + witness_path: &Path, + r1cs_path: &Path, + _pkey_path: &Path, + ) -> Result { + // Load R1CS (binary or JSON) + let r1cs = load_r1cs(r1cs_path)?; + + // Load witness (binary .wtns or JSON) + let wtns = load_witness(witness_path)?; + + // Convert to Lambdaworks QAP representation + let (qap, wtns, pubs) = circom_to_lambda(r1cs, wtns); + + // Trusted setup (on-the-fly, since zkey loading is not supported) + log::info!("running Lambdaworks Groth16 setup (on-the-fly)"); + let (proving_key, verifying_key) = lambdaworks_groth16::setup(&qap); + + // Generate proof + let proof = lambdaworks_groth16::Prover::prove(&wtns, &qap, &proving_key); + + // Verify internally in debug builds + debug_assert!( + lambdaworks_groth16::verify(&verifying_key, &proof, &pubs), + "Lambdaworks proof verification failed internally" + ); + + let proof_json = proof_to_snarkjs_json(&proof); + let public_signals = public_inputs_to_strings(&pubs); + + Ok(ProofOutput { + proof: proof_json, + public_signals, + }) + } + + fn verify( + &self, + vkey: &serde_json::Value, + public_signals: &[String], + proof: &serde_json::Value, + ) -> Result { + let _ = (vkey, public_signals, proof); + Err(ProveError::VerificationFailed( + "native Lambdaworks verification from snarkjs JSON not yet implemented; \ + use SnarkjsBackend for verification" + .to_string(), + )) + } +} + +/// Load an R1CS file, supporting both binary `.r1cs` and JSON `.r1cs.json` formats. +fn load_r1cs(path: &Path) -> Result { + let ext = path.extension().and_then(|e| e.to_str()).unwrap_or(""); + + if ext == "json" { + // JSON format: use lambdaworks' own reader + lambdaworks_circom_adapter::read_circom_r1cs(path).map_err(|e| { + ProveError::ProvingFailed(format!( + "failed to read R1CS JSON from {}: {e:?}", + path.display() + )) + }) + } else { + // Binary format: parse with our generic reader, convert to CircomR1CS + let r1cs = read_r1cs_file(path, |bytes| FrElement::from_bytes_le(bytes).unwrap())?; + + Ok(CircomR1CS { + n8: r1cs.n8, + prime: r1cs.prime.to_string(), + num_vars: r1cs.num_variables, + num_outputs: r1cs.num_outputs as usize, + num_pub_inputs: r1cs.num_pub_inputs as usize, + num_priv_inputs: r1cs.num_priv_inputs as usize, + num_labels: r1cs.num_labels as usize, + num_constraints: r1cs.num_constraints, + constraints: r1cs.constraints, + }) + } +} + +/// Load a witness file, supporting both binary `.wtns` and JSON formats. +fn load_witness(path: &Path) -> Result, ProveError> { + let ext = path.extension().and_then(|e| e.to_str()).unwrap_or(""); + if ext == "json" { + lambdaworks_circom_adapter::read_circom_witness(path).map_err(|e| { + ProveError::ProvingFailed(format!( + "failed to read witness JSON from {}: {e:?}", + path.display() + )) + }) + } else { + let data = std::fs::read(path)?; + parse_witness_to_elems(&data, |bytes| FrElement::from_bytes_le(bytes).unwrap()) + .map_err(|e| ProveError::ProvingFailed(format!("failed to parse witness: {e}"))) + } +} diff --git a/crates/circomkit-prove/src/lib.rs b/crates/circomkit-prove/src/lib.rs new file mode 100644 index 0000000..349ac10 --- /dev/null +++ b/crates/circomkit-prove/src/lib.rs @@ -0,0 +1,73 @@ +mod capabilities; +mod error; +mod snarkjs; +mod traits; +mod types; + +#[cfg(feature = "prove-arkworks")] +mod arkworks; + +#[cfg(feature = "prove-lambdaworks")] +mod lambdaworks; + +pub use capabilities::{BackendCapabilities, capabilities_for}; +pub use error::ProveError; +pub use snarkjs::SnarkjsBackend; +pub use traits::{ProvingBackend, SetupBackend}; +pub use types::ProofOutput; + +#[cfg(feature = "prove-arkworks")] +pub use arkworks::ArkworksBackend; + +#[cfg(feature = "prove-lambdaworks")] +pub use lambdaworks::LambdaworksBackend; + +use circomkit_core::enums::{Prime, Protocol, ProvingBackendKind}; + +/// Construct a proving backend for a `(backend, protocol, curve)` request. +/// +/// The capability matrix is checked first, so an unsupported protocol/curve +/// combination produces a precise [`ProveError::UnsupportedProtocol`] / +/// [`ProveError::UnsupportedCurve`] regardless of which backend features are +/// compiled in. If the combination is valid but the backend's feature is not +/// enabled, [`ProveError::BackendNotEnabled`] is returned instead. +pub fn make_proving_backend( + kind: ProvingBackendKind, + protocol: Protocol, + prime: Prime, +) -> Result, ProveError> { + // Capability check is always available, even for compiled-out backends. + capabilities_for(kind).ensure_supports(protocol, prime)?; + + match kind { + ProvingBackendKind::Snarkjs => Ok(Box::new(SnarkjsBackend::new("snarkjs", protocol))), + + ProvingBackendKind::Lambdaworks => { + #[cfg(feature = "prove-lambdaworks")] + { + Ok(Box::new(LambdaworksBackend)) + } + #[cfg(not(feature = "prove-lambdaworks"))] + { + Err(ProveError::BackendNotEnabled { + backend: "lambdaworks", + feature: "prove-lambdaworks", + }) + } + } + + ProvingBackendKind::Arkworks => { + #[cfg(feature = "prove-arkworks")] + { + Ok(Box::new(ArkworksBackend)) + } + #[cfg(not(feature = "prove-arkworks"))] + { + Err(ProveError::BackendNotEnabled { + backend: "arkworks", + feature: "prove-arkworks", + }) + } + } + } +} diff --git a/crates/circomkit-prove/src/snarkjs/mod.rs b/crates/circomkit-prove/src/snarkjs/mod.rs new file mode 100644 index 0000000..c2e56c5 --- /dev/null +++ b/crates/circomkit-prove/src/snarkjs/mod.rs @@ -0,0 +1,261 @@ +use std::path::Path; +use std::process::Command; + +use circomkit_core::config::ProverConfig; +use circomkit_core::enums::Protocol; +use circomkit_core::types::CircuitSignals; + +use crate::error::ProveError; +use crate::traits::{ProvingBackend, SetupBackend}; +use crate::types::ProofOutput; + +/// Proving backend that delegates to the `snarkjs` CLI via subprocess. +pub struct SnarkjsBackend { + /// Command to invoke snarkjs (e.g. "snarkjs" or "npx snarkjs"). + snarkjs_cmd: String, + /// Protocol to use for proving. + protocol: Protocol, +} + +impl Default for SnarkjsBackend { + fn default() -> Self { + Self { + snarkjs_cmd: "snarkjs".to_string(), + protocol: Protocol::Groth16, + } + } +} + +impl SnarkjsBackend { + pub fn new(cmd: impl Into, protocol: Protocol) -> Self { + Self { + snarkjs_cmd: cmd.into(), + protocol, + } + } + + fn protocol_cmd(&self) -> &str { + match self.protocol { + Protocol::Groth16 => "groth16", + Protocol::Plonk => "plonk", + Protocol::Fflonk => "fflonk", + } + } + + fn run(&self, args: &[&str]) -> Result { + log::debug!("{} {}", self.snarkjs_cmd, args.join(" ")); + + let output = Command::new(&self.snarkjs_cmd) + .args(args) + .output() + .map_err(|e| ProveError::SnarkjsError(format!("failed to run snarkjs: {e}")))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + let stdout = String::from_utf8_lossy(&output.stdout); + return Err(ProveError::SnarkjsError(format!( + "snarkjs exited with {}:\nstdout: {stdout}\nstderr: {stderr}", + output.status + ))); + } + + Ok(String::from_utf8_lossy(&output.stdout).to_string()) + } +} + +impl ProvingBackend for SnarkjsBackend { + fn capabilities(&self) -> crate::capabilities::BackendCapabilities { + crate::capabilities::capabilities_for(circomkit_core::enums::ProvingBackendKind::Snarkjs) + } + + fn full_prove( + &self, + input: &CircuitSignals, + wasm_path: &Path, + pkey_path: &Path, + ) -> Result { + let tmp_dir = tempfile::tempdir()?; + let input_path = tmp_dir.path().join("input.json"); + let proof_path = tmp_dir.path().join("proof.json"); + let public_path = tmp_dir.path().join("public.json"); + + std::fs::write(&input_path, serde_json::to_string(input)?)?; + + self.run(&[ + self.protocol_cmd(), + "fullprove", + &input_path.to_string_lossy(), + &wasm_path.to_string_lossy(), + &pkey_path.to_string_lossy(), + &proof_path.to_string_lossy(), + &public_path.to_string_lossy(), + ])?; + + let proof: serde_json::Value = + serde_json::from_str(&std::fs::read_to_string(&proof_path)?)?; + let public_signals: Vec = + serde_json::from_str(&std::fs::read_to_string(&public_path)?)?; + + Ok(ProofOutput { + proof, + public_signals, + }) + } + + fn prove( + &self, + witness_path: &Path, + _r1cs_path: &Path, + pkey_path: &Path, + ) -> Result { + let tmp_dir = tempfile::tempdir()?; + let proof_path = tmp_dir.path().join("proof.json"); + let public_path = tmp_dir.path().join("public.json"); + + self.run(&[ + self.protocol_cmd(), + "prove", + &pkey_path.to_string_lossy(), + &witness_path.to_string_lossy(), + &proof_path.to_string_lossy(), + &public_path.to_string_lossy(), + ])?; + + let proof: serde_json::Value = + serde_json::from_str(&std::fs::read_to_string(&proof_path)?)?; + let public_signals: Vec = + serde_json::from_str(&std::fs::read_to_string(&public_path)?)?; + + Ok(ProofOutput { + proof, + public_signals, + }) + } + + fn verify( + &self, + vkey: &serde_json::Value, + public_signals: &[String], + proof: &serde_json::Value, + ) -> Result { + let tmp_dir = tempfile::tempdir()?; + let vkey_path = tmp_dir.path().join("vkey.json"); + let proof_path = tmp_dir.path().join("proof.json"); + let public_path = tmp_dir.path().join("public.json"); + + std::fs::write(&vkey_path, serde_json::to_string(vkey)?)?; + std::fs::write(&proof_path, serde_json::to_string(proof)?)?; + std::fs::write(&public_path, serde_json::to_string(public_signals)?)?; + + // For verify, snarkjs exits 1 on invalid proof — that's not an error, + // it means the proof is rejected. We check stdout for "OK!" instead. + let output = Command::new(&self.snarkjs_cmd) + .args([ + self.protocol_cmd(), + "verify", + &vkey_path.to_string_lossy(), + &public_path.to_string_lossy(), + &proof_path.to_string_lossy(), + ]) + .output() + .map_err(|e| ProveError::SnarkjsError(format!("failed to run snarkjs: {e}")))?; + + let stdout = String::from_utf8_lossy(&output.stdout); + Ok(stdout.contains("OK!")) + } +} + +impl SetupBackend for SnarkjsBackend { + fn setup( + &self, + r1cs_path: &Path, + ptau_path: &Path, + pkey_path: &Path, + config: &ProverConfig, + ) -> Result<(), ProveError> { + match config.protocol { + Protocol::Groth16 => { + let tmp_dir = tempfile::tempdir()?; + let mut current_zkey = tmp_dir.path().join("circuit_0.zkey"); + + // snarkjs groth16 setup is actually "zkey new" + self.run(&[ + "groth16", + "setup", + &r1cs_path.to_string_lossy(), + &ptau_path.to_string_lossy(), + ¤t_zkey.to_string_lossy(), + ])?; + + // Phase-2 contributions + for i in 0..config.groth16.num_contributions { + let next_zkey = tmp_dir.path().join(format!("circuit_{}.zkey", i + 1)); + let name = format!("contribution_{}", i + 1); + + self.run(&[ + "zkey", + "contribute", + ¤t_zkey.to_string_lossy(), + &next_zkey.to_string_lossy(), + &format!("--name={name}"), + "-e=random_entropy", + ])?; + + current_zkey = next_zkey; + } + + if let Some(parent) = pkey_path.parent() { + std::fs::create_dir_all(parent)?; + } + std::fs::rename(¤t_zkey, pkey_path)?; + } + Protocol::Plonk | Protocol::Fflonk => { + if let Some(parent) = pkey_path.parent() { + std::fs::create_dir_all(parent)?; + } + self.run(&[ + self.protocol_cmd(), + "setup", + &r1cs_path.to_string_lossy(), + &ptau_path.to_string_lossy(), + &pkey_path.to_string_lossy(), + ])?; + } + } + + Ok(()) + } + + fn export_vkey(&self, pkey_path: &Path, vkey_path: &Path) -> Result<(), ProveError> { + if let Some(parent) = vkey_path.parent() { + std::fs::create_dir_all(parent)?; + } + self.run(&[ + "zkey", + "export", + "verificationkey", + &pkey_path.to_string_lossy(), + &vkey_path.to_string_lossy(), + ])?; + Ok(()) + } + + fn export_contract( + &self, + pkey_path: &Path, + sol_path: &Path, + _protocol: Protocol, + ) -> Result<(), ProveError> { + if let Some(parent) = sol_path.parent() { + std::fs::create_dir_all(parent)?; + } + self.run(&[ + "zkey", + "export", + "solidityverifier", + &pkey_path.to_string_lossy(), + &sol_path.to_string_lossy(), + ])?; + Ok(()) + } +} diff --git a/crates/circomkit-prove/src/traits.rs b/crates/circomkit-prove/src/traits.rs new file mode 100644 index 0000000..dcada1a --- /dev/null +++ b/crates/circomkit-prove/src/traits.rs @@ -0,0 +1,62 @@ +use std::path::Path; + +use circomkit_core::config::ProverConfig; +use circomkit_core::enums::Protocol; +use circomkit_core::types::CircuitSignals; + +use crate::capabilities::BackendCapabilities; +use crate::error::ProveError; +use crate::types::ProofOutput; + +/// Trait for proving backends. +pub trait ProvingBackend { + /// Describe which protocols and curves this backend supports. + fn capabilities(&self) -> BackendCapabilities; + + /// Generate a proof from circuit inputs (full pipeline: witness + prove). + fn full_prove( + &self, + input: &CircuitSignals, + wasm_path: &Path, + pkey_path: &Path, + ) -> Result; + + /// Generate a proof from a pre-computed witness file. + fn prove( + &self, + witness_path: &Path, + r1cs_path: &Path, + pkey_path: &Path, + ) -> Result; + + /// Verify a proof against public signals and a verification key. + fn verify( + &self, + vkey: &serde_json::Value, + public_signals: &[String], + proof: &serde_json::Value, + ) -> Result; +} + +/// Trait for trusted setup operations. +pub trait SetupBackend { + /// Run trusted setup (phase-2 ceremony for Groth16, or direct setup for PLONK/FFLONK). + fn setup( + &self, + r1cs_path: &Path, + ptau_path: &Path, + pkey_path: &Path, + config: &ProverConfig, + ) -> Result<(), ProveError>; + + /// Export a verification key from a proving key. + fn export_vkey(&self, pkey_path: &Path, vkey_path: &Path) -> Result<(), ProveError>; + + /// Export a Solidity verifier contract from a proving key. + fn export_contract( + &self, + pkey_path: &Path, + sol_path: &Path, + protocol: Protocol, + ) -> Result<(), ProveError>; +} diff --git a/crates/circomkit-prove/src/types.rs b/crates/circomkit-prove/src/types.rs new file mode 100644 index 0000000..7eb4b89 --- /dev/null +++ b/crates/circomkit-prove/src/types.rs @@ -0,0 +1,11 @@ +use serde::{Deserialize, Serialize}; + +/// A proof output in snarkjs-compatible format. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ProofOutput { + /// Protocol-specific proof JSON (Groth16, PLONK, or FFLONK format). + pub proof: serde_json::Value, + /// Public signals as decimal strings. + pub public_signals: Vec, +} diff --git a/crates/circomkit-prove/tests/arkworks_integration.rs b/crates/circomkit-prove/tests/arkworks_integration.rs new file mode 100644 index 0000000..28cd0f2 --- /dev/null +++ b/crates/circomkit-prove/tests/arkworks_integration.rs @@ -0,0 +1,64 @@ +#![cfg(feature = "prove-arkworks")] + +use std::path::PathBuf; + +use circomkit_prove::{ArkworksBackend, ProofOutput, ProvingBackend}; + +fn test_data_dir() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../tests/data/multiplier_30") +} + +#[test] +fn arkworks_prove_with_binary_r1cs() { + let backend = ArkworksBackend; + let data = test_data_dir(); + + let ProofOutput { + proof, + public_signals, + } = backend + .prove( + &data.join("witness.wtns"), + &data.join("multiplier_30.r1cs"), + &data.join("groth16_pkey.zkey"), + ) + .expect("prove with binary r1cs should succeed"); + + // Unlike Lambdaworks, Arkworks reports only the circuit's public output: + // 2^30 = 1073741824. + assert_eq!(public_signals, vec!["1073741824"]); + + assert_eq!(proof["protocol"], "groth16"); + assert_eq!(proof["curve"], "bn128"); +} + +#[test] +fn arkworks_full_prove_unsupported() { + let backend = ArkworksBackend; + let data = test_data_dir(); + + let input = circomkit_core::signals! { + "in" => vec![2_i64; 30], + }; + + // Arkworks proves from a pre-computed witness; it does not run the witness + // calculator itself, so `full_prove` is not supported. + let result = backend.full_prove( + &input, + &data.join("multiplier_30.wasm"), + &data.join("groth16_pkey.zkey"), + ); + + assert!(result.is_err()); +} + +#[test] +fn arkworks_verify_from_json_unsupported() { + let backend = ArkworksBackend; + + // Native verification from snarkjs-format JSON is not implemented yet; + // verification should be delegated to snarkjs. + let result = backend.verify(&serde_json::json!({}), &[], &serde_json::json!({})); + + assert!(result.is_err()); +} diff --git a/crates/circomkit-prove/tests/backend_matrix.rs b/crates/circomkit-prove/tests/backend_matrix.rs new file mode 100644 index 0000000..d121d22 --- /dev/null +++ b/crates/circomkit-prove/tests/backend_matrix.rs @@ -0,0 +1,226 @@ +//! Cross-backend / cross-curve proving matrix. +//! +//! Two concerns are covered: +//! +//! 1. **Capability matrix** — every `(backend, protocol, curve)` request is +//! routed through [`make_proving_backend`], which must either return a +//! backend (supported, feature enabled), a `BackendNotEnabled` error +//! (supported, feature off), or a precise `UnsupportedProtocol` / +//! `UnsupportedCurve` error (unsupported). This part always runs. +//! +//! 2. **Real proofs** — for the combinations we have fixtures for, an actual +//! proof is generated with each backend on its native curve. These parts are +//! gated behind the relevant `prove-*` features (and snarkjs needs the +//! `snarkjs` CLI on PATH). + +use std::path::PathBuf; + +use circomkit_core::enums::{Prime, Protocol, ProvingBackendKind}; +use circomkit_prove::{ProveError, capabilities_for, make_proving_backend}; + +fn test_data_dir() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../tests/data/multiplier_30") +} + +const ALL_BACKENDS: &[ProvingBackendKind] = &[ + ProvingBackendKind::Snarkjs, + ProvingBackendKind::Lambdaworks, + ProvingBackendKind::Arkworks, +]; + +const ALL_PROTOCOLS: &[Protocol] = &[Protocol::Groth16, Protocol::Plonk, Protocol::Fflonk]; + +const ALL_PRIMES: &[Prime] = &[ + Prime::Bn128, + Prime::Bls12381, + Prime::Goldilocks, + Prime::Grumpkin, + Prime::Pallas, + Prime::Vesta, + Prime::Secq256r1, +]; + +/// Walk the entire grid and assert `make_proving_backend` agrees with the +/// capability table: unsupported combos error with a capability error, +/// supported combos either build or report the feature is disabled. +#[test] +fn capability_matrix_is_enforced() { + for &kind in ALL_BACKENDS { + let caps = capabilities_for(kind); + for &protocol in ALL_PROTOCOLS { + for &prime in ALL_PRIMES { + let result = make_proving_backend(kind, protocol, prime); + let supported = caps.supports(protocol, prime); + + match result { + Ok(backend) => { + assert!( + supported, + "{kind:?} built a backend for an unsupported ({protocol}, {prime})" + ); + // The constructed backend must report the same support. + assert!(backend.capabilities().supports(protocol, prime)); + } + Err(ProveError::BackendNotEnabled { .. }) => { + // Only valid when the combo is genuinely supported but + // the backend feature is compiled out. + assert!( + supported, + "{kind:?} reported BackendNotEnabled for unsupported ({protocol}, {prime})" + ); + } + Err(ProveError::UnsupportedProtocol { .. }) => { + assert!( + !caps.protocols.contains(&protocol), + "{kind:?} rejected protocol {protocol} that it claims to support" + ); + } + Err(ProveError::UnsupportedCurve { .. }) => { + assert!( + caps.protocols.contains(&protocol) && !caps.primes.contains(&prime), + "{kind:?} rejected curve {prime} unexpectedly" + ); + } + Err(e) => panic!("unexpected error for {kind:?} ({protocol}, {prime}): {e}"), + } + } + } + } +} + +/// Spot-check the specific examples called out in the design: the native +/// backends are Groth16-only and curve-specific. +#[test] +fn unsupported_combinations_give_clear_errors() { + // Lambdaworks: Groth16 + BLS12-381 only. + assert!(matches!( + make_proving_backend( + ProvingBackendKind::Lambdaworks, + Protocol::Plonk, + Prime::Bls12381 + ), + Err(ProveError::UnsupportedProtocol { + backend: "lambdaworks", + .. + }) + )); + assert!(matches!( + make_proving_backend( + ProvingBackendKind::Lambdaworks, + Protocol::Groth16, + Prime::Bn128 + ), + Err(ProveError::UnsupportedCurve { + backend: "lambdaworks", + .. + }) + )); + + // Arkworks: Groth16 + BN254 (bn128) only. + assert!(matches!( + make_proving_backend(ProvingBackendKind::Arkworks, Protocol::Fflonk, Prime::Bn128), + Err(ProveError::UnsupportedProtocol { + backend: "arkworks", + .. + }) + )); + assert!(matches!( + make_proving_backend( + ProvingBackendKind::Arkworks, + Protocol::Groth16, + Prime::Bls12381 + ), + Err(ProveError::UnsupportedCurve { + backend: "arkworks", + .. + }) + )); + + // snarkjs is universal — no capability error anywhere in the grid. + for &protocol in ALL_PROTOCOLS { + for &prime in ALL_PRIMES { + assert!( + make_proving_backend(ProvingBackendKind::Snarkjs, protocol, prime).is_ok(), + "snarkjs should support ({protocol}, {prime})" + ); + } + } +} + +/// Arkworks proves Groth16 over BN254 from a snarkjs `.zkey` + witness. +#[cfg(feature = "prove-arkworks")] +#[test] +fn arkworks_groth16_bn254_proves() { + let data = test_data_dir(); + let backend = make_proving_backend( + ProvingBackendKind::Arkworks, + Protocol::Groth16, + Prime::Bn128, + ) + .expect("arkworks backend should build"); + + let output = backend + .prove( + &data.join("witness.wtns"), + &data.join("multiplier_30.r1cs"), + &data.join("groth16_pkey.zkey"), + ) + .expect("arkworks prove should succeed"); + + assert_eq!(output.proof["protocol"], "groth16"); + assert_eq!(output.proof["curve"], "bn128"); + // multiplier_30 over 2 thirty times => 2^30 = 1073741824 is the public output. + assert_eq!(output.public_signals, vec!["1073741824"]); +} + +/// Lambdaworks proves Groth16 over BLS12-381 with an on-the-fly setup. +#[cfg(feature = "prove-lambdaworks")] +#[test] +fn lambdaworks_groth16_bls12381_proves() { + let data = test_data_dir(); + let backend = make_proving_backend( + ProvingBackendKind::Lambdaworks, + Protocol::Groth16, + Prime::Bls12381, + ) + .expect("lambdaworks backend should build"); + + let output = backend + .prove( + &data.join("witness.wtns"), + &data.join("multiplier_30.r1cs"), + &data.join("unused.zkey"), + ) + .expect("lambdaworks prove should succeed"); + + assert_eq!(output.proof["protocol"], "groth16"); + assert_eq!(output.proof["curve"], "bls12381"); + // Lambdaworks includes the constant "1" wire ahead of the output. + assert_eq!(output.public_signals, vec!["1", "1073741824"]); +} + +/// snarkjs proves Groth16 over BN254 via the CLI (needs `snarkjs` on PATH). +#[test] +fn snarkjs_groth16_bn254_proves() { + let data = test_data_dir(); + let zkey = data.join("groth16_pkey.zkey"); + let wasm = data.join("multiplier_30.wasm"); + if !zkey.exists() || !wasm.exists() { + eprintln!("skipping: snarkjs fixtures missing"); + return; + } + + let backend = + make_proving_backend(ProvingBackendKind::Snarkjs, Protocol::Groth16, Prime::Bn128) + .expect("snarkjs backend should build"); + + let input = circomkit_core::signals! { "in" => vec![2_i64; 30] }; + + match backend.full_prove(&input, &wasm, &zkey) { + Ok(output) => { + assert_eq!(output.proof["protocol"], "groth16"); + assert_eq!(output.public_signals, vec!["1073741824"]); + } + Err(e) => eprintln!("skipping snarkjs assertion (snarkjs CLI unavailable?): {e}"), + } +} diff --git a/crates/circomkit-prove/tests/lambdaworks_integration.rs b/crates/circomkit-prove/tests/lambdaworks_integration.rs new file mode 100644 index 0000000..dffd10c --- /dev/null +++ b/crates/circomkit-prove/tests/lambdaworks_integration.rs @@ -0,0 +1,73 @@ +#![cfg(feature = "prove-lambdaworks")] + +use std::path::PathBuf; + +use circomkit_prove::{LambdaworksBackend, ProofOutput, ProvingBackend}; + +fn test_data_dir() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../tests/data/multiplier_30") +} + +#[test] +fn lambdaworks_prove_with_binary_r1cs() { + let backend = LambdaworksBackend; + let data = test_data_dir(); + + let ProofOutput { + proof, + public_signals, + } = backend + .prove( + &data.join("witness.wtns"), + &data.join("multiplier_30.r1cs"), + &data.join("unused.zkey"), // pkey_path is unused by Lambdaworks + ) + .expect("prove with binary r1cs should succeed"); + + // Lambdaworks includes the constant wire "1" as the first public signal, + // followed by the actual output: 2^30 = 1073741824 + assert_eq!(public_signals, vec!["1", "1073741824"]); + + assert_eq!(proof["protocol"], "groth16"); + assert_eq!(proof["curve"], "bls12381"); +} + +#[test] +fn lambdaworks_prove_with_json_r1cs() { + let backend = LambdaworksBackend; + let data = test_data_dir(); + + let ProofOutput { + proof, + public_signals, + } = backend + .prove( + &data.join("witness.wtns"), + &data.join("multiplier_30.r1cs.json"), + &data.join("unused.zkey"), + ) + .expect("prove with json r1cs should succeed"); + + assert_eq!(public_signals, vec!["1", "1073741824"]); + + assert_eq!(proof["protocol"], "groth16"); + assert_eq!(proof["curve"], "bls12381"); +} + +#[test] +fn lambdaworks_full_prove_unsupported() { + let backend = LambdaworksBackend; + let data = test_data_dir(); + + let input = circomkit_core::signals! { + "in" => vec![2_i64; 30], + }; + + let result = backend.full_prove( + &input, + &data.join("multiplier_30.wasm"), + &data.join("unused.zkey"), + ); + + assert!(result.is_err()); +} diff --git a/crates/circomkit-prove/tests/snarkjs_integration.rs b/crates/circomkit-prove/tests/snarkjs_integration.rs new file mode 100644 index 0000000..aa53c5e --- /dev/null +++ b/crates/circomkit-prove/tests/snarkjs_integration.rs @@ -0,0 +1,76 @@ +use std::path::PathBuf; + +use circomkit_core::signals; +use circomkit_prove::{ProofOutput, ProvingBackend, SnarkjsBackend}; + +fn test_data_dir() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../tests/data/multiplier_30") +} + +#[test] +fn snarkjs_full_prove_and_verify() { + let backend = SnarkjsBackend::default(); + let data = test_data_dir(); + + let input = signals! { + "in" => vec![2_i64; 30], + }; + + let ProofOutput { + proof, + public_signals, + } = backend + .full_prove( + &input, + &data.join("multiplier_30.wasm"), + &data.join("groth16_pkey.zkey"), + ) + .expect("full_prove should succeed"); + + // Output should be 2^30 = 1073741824 + assert_eq!(public_signals, vec!["1073741824"]); + + // Proof should have the groth16 structure + assert_eq!(proof["protocol"], "groth16"); + + // Verify with the vkey + let vkey: serde_json::Value = + serde_json::from_str(&std::fs::read_to_string(data.join("groth16_vkey.json")).unwrap()) + .unwrap(); + + let ok = backend + .verify(&vkey, &public_signals, &proof) + .expect("verify should not error"); + assert!(ok, "proof should verify"); +} + +#[test] +fn snarkjs_verify_rejects_bad_proof() { + let backend = SnarkjsBackend::default(); + let data = test_data_dir(); + + let input = signals! { + "in" => vec![2_i64; 30], + }; + + let ProofOutput { + proof, + mut public_signals, + } = backend + .full_prove( + &input, + &data.join("multiplier_30.wasm"), + &data.join("groth16_pkey.zkey"), + ) + .unwrap(); + + // Tamper with public signals + public_signals[0] = "999".to_string(); + + let vkey: serde_json::Value = + serde_json::from_str(&std::fs::read_to_string(data.join("groth16_vkey.json")).unwrap()) + .unwrap(); + + let ok = backend.verify(&vkey, &public_signals, &proof).unwrap(); + assert!(!ok, "tampered proof should not verify"); +} diff --git a/crates/circomkit-test/Cargo.toml b/crates/circomkit-test/Cargo.toml new file mode 100644 index 0000000..9c2ef1e --- /dev/null +++ b/crates/circomkit-test/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "circomkit-test" +description = "Testing utilities for Circom circuits" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +circomkit-core.workspace = true +circomkit-witness.workspace = true +circomkit-prove.workspace = true +thiserror.workspace = true +log.workspace = true +serde_json.workspace = true +num-bigint.workspace = true diff --git a/crates/circomkit-test/src/error.rs b/crates/circomkit-test/src/error.rs new file mode 100644 index 0000000..a6be312 --- /dev/null +++ b/crates/circomkit-test/src/error.rs @@ -0,0 +1,43 @@ +/// Errors that can occur during circuit testing. +#[derive(Debug, thiserror::Error)] +pub enum TestError { + #[error("expected witness computation to fail, but it succeeded")] + ExpectedFailure, + + #[error("expected at least {expected} constraints, got {actual}")] + UnderConstrained { expected: u32, actual: u32 }, + + #[error("expected exactly {expected} constraints, got {actual}")] + ConstraintCountMismatch { expected: u32, actual: u32 }, + + #[error("expected constraints to fail, but they passed")] + ExpectedConstraintFailure, + + #[error("output mismatch for signal '{signal}': expected {expected}, got {actual}")] + OutputMismatch { + signal: String, + expected: String, + actual: String, + }, + + #[error("verification expected to pass, but failed")] + VerificationExpectedPass, + + #[error("verification expected to fail, but passed")] + VerificationExpectedFail, + + #[error(transparent)] + Io(#[from] std::io::Error), + + #[error(transparent)] + Json(#[from] serde_json::Error), + + #[error(transparent)] + Witness(#[from] circomkit_witness::WitnessError), + + #[error(transparent)] + Prove(#[from] circomkit_prove::ProveError), + + #[error(transparent)] + Core(#[from] circomkit_core::error::CoreError), +} diff --git a/crates/circomkit-test/src/lib.rs b/crates/circomkit-test/src/lib.rs new file mode 100644 index 0000000..fb84c4b --- /dev/null +++ b/crates/circomkit-test/src/lib.rs @@ -0,0 +1,7 @@ +mod error; +mod proof_tester; +mod witness_tester; + +pub use error::TestError; +pub use proof_tester::ProofTester; +pub use witness_tester::WitnessTester; diff --git a/crates/circomkit-test/src/proof_tester.rs b/crates/circomkit-test/src/proof_tester.rs new file mode 100644 index 0000000..85b50fd --- /dev/null +++ b/crates/circomkit-test/src/proof_tester.rs @@ -0,0 +1,80 @@ +use std::path::PathBuf; + +use circomkit_core::enums::Protocol; +use circomkit_core::types::CircuitSignals; +use circomkit_prove::ProofOutput; +use circomkit_prove::ProvingBackend; + +use crate::error::TestError; + +/// A circuit tester focused on proof-level testing. +pub struct ProofTester { + backend: Box, + wasm_path: PathBuf, + pkey_path: PathBuf, + /// The parsed verification key. + pub vkey: serde_json::Value, + /// The protocol used for proofs. + pub protocol: Protocol, +} + +impl ProofTester { + pub fn new( + backend: Box, + wasm_path: PathBuf, + pkey_path: PathBuf, + vkey_path: PathBuf, + protocol: Protocol, + ) -> Result { + let vkey_str = std::fs::read_to_string(&vkey_path)?; + let vkey: serde_json::Value = serde_json::from_str(&vkey_str)?; + + Ok(Self { + backend, + wasm_path, + pkey_path, + vkey, + protocol, + }) + } + + /// Generate a proof from circuit inputs. + pub fn prove(&self, input: &CircuitSignals) -> Result { + Ok(self + .backend + .full_prove(input, &self.wasm_path, &self.pkey_path)?) + } + + /// Verify a proof. + pub fn verify( + &self, + proof: &serde_json::Value, + public_signals: &[String], + ) -> Result { + Ok(self.backend.verify(&self.vkey, public_signals, proof)?) + } + + /// Assert that verification passes. + pub fn expect_pass( + &self, + proof: &serde_json::Value, + public_signals: &[String], + ) -> Result<(), TestError> { + if !self.verify(proof, public_signals)? { + return Err(TestError::VerificationExpectedPass); + } + Ok(()) + } + + /// Assert that verification fails. + pub fn expect_fail( + &self, + proof: &serde_json::Value, + public_signals: &[String], + ) -> Result<(), TestError> { + if self.verify(proof, public_signals)? { + return Err(TestError::VerificationExpectedFail); + } + Ok(()) + } +} diff --git a/crates/circomkit-test/src/witness_tester.rs b/crates/circomkit-test/src/witness_tester.rs new file mode 100644 index 0000000..e8f01fc --- /dev/null +++ b/crates/circomkit-test/src/witness_tester.rs @@ -0,0 +1,176 @@ +use std::collections::HashMap; +use std::path::PathBuf; +use std::sync::{Mutex, OnceLock}; + +use num_bigint::BigInt; + +use circomkit_core::functions::{edit_witness, parse_symbols, read_witness_signals}; +use circomkit_core::types::{CircuitSignals, R1CSInfo, Symbols, Witness}; +use circomkit_core::utils::read_r1cs_info; +use circomkit_witness::WitnessCalculator; + +use crate::error::TestError; + +/// A circuit tester focused on witness-level testing. +/// +/// Supports computing witnesses, checking outputs, asserting failures, +/// reading signals, editing witnesses for soundness testing, and +/// inspecting constraint counts. +pub struct WitnessTester { + calculator: Box, + symbols: OnceLock>>, + r1cs_info: OnceLock>>, + r1cs_path: PathBuf, + sym_path: PathBuf, +} + +impl WitnessTester { + pub fn new( + calculator: Box, + r1cs_path: PathBuf, + sym_path: PathBuf, + ) -> Self { + Self { + calculator, + symbols: OnceLock::new(), + r1cs_info: OnceLock::new(), + r1cs_path, + sym_path, + } + } + + /// Compute a witness from input signals. + pub fn calculate_witness(&self, input: &CircuitSignals) -> Result { + Ok(self.calculator.calculate(input)?) + } + + /// Get R1CS info (lazily loaded). + pub fn r1cs_info(&self) -> Result { + let mutex = self.r1cs_info.get_or_init(|| Mutex::new(None)); + let mut guard = mutex.lock().unwrap(); + if guard.is_none() { + *guard = Some(read_r1cs_info(&self.r1cs_path)?); + } + Ok(guard.as_ref().unwrap().clone()) + } + + /// Get the symbol table (lazily loaded). + pub fn symbols(&self) -> Result { + let mutex = self.symbols.get_or_init(|| Mutex::new(None)); + let mut guard = mutex.lock().unwrap(); + if guard.is_none() { + *guard = Some(parse_symbols(&self.sym_path)?); + } + Ok(guard.as_ref().unwrap().clone()) + } + + /// Get the constraint count. + pub fn constraint_count(&self) -> Result { + Ok(self.r1cs_info()?.constraints) + } + + /// Assert the constraint count. + /// + /// If `exact` is true, asserts equality. Otherwise asserts `actual >= expected`. + pub fn expect_constraint_count(&self, expected: u32, exact: bool) -> Result<(), TestError> { + let actual = self.constraint_count()?; + if exact && actual != expected { + return Err(TestError::ConstraintCountMismatch { expected, actual }); + } + if !exact && actual < expected { + return Err(TestError::UnderConstrained { expected, actual }); + } + Ok(()) + } + + /// Expect the input to produce a valid witness. + /// + /// If `output` is provided, also checks that the output signals match. + pub fn expect_pass( + &self, + input: &CircuitSignals, + output: Option<&CircuitSignals>, + ) -> Result<(), TestError> { + let witness = self.calculate_witness(input)?; + + if let Some(expected) = output { + let symbols = self.symbols()?; + let signal_names: Vec<&str> = expected.keys().map(|s| s.as_str()).collect(); + let actual = read_witness_signals(&witness, &symbols, &signal_names)?; + + for (name, expected_val) in expected { + let actual_val = actual.get(name).ok_or_else(|| TestError::OutputMismatch { + signal: name.clone(), + expected: format!("{expected_val:?}"), + actual: "not found".to_string(), + })?; + + if expected_val != actual_val { + return Err(TestError::OutputMismatch { + signal: name.clone(), + expected: format!("{expected_val:?}"), + actual: format!("{actual_val:?}"), + }); + } + } + } + + Ok(()) + } + + /// Expect witness computation to fail with a circuit error. + /// + /// Returns the error message on success. + pub fn expect_fail(&self, input: &CircuitSignals) -> Result { + match self.calculator.calculate(input) { + Err(e) if e.is_circuit_error() => Ok(e.to_string()), + Err(e) => Err(TestError::Witness(e)), + Ok(_) => Err(TestError::ExpectedFailure), + } + } + + /// Compute a witness and read specific output signals. + pub fn compute( + &self, + input: &CircuitSignals, + signals: &[&str], + ) -> Result { + let witness = self.calculate_witness(input)?; + let symbols = self.symbols()?; + Ok(read_witness_signals(&witness, &symbols, signals)?) + } + + /// Read signal values from a pre-computed witness. + pub fn read_witness_signals( + &self, + witness: &Witness, + signals: &[&str], + ) -> Result { + let symbols = self.symbols()?; + Ok(read_witness_signals(witness, &symbols, signals)?) + } + + /// Read raw symbol values from a witness by full symbol names. + pub fn read_witness( + &self, + witness: &Witness, + symbol_names: &[&str], + ) -> Result, TestError> { + let symbols = self.symbols()?; + Ok(circomkit_core::functions::read_witness_raw( + witness, + &symbols, + symbol_names, + )?) + } + + /// Edit witness values by symbol name (for soundness testing). + pub fn edit_witness( + &self, + witness: &Witness, + overrides: &HashMap, + ) -> Result { + let symbols = self.symbols()?; + Ok(edit_witness(witness, &symbols, overrides)?) + } +} diff --git a/crates/circomkit-witness/Cargo.toml b/crates/circomkit-witness/Cargo.toml new file mode 100644 index 0000000..253a0b0 --- /dev/null +++ b/crates/circomkit-witness/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "circomkit-witness" +description = "Witness calculator trait and backends for Circomkit" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +circomkit-core.workspace = true +thiserror.workspace = true +log.workspace = true +serde_json.workspace = true +num-bigint.workspace = true +num-traits.workspace = true + +[dependencies.wasmtime] +workspace = true +optional = true + +[features] +default = ["witness-wasm"] +witness-wasm = ["dep:wasmtime"] +witness-c = [] diff --git a/crates/circomkit-witness/src/error.rs b/crates/circomkit-witness/src/error.rs new file mode 100644 index 0000000..1c7de7a --- /dev/null +++ b/crates/circomkit-witness/src/error.rs @@ -0,0 +1,35 @@ +/// Errors that can occur during witness calculation. +#[derive(Debug, thiserror::Error)] +pub enum WitnessError { + #[error("assertion failed in circuit: {0}")] + AssertionFailed(String), + + #[error("not enough values for input signal: {0}")] + NotEnoughInputs(String), + + #[error("too many values for input signal: {0}")] + TooManyInputs(String), + + #[error("not all inputs have been set")] + MissingInputs, + + #[error(transparent)] + Io(#[from] std::io::Error), + + #[error("{0}")] + Other(String), +} + +impl WitnessError { + /// Returns `true` if this is an expected circuit-level failure + /// (assertion, input mismatch) rather than an infrastructure error. + pub fn is_circuit_error(&self) -> bool { + matches!( + self, + Self::AssertionFailed(_) + | Self::NotEnoughInputs(_) + | Self::TooManyInputs(_) + | Self::MissingInputs + ) + } +} diff --git a/crates/circomkit-witness/src/factory.rs b/crates/circomkit-witness/src/factory.rs new file mode 100644 index 0000000..6c819f7 --- /dev/null +++ b/crates/circomkit-witness/src/factory.rs @@ -0,0 +1,34 @@ +use std::path::Path; + +use circomkit_core::enums::WitnessBackend; + +use crate::WitnessCalculator; +use crate::WitnessError; + +/// Create the appropriate witness calculator based on the configured backend. +pub fn make_witness_calculator( + backend: WitnessBackend, + wasm_path: &Path, + _c_binary_path: Option<&Path>, +) -> Result, WitnessError> { + match backend { + #[cfg(feature = "witness-wasm")] + WitnessBackend::Wasm => { + let calc = crate::wasm::WasmWitnessCalculator::new(wasm_path.to_path_buf())?; + Ok(Box::new(calc)) + } + + #[cfg(feature = "witness-c")] + WitnessBackend::C => { + let _ = (_c_binary_path, wasm_path); + Err(WitnessError::Other( + "C witness calculator not yet implemented".to_string(), + )) + } + + #[allow(unreachable_patterns)] + _ => Err(WitnessError::Other(format!( + "witness backend '{backend:?}' is not enabled via feature flags" + ))), + } +} diff --git a/crates/circomkit-witness/src/lib.rs b/crates/circomkit-witness/src/lib.rs new file mode 100644 index 0000000..bdc7c4a --- /dev/null +++ b/crates/circomkit-witness/src/lib.rs @@ -0,0 +1,13 @@ +mod error; +mod factory; +mod traits; + +#[cfg(feature = "witness-wasm")] +mod wasm; + +pub use error::WitnessError; +pub use factory::make_witness_calculator; +pub use traits::WitnessCalculator; + +#[cfg(feature = "witness-wasm")] +pub use wasm::WasmWitnessCalculator; diff --git a/crates/circomkit-witness/src/traits.rs b/crates/circomkit-witness/src/traits.rs new file mode 100644 index 0000000..47a2259 --- /dev/null +++ b/crates/circomkit-witness/src/traits.rs @@ -0,0 +1,9 @@ +use circomkit_core::types::{CircuitSignals, Witness}; + +use crate::WitnessError; + +/// Trait for witness calculators that compute a witness from circuit inputs. +pub trait WitnessCalculator { + /// Calculate a witness from circuit input signals. + fn calculate(&self, input: &CircuitSignals) -> Result; +} diff --git a/crates/circomkit-witness/src/wasm.rs b/crates/circomkit-witness/src/wasm.rs new file mode 100644 index 0000000..6ca0ac6 --- /dev/null +++ b/crates/circomkit-witness/src/wasm.rs @@ -0,0 +1,481 @@ +use std::path::PathBuf; + +use num_bigint::BigInt; +use num_traits::Zero; +use wasmtime::{Engine, Instance, Linker, Module, Store}; + +use circomkit_core::types::{CircuitSignals, SignalValue, Witness}; + +use crate::error::WitnessError; +use crate::traits::WitnessCalculator; + +/// WASM-based witness calculator using wasmtime. +/// +/// Loads a circom-generated WASM module and implements the circom +/// witness calculation protocol (shared RW memory, FNV signal hashing, etc.). +pub struct WasmWitnessCalculator { + wasm_path: PathBuf, +} + +impl WasmWitnessCalculator { + pub fn new(wasm_path: PathBuf) -> Result { + if !wasm_path.exists() { + return Err(WitnessError::Other(format!( + "WASM file not found: {}", + wasm_path.display() + ))); + } + Ok(Self { wasm_path }) + } +} + +/// State stored inside the wasmtime Store, shared with host functions. +#[derive(Default)] +struct HostState { + error_message: String, + log_buffer: String, + exception: Option, +} + +impl WitnessCalculator for WasmWitnessCalculator { + fn calculate(&self, input: &CircuitSignals) -> Result { + let engine = Engine::default(); + let module = Module::from_file(&engine, &self.wasm_path) + .map_err(|e| WitnessError::Other(format!("failed to load WASM module: {e}")))?; + + let mut linker = Linker::::new(&engine); + + // Register circom runtime host functions + linker + .func_wrap( + "runtime", + "exceptionHandler", + |mut caller: wasmtime::Caller<'_, HostState>, code: i32| { + caller.data_mut().exception = Some(code as u32); + }, + ) + .map_err(|e| WitnessError::Other(format!("linker error: {e}")))?; + + linker + .func_wrap( + "runtime", + "printErrorMessage", + |mut caller: wasmtime::Caller<'_, HostState>| { + let msg = get_message_from_wasm(&mut caller); + let state = caller.data_mut(); + state.error_message.push_str(&msg); + state.error_message.push('\n'); + }, + ) + .map_err(|e| WitnessError::Other(format!("linker error: {e}")))?; + + linker + .func_wrap( + "runtime", + "writeBufferMessage", + |mut caller: wasmtime::Caller<'_, HostState>| { + let msg = get_message_from_wasm(&mut caller); + let state = caller.data_mut(); + if msg == "\n" { + log::info!("{}", state.log_buffer); + state.log_buffer.clear(); + } else { + if !state.log_buffer.is_empty() { + state.log_buffer.push(' '); + } + state.log_buffer.push_str(&msg); + } + }, + ) + .map_err(|e| WitnessError::Other(format!("linker error: {e}")))?; + + linker + .func_wrap( + "runtime", + "showSharedRWMemory", + |_caller: wasmtime::Caller<'_, HostState>| { + // Debug callback — no-op in production + }, + ) + .map_err(|e| WitnessError::Other(format!("linker error: {e}")))?; + + let mut store = Store::new(&engine, HostState::default()); + + let instance = linker + .instantiate(&mut store, &module) + .map_err(|e| WitnessError::Other(format!("WASM instantiation failed: {e}")))?; + + // Get metadata + let n32 = call_i32(&instance, &mut store, "getFieldNumLen32")? as usize; + let witness_size = call_i32(&instance, &mut store, "getWitnessSize")? as usize; + let input_size = call_i32(&instance, &mut store, "getInputSize")? as usize; + + // Read the prime + call_void(&instance, &mut store, "getRawPrime", &[])?; + let prime = read_shared_field_element(&instance, &mut store, n32)?; + + // Initialize + call_void(&instance, &mut store, "init", &[wasmtime::Val::I32(1)])?; + check_exception(&mut store)?; + + // Flatten and set all input signals + let mut input_counter = 0usize; + for (name, value) in input { + let (h_msb, h_lsb) = fnv_hash(name); + + // Get expected signal size from the circuit + let signal_size = call_export_i32( + &instance, + &mut store, + "getInputSignalSize", + &[ + wasmtime::Val::I32(h_msb as i32), + wasmtime::Val::I32(h_lsb as i32), + ], + )?; + + if signal_size < 0 { + return Err(WitnessError::Other(format!("signal not found: {name}"))); + } + let signal_size = signal_size as usize; + + let flat = flatten_signal(value); + + if flat.len() < signal_size { + return Err(WitnessError::NotEnoughInputs(name.clone())); + } + if flat.len() > signal_size { + return Err(WitnessError::TooManyInputs(name.clone())); + } + + for (i, val) in flat.iter().enumerate() { + let normalized = normalize(val, &prime); + let limbs = bigint_to_u32_array(&normalized, n32); + + // Write to shared RW memory: index j gets limbs[n32-1-j] + for j in 0..n32 { + let write_fn = instance + .get_func(&mut store, "writeSharedRWMemory") + .ok_or_else(|| { + WitnessError::Other("writeSharedRWMemory not found".to_string()) + })?; + write_fn + .call( + &mut store, + &[ + wasmtime::Val::I32(j as i32), + wasmtime::Val::I32(limbs[n32 - 1 - j] as i32), + ], + &mut [], + ) + .map_err(|e| { + WitnessError::Other(format!("writeSharedRWMemory failed: {e}")) + })?; + } + + // Set the input signal + let result = call_void( + &instance, + &mut store, + "setInputSignal", + &[ + wasmtime::Val::I32(h_msb as i32), + wasmtime::Val::I32(h_lsb as i32), + wasmtime::Val::I32(i as i32), + ], + ); + + if let Err(e) = result { + check_exception(&mut store)?; + return Err(WitnessError::Other(format!("setInputSignal failed: {e}"))); + } + + check_exception(&mut store)?; + input_counter += 1; + } + } + + if input_counter < input_size { + return Err(WitnessError::MissingInputs); + } + + // Read witness + let mut witness = Vec::with_capacity(witness_size); + for i in 0..witness_size { + let get_witness_fn = instance + .get_func(&mut store, "getWitness") + .ok_or_else(|| WitnessError::Other("getWitness not found".to_string()))?; + get_witness_fn + .call(&mut store, &[wasmtime::Val::I32(i as i32)], &mut []) + .map_err(|e| WitnessError::Other(format!("getWitness failed: {e}")))?; + + let val = read_shared_field_element(&instance, &mut store, n32)?; + witness.push(val); + } + + Ok(witness) + } +} + +// ---- Helper functions ---- + +/// FNV-1a 64-bit hash of a string, returning (MSB_u32, LSB_u32). +fn fnv_hash(s: &str) -> (u32, u32) { + let mut hash: u64 = 0xCBF2_9CE4_8422_2325; + for byte in s.bytes() { + hash ^= byte as u64; + hash = hash.wrapping_mul(0x0100_0000_01B3); + } + let msb = (hash >> 32) as u32; + let lsb = hash as u32; + (msb, lsb) +} + +/// Normalize a BigInt modulo prime (result in [0, prime)). +fn normalize(val: &BigInt, prime: &BigInt) -> BigInt { + let r = val % prime; + if r < BigInt::zero() { r + prime } else { r } +} + +/// Convert a non-negative BigInt into a big-endian array of `size` u32 limbs. +fn bigint_to_u32_array(val: &BigInt, size: usize) -> Vec { + let mut res = vec![0u32; size]; + let radix = BigInt::from(0x1_0000_0000u64); + let mut rem = val.clone(); + + for limb in res.iter_mut().rev() { + if rem.is_zero() { + break; + } + let (q, r) = num_integer_div_rem(&rem, &radix); + *limb = bigint_to_u32(&r); + rem = q; + } + + res +} + +fn num_integer_div_rem(a: &BigInt, b: &BigInt) -> (BigInt, BigInt) { + use num_traits::Signed; + let q = a / b; + let r = a - &q * b; + if r.is_negative() { + (q - BigInt::from(1), r + b) + } else { + (q, r) + } +} + +fn bigint_to_u32(val: &BigInt) -> u32 { + let (_, bytes) = val.to_bytes_le(); + let mut buf = [0u8; 4]; + let len = bytes.len().min(4); + buf[..len].copy_from_slice(&bytes[..len]); + u32::from_le_bytes(buf) +} + +/// Read a field element from shared RW memory as a BigInt. +fn read_shared_field_element( + instance: &Instance, + store: &mut Store, + n32: usize, +) -> Result { + let mut arr = vec![0u32; n32]; + let mut results = [wasmtime::Val::I32(0)]; + for j in 0..n32 { + let read_fn = instance + .get_func(&mut *store, "readSharedRWMemory") + .ok_or_else(|| WitnessError::Other("readSharedRWMemory not found".to_string()))?; + read_fn + .call(&mut *store, &[wasmtime::Val::I32(j as i32)], &mut results) + .map_err(|e| WitnessError::Other(format!("readSharedRWMemory failed: {e}")))?; + arr[n32 - 1 - j] = results[0].unwrap_i32() as u32; + } + + Ok(from_u32_array_be(&arr)) +} + +/// Convert a big-endian u32 array to BigInt. +fn from_u32_array_be(arr: &[u32]) -> BigInt { + let mut result = BigInt::zero(); + let radix = BigInt::from(0x1_0000_0000u64); + for &limb in arr { + result = result * &radix + BigInt::from(limb); + } + result +} + +/// Flatten a SignalValue into a list of BigInt values. +fn flatten_signal(value: &SignalValue) -> Vec { + match value { + SignalValue::Single(v) => vec![v.clone()], + SignalValue::Array(arr) => arr.iter().flat_map(flatten_signal).collect(), + } +} + +/// Get the message string from WASM by repeatedly calling `getMessageChar`. +fn get_message_from_wasm(caller: &mut wasmtime::Caller<'_, HostState>) -> String { + let get_char = match caller.get_export("getMessageChar") { + Some(wasmtime::Extern::Func(f)) => f, + _ => return String::new(), + }; + + let mut msg = String::new(); + let mut results = [wasmtime::Val::I32(0)]; + loop { + if get_char.call(&mut *caller, &[], &mut results).is_err() { + break; + } + let c = results[0].unwrap_i32() as u32; + if c == 0 { + break; + } + if let Some(ch) = char::from_u32(c) { + msg.push(ch); + } + } + msg +} + +/// Check if the WASM module raised an exception via the host state. +fn check_exception(store: &mut Store) -> Result<(), WitnessError> { + let state = store.data(); + if let Some(code) = state.exception { + let detail = if state.error_message.is_empty() { + String::new() + } else { + format!(": {}", state.error_message.trim()) + }; + + // Reset + store.data_mut().exception = None; + store.data_mut().error_message.clear(); + + match code { + 1 => Err(WitnessError::Other(format!("signal not found{detail}"))), + 2 => Err(WitnessError::Other(format!("too many signals set{detail}"))), + 3 => Err(WitnessError::Other(format!("signal already set{detail}"))), + 4 => Err(WitnessError::AssertionFailed(format!( + "assert failed{detail}" + ))), + 5 => Err(WitnessError::Other(format!("not enough memory{detail}"))), + 6 => Err(WitnessError::Other(format!( + "input signal array access exceeds size{detail}" + ))), + _ => Err(WitnessError::Other(format!( + "unknown WASM error (code {code}){detail}" + ))), + } + } else { + Ok(()) + } +} + +// ---- Convenience wrappers for calling WASM exports ---- + +fn call_void( + instance: &Instance, + store: &mut Store, + name: &str, + args: &[wasmtime::Val], +) -> Result<(), WitnessError> { + let func = instance + .get_func(&mut *store, name) + .ok_or_else(|| WitnessError::Other(format!("WASM export '{name}' not found")))?; + func.call(&mut *store, args, &mut []) + .map_err(|e| WitnessError::Other(format!("{name} failed: {e}")))?; + Ok(()) +} + +fn call_i32( + instance: &Instance, + store: &mut Store, + name: &str, +) -> Result { + call_export_i32(instance, store, name, &[]) +} + +fn call_export_i32( + instance: &Instance, + store: &mut Store, + name: &str, + args: &[wasmtime::Val], +) -> Result { + let func = instance + .get_func(&mut *store, name) + .ok_or_else(|| WitnessError::Other(format!("WASM export '{name}' not found")))?; + let mut results = [wasmtime::Val::I32(0)]; + func.call(&mut *store, args, &mut results) + .map_err(|e| WitnessError::Other(format!("{name} failed: {e}")))?; + Ok(results[0].unwrap_i32()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn fnv_hash_known_values() { + let (msb, lsb) = fnv_hash("in"); + assert_ne!(msb, 0); + assert_ne!(lsb, 0); + + // Same input must produce same hash + let (msb2, lsb2) = fnv_hash("in"); + assert_eq!(msb, msb2); + assert_eq!(lsb, lsb2); + + // Different inputs produce different hashes + let (msb3, lsb3) = fnv_hash("out"); + assert!(msb != msb3 || lsb != lsb3); + } + + #[test] + fn bigint_to_array_roundtrip() { + let val = BigInt::from(12345678u64); + let arr = bigint_to_u32_array(&val, 8); + let back = from_u32_array_be(&arr); + assert_eq!(val, back); + } + + #[test] + fn bigint_to_array_large() { + let val = BigInt::from(u64::MAX); + let arr = bigint_to_u32_array(&val, 8); + let back = from_u32_array_be(&arr); + assert_eq!(val, back); + } + + #[test] + fn bigint_to_array_zero() { + let val = BigInt::zero(); + let arr = bigint_to_u32_array(&val, 8); + assert!(arr.iter().all(|&x| x == 0)); + let back = from_u32_array_be(&arr); + assert_eq!(val, back); + } + + #[test] + fn flatten_nested_signal() { + let sig = SignalValue::Array(vec![ + SignalValue::Single(BigInt::from(1)), + SignalValue::Array(vec![ + SignalValue::Single(BigInt::from(2)), + SignalValue::Single(BigInt::from(3)), + ]), + ]); + let flat = flatten_signal(&sig); + assert_eq!( + flat, + vec![BigInt::from(1), BigInt::from(2), BigInt::from(3)] + ); + } + + #[test] + fn normalize_negative() { + let prime = BigInt::from(7); + assert_eq!(normalize(&BigInt::from(-1), &prime), BigInt::from(6)); + assert_eq!(normalize(&BigInt::from(0), &prime), BigInt::from(0)); + assert_eq!(normalize(&BigInt::from(10), &prime), BigInt::from(3)); + } +} diff --git a/crates/circomkit-witness/tests/wasm_integration.rs b/crates/circomkit-witness/tests/wasm_integration.rs new file mode 100644 index 0000000..f73ae08 --- /dev/null +++ b/crates/circomkit-witness/tests/wasm_integration.rs @@ -0,0 +1,62 @@ +#[cfg(feature = "witness-wasm")] +mod tests { + use std::path::PathBuf; + + use circomkit_core::signals; + use circomkit_witness::{WasmWitnessCalculator, WitnessCalculator}; + use num_bigint::BigInt; + + fn test_data_dir() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../tests/data/multiplier_30") + } + + fn wasm_path() -> PathBuf { + test_data_dir().join("multiplier_30.wasm") + } + + #[test] + fn calculate_witness_multiplier_30() { + let calc = WasmWitnessCalculator::new(wasm_path()).unwrap(); + + // 30 inputs of 2 => output = 2^30 = 1073741824 + let input = signals! { + "in" => vec![2_i64; 30], + }; + + let witness = calc.calculate(&input).unwrap(); + + // witness[0] is always 1 (the "one" wire) + assert_eq!(witness[0], BigInt::from(1)); + + // witness[1] should be the output: 2^30 + assert_eq!(witness[1], BigInt::from(1073741824u64)); + + assert!(witness.len() > 30); + } + + #[test] + fn calculate_witness_all_ones() { + let calc = WasmWitnessCalculator::new(wasm_path()).unwrap(); + + let input = signals! { + "in" => vec![1_i64; 30], + }; + + let witness = calc.calculate(&input).unwrap(); + assert_eq!(witness[0], BigInt::from(1)); + assert_eq!(witness[1], BigInt::from(1)); + } + + #[test] + fn wrong_input_count_fails() { + let calc = WasmWitnessCalculator::new(wasm_path()).unwrap(); + + // Only 5 inputs instead of 30 + let input = signals! { + "in" => vec![2_i64; 5], + }; + + let result = calc.calculate(&input); + assert!(result.is_err()); + } +} diff --git a/crates/circomkit/Cargo.toml b/crates/circomkit/Cargo.toml new file mode 100644 index 0000000..105c562 --- /dev/null +++ b/crates/circomkit/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "circomkit" +description = "Circom testing & development toolkit" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +circomkit-core.workspace = true +circomkit-witness.workspace = true +circomkit-prove.workspace = true +circomkit-test.workspace = true +log.workspace = true +serde_json.workspace = true +num-bigint.workspace = true +thiserror.workspace = true + +[features] +default = [] +# Native proving backends (forwarded to circomkit-prove). +prove-arkworks = ["circomkit-prove/prove-arkworks"] +prove-lambdaworks = ["circomkit-prove/prove-lambdaworks"] diff --git a/crates/circomkit/src/circomkit/compile.rs b/crates/circomkit/src/circomkit/compile.rs new file mode 100644 index 0000000..65801c9 --- /dev/null +++ b/crates/circomkit/src/circomkit/compile.rs @@ -0,0 +1,100 @@ +use std::path::PathBuf; + +use circomkit_core::error::{CoreError, Result}; +use circomkit_core::functions::{compile_circuit, instantiate_circuit}; +use circomkit_core::types::R1CSInfo; +use circomkit_core::utils::read_r1cs_info; + +use super::Circomkit; + +impl Circomkit { + /// Generate the main component `.circom` file for a circuit. + pub fn instantiate(&self, circuit: &str) -> Result { + let resolved = self.resolve(circuit)?; + let main_path = self.paths.circuit_main(circuit); + instantiate_circuit(&resolved.circuit, &main_path, &resolved.version)?; + log::info!("instantiated {circuit} at {}", main_path.display()); + Ok(main_path) + } + + /// Check whether build artifacts are up-to-date relative to the source file. + /// + /// Returns `true` if the R1CS file exists and is newer than both the source + /// `.circom` file and the generated main component file. + fn is_build_fresh(&self, circuit: &str, source_file: &str) -> bool { + let r1cs_path = self.paths.circuit_r1cs(circuit); + let source_path = self.paths.circuit_source(source_file); + let main_path = self.paths.circuit_main(circuit); + + let r1cs_mtime = match r1cs_path.metadata().and_then(|m| m.modified()) { + Ok(t) => t, + Err(_) => return false, + }; + + // Check source .circom file mtime + if let Ok(source_mtime) = source_path.metadata().and_then(|m| m.modified()) { + if source_mtime > r1cs_mtime { + return false; + } + } + + // Check generated main file mtime + if let Ok(main_mtime) = main_path.metadata().and_then(|m| m.modified()) { + if main_mtime > r1cs_mtime { + return false; + } + } + + true + } + + /// Compile a circuit. Auto-instantiates if the main file doesn't exist. + /// + /// When `recompile` is `false` (the default), compilation is skipped if the + /// build artifacts are newer than the source file. Set `recompile` to `true` + /// to always recompile. + pub fn compile(&self, circuit: &str) -> Result { + let resolved = self.resolve(circuit)?; + let main_path = self.paths.circuit_main(circuit); + + if !main_path.exists() { + self.instantiate(circuit)?; + } + + let out_dir = self.paths.circuit_dir(circuit); + + if !resolved.compiler.recompile && self.is_build_fresh(circuit, &resolved.circuit.file) { + log::info!("skipping compilation for {circuit} (build is up-to-date)"); + return Ok(out_dir); + } + + compile_circuit(&resolved.compiler, &main_path, &out_dir)?; + log::info!("compiled {circuit} to {}", out_dir.display()); + Ok(out_dir) + } + + /// Get circuit info from the R1CS file. + pub fn info(&self, circuit: &str) -> Result { + let r1cs_path = self.paths.circuit_r1cs(circuit); + if !r1cs_path.exists() { + return Err(CoreError::FileNotFound(r1cs_path)); + } + read_r1cs_info(&r1cs_path) + } + + /// Remove all build artifacts for a circuit. + pub fn clear(&self, circuit: &str) -> Result<()> { + let dir = self.paths.circuit_dir(circuit); + if dir.exists() { + std::fs::remove_dir_all(&dir)?; + log::info!("cleared {}", dir.display()); + } + + let main_path = self.paths.circuit_main(circuit); + if main_path.exists() { + std::fs::remove_file(&main_path)?; + } + + Ok(()) + } +} diff --git a/crates/circomkit/src/circomkit/mod.rs b/crates/circomkit/src/circomkit/mod.rs new file mode 100644 index 0000000..6c194ca --- /dev/null +++ b/crates/circomkit/src/circomkit/mod.rs @@ -0,0 +1,56 @@ +mod compile; +mod prove; +mod testing; + +use std::path::Path; + +use circomkit_core::config::{CircomkitConfig, ResolvedCircuitConfig}; +use circomkit_core::error::{CoreError, Result}; +use circomkit_core::pathing::CircomkitPaths; +use circomkit_core::types::CircuitSignals; +use circomkit_prove::SnarkjsBackend; + +/// The main orchestrator for Circomkit operations. +/// +/// Holds the configuration and provides high-level methods for the full +/// circuit development lifecycle: compile, setup, prove, verify, and test. +pub struct Circomkit { + pub config: CircomkitConfig, + pub paths: CircomkitPaths, +} + +impl Circomkit { + /// Create a new Circomkit instance from a config. + pub fn new(config: CircomkitConfig) -> Result { + config.validate()?; + let paths = CircomkitPaths::new(&config); + Ok(Self { config, paths }) + } + + /// Load Circomkit from a `circomkit.json` file. + pub fn from_file(path: &Path) -> Result { + let config = CircomkitConfig::from_file(path)?; + Self::new(config) + } + + /// Resolve a circuit's config (merging per-circuit overrides with global). + pub(crate) fn resolve(&self, circuit: &str) -> Result { + self.config.resolve_circuit(circuit) + } + + /// Create a SnarkjsBackend for the current protocol. + pub(crate) fn snarkjs(&self) -> SnarkjsBackend { + SnarkjsBackend::new("snarkjs", self.config.prover.protocol) + } + + /// Load circuit input signals from the inputs directory. + pub fn load_input(&self, circuit: &str, input: &str) -> Result { + let path = self.paths.input_json(circuit, input); + if !path.exists() { + return Err(CoreError::FileNotFound(path)); + } + let content = std::fs::read_to_string(&path)?; + let signals: CircuitSignals = serde_json::from_str(&content)?; + Ok(signals) + } +} diff --git a/crates/circomkit/src/circomkit/prove.rs b/crates/circomkit/src/circomkit/prove.rs new file mode 100644 index 0000000..e0be8ce --- /dev/null +++ b/crates/circomkit/src/circomkit/prove.rs @@ -0,0 +1,215 @@ +use std::path::{Path, PathBuf}; + +use circomkit_core::enums::ProvingBackendKind; +use circomkit_core::error::{CoreError, Result}; +use circomkit_core::functions::get_calldata; +use circomkit_core::types::CircuitSignals; +use circomkit_prove::{ProvingBackend, SetupBackend, make_proving_backend}; +use circomkit_witness::make_witness_calculator; + +use super::Circomkit; + +/// Output from a trusted setup. +pub struct SetupOutput { + pub pkey_path: PathBuf, + pub vkey_path: PathBuf, +} + +impl Circomkit { + /// Get or download the PTAU file for a circuit. + pub fn ptau(&self, circuit: &str) -> Result { + let info = self.info(circuit)?; + let ptau_name = circomkit_core::utils::ptau_name_for_constraints(info.constraints); + + if let Some(path) = + circomkit_core::utils::ptau_path_if_exists(&ptau_name, &self.config.prover.ptau_dir) + { + return Ok(path); + } + + circomkit_core::utils::download_ptau(&ptau_name, &self.config.prover.ptau_dir) + } + + /// Run trusted setup for a circuit. + pub fn setup(&self, circuit: &str, ptau_path: Option<&Path>) -> Result { + let resolved = self.resolve(circuit)?; + let protocol = resolved.prover.protocol; + + let ptau = match ptau_path { + Some(p) => p.to_path_buf(), + None => self.ptau(circuit)?, + }; + + let pkey_path = self.paths.pkey(circuit, protocol); + let vkey_path = self.paths.vkey(circuit, protocol); + + self.snarkjs() + .setup( + &self.paths.circuit_r1cs(circuit), + &ptau, + &pkey_path, + &resolved.prover, + ) + .map_err(|e| CoreError::CompilationFailed(format!("setup failed: {e}")))?; + + self.snarkjs() + .export_vkey(&pkey_path, &vkey_path) + .map_err(|e| CoreError::CompilationFailed(format!("vkey export failed: {e}")))?; + + log::info!("setup complete for {circuit}"); + Ok(SetupOutput { + pkey_path, + vkey_path, + }) + } + + /// Export verification key from an existing proving key. + pub fn vkey(&self, circuit: &str) -> Result { + let protocol = self.config.prover.protocol; + let pkey_path = self.paths.pkey(circuit, protocol); + let vkey_path = self.paths.vkey(circuit, protocol); + + self.snarkjs() + .export_vkey(&pkey_path, &vkey_path) + .map_err(|e| CoreError::CompilationFailed(format!("vkey export failed: {e}")))?; + + Ok(vkey_path) + } + + /// Export Solidity verifier contract. + pub fn contract(&self, circuit: &str) -> Result { + let protocol = self.config.prover.protocol; + let pkey_path = self.paths.pkey(circuit, protocol); + let sol_path = self.paths.verifier_sol(circuit, protocol); + + self.snarkjs() + .export_contract(&pkey_path, &sol_path, protocol) + .map_err(|e| CoreError::CompilationFailed(format!("contract export failed: {e}")))?; + + log::info!("contract exported to {}", sol_path.display()); + Ok(sol_path) + } + + /// Compute a witness for a circuit with the given input. + pub fn witness( + &self, + circuit: &str, + input: &str, + data: Option<&CircuitSignals>, + ) -> Result { + let input_data = match data { + Some(d) => d.clone(), + None => self.load_input(circuit, input)?, + }; + + let wasm_path = self.paths.circuit_wasm(circuit); + let calc = make_witness_calculator(self.config.witness.calculator, &wasm_path, None) + .map_err(|e| CoreError::CompilationFailed(format!("witness calculator: {e}")))?; + + let witness = calc + .calculate(&input_data) + .map_err(|e| CoreError::CompilationFailed(format!("witness calculation: {e}")))?; + + let wtns_path = self.paths.witness_path(circuit, input); + if let Some(parent) = wtns_path.parent() { + std::fs::create_dir_all(parent)?; + } + circomkit_core::utils::write_witness_file(&wtns_path, &witness)?; + + log::info!("witness computed for {circuit}/{input}"); + Ok(wtns_path) + } + + /// Generate a proof for a circuit with the given input. + /// + /// The proving backend is selected from the resolved circuit config + /// (`prover.backend`), capability-checked against the protocol and curve. + /// snarkjs uses its one-shot `full_prove`; native backends (arkworks, + /// lambdaworks) compute a witness first, then prove from it. + pub fn prove( + &self, + circuit: &str, + input: &str, + data: Option<&CircuitSignals>, + ) -> Result { + let resolved = self.resolve(circuit)?; + let protocol = resolved.prover.protocol; + let kind = resolved.prover.backend; + let prime = resolved.compiler.prime; + + let pkey_path = self.paths.pkey(circuit, protocol); + + // Capability check (protocol + curve) happens inside the factory. + let backend = make_proving_backend(kind, protocol, prime) + .map_err(|e| CoreError::CompilationFailed(format!("prove failed: {e}")))?; + + let output = if kind == ProvingBackendKind::Snarkjs { + // One-shot: snarkjs computes the witness and proves in one subprocess. + let input_data = match data { + Some(d) => d.clone(), + None => self.load_input(circuit, input)?, + }; + let wasm_path = self.paths.circuit_wasm(circuit); + backend + .full_prove(&input_data, &wasm_path, &pkey_path) + .map_err(|e| CoreError::CompilationFailed(format!("prove failed: {e}")))? + } else { + // Native backends prove from a pre-computed witness. + let wtns_path = self.witness(circuit, input, data)?; + let r1cs_path = self.paths.circuit_r1cs(circuit); + backend + .prove(&wtns_path, &r1cs_path, &pkey_path) + .map_err(|e| CoreError::CompilationFailed(format!("prove failed: {e}")))? + }; + + let proof_path = self.paths.proof_path(circuit, input, protocol); + let public_path = self.paths.public_signals_path(circuit, input); + + if let Some(parent) = proof_path.parent() { + std::fs::create_dir_all(parent)?; + } + std::fs::write(&proof_path, serde_json::to_string_pretty(&output.proof)?)?; + std::fs::write( + &public_path, + serde_json::to_string_pretty(&output.public_signals)?, + )?; + + log::info!("proof generated for {circuit}/{input}"); + Ok(proof_path) + } + + /// Verify a proof for a circuit with the given input. + pub fn verify(&self, circuit: &str, input: &str) -> Result { + let protocol = self.config.prover.protocol; + let vkey_path = self.paths.vkey(circuit, protocol); + let proof_path = self.paths.proof_path(circuit, input, protocol); + let public_path = self.paths.public_signals_path(circuit, input); + + let vkey: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(&vkey_path)?)?; + let proof: serde_json::Value = + serde_json::from_str(&std::fs::read_to_string(&proof_path)?)?; + let public_signals: Vec = + serde_json::from_str(&std::fs::read_to_string(&public_path)?)?; + + let ok = self + .snarkjs() + .verify(&vkey, &public_signals, &proof) + .map_err(|e| CoreError::CompilationFailed(format!("verify failed: {e}")))?; + + Ok(ok) + } + + /// Generate calldata for a circuit proof. + pub fn calldata(&self, circuit: &str, input: &str, pretty: bool) -> Result { + let protocol = self.config.prover.protocol; + let proof_path = self.paths.proof_path(circuit, input, protocol); + let public_path = self.paths.public_signals_path(circuit, input); + + let proof: serde_json::Value = + serde_json::from_str(&std::fs::read_to_string(&proof_path)?)?; + let public_signals: Vec = + serde_json::from_str(&std::fs::read_to_string(&public_path)?)?; + + get_calldata(&proof, &public_signals, pretty) + } +} diff --git a/crates/circomkit/src/circomkit/testing.rs b/crates/circomkit/src/circomkit/testing.rs new file mode 100644 index 0000000..371ff6c --- /dev/null +++ b/crates/circomkit/src/circomkit/testing.rs @@ -0,0 +1,46 @@ +use circomkit_core::config::CircuitConfig; +use circomkit_core::enums::Protocol; +use circomkit_prove::SnarkjsBackend; +use circomkit_test::{ProofTester, WitnessTester}; +use circomkit_witness::make_witness_calculator; + +use super::Circomkit; + +impl Circomkit { + /// Create a WitnessTester for a circuit. + pub fn witness_tester( + &self, + circuit: &str, + config: CircuitConfig, + ) -> std::result::Result { + // Ensure circuit is compiled + self.compile(circuit) + .map_err(circomkit_test::TestError::Core)?; + + let wasm_path = self.paths.circuit_wasm(circuit); + let calc = make_witness_calculator(self.config.witness.calculator, &wasm_path, None)?; + + let _ = config; + Ok(WitnessTester::new( + calc, + self.paths.circuit_r1cs(circuit), + self.paths.circuit_sym(circuit), + )) + } + + /// Create a ProofTester for a circuit. + pub fn proof_tester( + &self, + circuit: &str, + protocol: Protocol, + ) -> std::result::Result { + let backend = Box::new(SnarkjsBackend::new("snarkjs", protocol)); + ProofTester::new( + backend, + self.paths.circuit_wasm(circuit), + self.paths.pkey(circuit, protocol), + self.paths.vkey(circuit, protocol), + protocol, + ) + } +} diff --git a/crates/circomkit/src/lib.rs b/crates/circomkit/src/lib.rs new file mode 100644 index 0000000..758517b --- /dev/null +++ b/crates/circomkit/src/lib.rs @@ -0,0 +1,22 @@ +pub use circomkit_core as core; +pub use circomkit_prove as prove; +pub use circomkit_test as test; +pub use circomkit_witness as witness; + +mod circomkit; + +pub use circomkit::Circomkit; + +// Re-export key types for convenience +pub use circomkit_core::config::{CircomkitConfig, CircuitConfig}; +pub use circomkit_core::enums::{Prime, Protocol}; +pub use circomkit_core::error::CoreError; +pub use circomkit_core::pathing::CircomkitPaths; +pub use circomkit_core::types::R1CSInfo; +pub use circomkit_core::types::{CircuitSignals, SignalValue, Witness}; +pub use circomkit_prove::{ProofOutput, ProvingBackend, SnarkjsBackend}; +pub use circomkit_test::{ProofTester, WitnessTester}; +pub use circomkit_witness::{WitnessCalculator, WitnessError}; + +// Re-export the signals! macro +pub use circomkit_core::signals; diff --git a/crates/circomkit/tests/circuits/main/arrays_2_3.circom b/crates/circomkit/tests/circuits/main/arrays_2_3.circom new file mode 100644 index 0000000..13b39d3 --- /dev/null +++ b/crates/circomkit/tests/circuits/main/arrays_2_3.circom @@ -0,0 +1,5 @@ +// auto-generated by circomkit +pragma circom 2.1.0; +include "../arrays.circom"; + +component main {public[in1D, in2D]} = Arrays(2, 3); diff --git a/tests/circuits/test/error_rt.circom b/crates/circomkit/tests/circuits/main/errors.circom similarity index 79% rename from tests/circuits/test/error_rt.circom rename to crates/circomkit/tests/circuits/main/errors.circom index 8bafc66..1ae676d 100644 --- a/tests/circuits/test/error_rt.circom +++ b/crates/circomkit/tests/circuits/main/errors.circom @@ -1,6 +1,5 @@ // auto-generated by circomkit -pragma circom 2.0.0; - +pragma circom 2.1.0; include "../errors.circom"; component main = Errors(); diff --git a/tests/circuits/test/multiplier_3.circom b/crates/circomkit/tests/circuits/main/multiplier_3.circom similarity index 81% rename from tests/circuits/test/multiplier_3.circom rename to crates/circomkit/tests/circuits/main/multiplier_3.circom index 968860f..0054997 100644 --- a/tests/circuits/test/multiplier_3.circom +++ b/crates/circomkit/tests/circuits/main/multiplier_3.circom @@ -1,6 +1,5 @@ // auto-generated by circomkit -pragma circom 2.0.0; - +pragma circom 2.1.0; include "../multiplier.circom"; component main = Multiplier(3); diff --git a/crates/circomkit/tests/e2e/common.rs b/crates/circomkit/tests/e2e/common.rs new file mode 100644 index 0000000..a6bf558 --- /dev/null +++ b/crates/circomkit/tests/e2e/common.rs @@ -0,0 +1,51 @@ +//! Shared test helpers for e2e integration tests. +//! +//! Requires `circom` and `snarkjs` to be installed and on PATH. + +use std::path::PathBuf; +use std::sync::{Mutex, Once}; + +use circomkit::Circomkit; + +/// Root of the workspace (two levels up from this crate's manifest dir). +pub fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..") +} + +/// PTAU file used by the tests (supports up to 2^8 = 256 constraints). +pub const TEST_PTAU: &str = "powersOfTau28_hez_final_08.ptau"; + +static ENSURE_PTAU: Once = Once::new(); + +/// Global lock to serialize tests that share filesystem state (CWD, build dir). +static TEST_LOCK: Mutex<()> = Mutex::new(()); + +/// Download the test PTAU file if it doesn't exist. +fn ensure_ptau() { + ENSURE_PTAU.call_once(|| { + let root = workspace_root(); + let ptau_dir = root.join("tests/ptau"); + let ptau_path = ptau_dir.join(TEST_PTAU); + if !ptau_path.exists() { + circomkit::core::utils::download_ptau(TEST_PTAU, &ptau_dir) + .expect("failed to download test PTAU"); + } + }); +} + +/// Load Circomkit from the test config. +/// +/// Sets CWD to the workspace root so relative paths in the config resolve correctly. +/// Downloads the PTAU file if it doesn't exist. +/// +/// Returns the Circomkit instance AND the lock guard — hold onto the guard +/// for the duration of your test to prevent concurrent filesystem access. +pub fn test_circomkit() -> (Circomkit, std::sync::MutexGuard<'static, ()>) { + let guard = TEST_LOCK.lock().unwrap_or_else(|e| e.into_inner()); + let root = workspace_root(); + std::env::set_current_dir(&root).expect("failed to set CWD to workspace root"); + ensure_ptau(); + let config_path = root.join("tests/circomkit.json"); + let ck = Circomkit::from_file(&config_path).expect("failed to load test config"); + (ck, guard) +} diff --git a/crates/circomkit/tests/e2e/compile.rs b/crates/circomkit/tests/e2e/compile.rs new file mode 100644 index 0000000..726d7db --- /dev/null +++ b/crates/circomkit/tests/e2e/compile.rs @@ -0,0 +1,151 @@ +use circomkit::Circomkit; +use circomkit::core::config::CircomkitConfig; + +use super::common::{test_circomkit, workspace_root}; + +#[test] +fn compile_multiplier() { + let (ck, _guard) = test_circomkit(); + let out = ck.compile("multiplier_3").unwrap(); + assert!(out.exists()); + assert!(ck.paths.circuit_r1cs("multiplier_3").exists()); + assert!(ck.paths.circuit_wasm("multiplier_3").exists()); + assert!(ck.paths.circuit_sym("multiplier_3").exists()); +} + +#[test] +fn compile_arrays() { + let (ck, _guard) = test_circomkit(); + let out = ck.compile("arrays_2_3").unwrap(); + assert!(out.exists()); +} + +#[test] +fn compile_errors() { + let (ck, _guard) = test_circomkit(); + let out = ck.compile("errors").unwrap(); + assert!(out.exists()); +} + +#[test] +fn info_multiplier() { + let (ck, _guard) = test_circomkit(); + ck.compile("multiplier_3").unwrap(); + let info = ck.info("multiplier_3").unwrap(); + + // Multiplier(3) with optimization=0 has 15 constraints + assert_eq!(info.constraints, 15); + assert!(info.wires > 0); + assert!(info.prime_name.is_some()); +} + +#[test] +fn clear_removes_artifacts() { + let (ck, _guard) = test_circomkit(); + ck.compile("errors").unwrap(); + let dir = ck.paths.circuit_dir("errors"); + assert!(dir.exists()); + + ck.clear("errors").unwrap(); + assert!(!dir.exists()); +} + +#[test] +fn source_mtime_not_modified_by_compile() { + let (ck, _guard) = test_circomkit(); + let source_path = ck.paths.circuit_source("multiplier"); + assert!(source_path.exists(), "source .circom file must exist"); + + let mtime_before = source_path.metadata().unwrap().modified().unwrap(); + ck.compile("multiplier_3").unwrap(); + let mtime_after = source_path.metadata().unwrap().modified().unwrap(); + + assert_eq!( + mtime_before, mtime_after, + "compilation must not modify the source .circom file's mtime" + ); +} + +#[test] +fn skips_compilation_when_build_is_fresh() { + let (ck, _guard) = test_circomkit(); + + // Start clean so we own the artifact timestamps + ck.clear("multiplier_3").unwrap(); + + // First compile to create artifacts + ck.compile("multiplier_3").unwrap(); + let r1cs_path = ck.paths.circuit_r1cs("multiplier_3"); + assert!(r1cs_path.exists()); + let mtime_after_first = r1cs_path.metadata().unwrap().modified().unwrap(); + + // Second compile should skip (recompile defaults to false) + // Sleep briefly so we can detect if the file was rewritten + std::thread::sleep(std::time::Duration::from_millis(100)); + ck.compile("multiplier_3").unwrap(); + let mtime_after_second = r1cs_path.metadata().unwrap().modified().unwrap(); + + assert_eq!( + mtime_after_first, mtime_after_second, + "r1cs mtime should not change when build is fresh" + ); +} + +#[test] +fn compile_custom_templates() { + let (ck, _guard) = test_circomkit(); + let out = ck.compile("custom_mul").unwrap(); + assert!(out.exists()); + assert!(ck.paths.circuit_r1cs("custom_mul").exists()); + assert!(ck.paths.circuit_wasm("custom_mul").exists()); + + // Verify the generated main file includes pragma custom_templates + let main_path = ck.paths.circuit_main("custom_mul"); + let main_source = std::fs::read_to_string(&main_path).unwrap(); + assert!( + main_source.contains("pragma custom_templates;"), + "generated main must include custom_templates pragma" + ); +} + +#[test] +fn compile_tags() { + let (ck, _guard) = test_circomkit(); + let out = ck.compile("bounded_add_8").unwrap(); + assert!(out.exists()); + assert!(ck.paths.circuit_r1cs("bounded_add_8").exists()); + assert!(ck.paths.circuit_wasm("bounded_add_8").exists()); + + // Verify the generated main file uses circom 2.2.0 (from per-circuit override) + let main_path = ck.paths.circuit_main("bounded_add_8"); + let main_source = std::fs::read_to_string(&main_path).unwrap(); + assert!( + main_source.contains("pragma circom 2.2.0;"), + "generated main must use overridden circom version for tags support" + ); +} + +#[test] +fn recompiles_when_forced() { + let mut config = + CircomkitConfig::from_file(&workspace_root().join("tests/circomkit.json")).unwrap(); + config.compiler.recompile = true; + let ck = Circomkit::new(config).unwrap(); + + // First compile + ck.compile("multiplier_3").unwrap(); + let r1cs_path = ck.paths.circuit_r1cs("multiplier_3"); + let mtime_after_first = r1cs_path.metadata().unwrap().modified().unwrap(); + + // Sleep so mtime will differ if recompiled + std::thread::sleep(std::time::Duration::from_millis(1100)); + + // Second compile with recompile=true should rewrite artifacts + ck.compile("multiplier_3").unwrap(); + let mtime_after_second = r1cs_path.metadata().unwrap().modified().unwrap(); + + assert!( + mtime_after_second > mtime_after_first, + "r1cs should be rewritten when recompile=true" + ); +} diff --git a/crates/circomkit/tests/e2e/config.rs b/crates/circomkit/tests/e2e/config.rs new file mode 100644 index 0000000..a925e76 --- /dev/null +++ b/crates/circomkit/tests/e2e/config.rs @@ -0,0 +1,54 @@ +use circomkit::core::config::CircomkitConfig; + +use super::common::test_circomkit; + +#[test] +fn load_test_config() { + let (ck, _guard) = test_circomkit(); + assert_eq!(ck.config.circuits.len(), 5); + assert!(ck.config.circuits.contains_key("multiplier_3")); + assert!(ck.config.circuits.contains_key("arrays_2_3")); + assert!(ck.config.circuits.contains_key("errors")); + assert!(ck.config.circuits.contains_key("custom_mul")); + assert!(ck.config.circuits.contains_key("bounded_add_8")); +} + +#[test] +fn resolve_circuit_config() { + let (ck, _guard) = test_circomkit(); + let resolved = ck.config.resolve_circuit("multiplier_3").unwrap(); + assert_eq!(resolved.circuit.template, "Multiplier"); + assert_eq!(resolved.circuit.file, "multiplier"); +} + +#[test] +fn nonexistent_circuit_errors() { + let (ck, _guard) = test_circomkit(); + let result = ck.config.resolve_circuit("nonexistent"); + assert!(result.is_err()); +} + +#[test] +fn json_schema_is_valid() { + let schema = CircomkitConfig::json_schema(); + let json = serde_json::to_string_pretty(&schema).unwrap(); + assert!(json.contains("CircomkitConfig")); + assert!(json.contains("circuits")); + assert!(json.contains("prover")); + assert!(json.contains("compiler")); +} + +#[test] +fn paths_resolve_correctly() { + let (ck, _guard) = test_circomkit(); + let r1cs = ck.paths.circuit_r1cs("multiplier_3"); + assert!(r1cs.to_string_lossy().contains("multiplier_3")); + assert!(r1cs.to_string_lossy().ends_with(".r1cs")); +} + +#[test] +fn load_input_from_file() { + let (ck, _guard) = test_circomkit(); + let input = ck.load_input("multiplier_3", "default").unwrap(); + assert!(input.contains_key("in")); +} diff --git a/crates/circomkit/tests/e2e/main.rs b/crates/circomkit/tests/e2e/main.rs new file mode 100644 index 0000000..45ab4ea --- /dev/null +++ b/crates/circomkit/tests/e2e/main.rs @@ -0,0 +1,13 @@ +//! End-to-end integration tests for Circomkit. +//! +//! These tests exercise the full pipeline: compilation, witness calculation, +//! proof generation, and verification. +//! +//! Requires `circom` and `snarkjs` to be installed and on PATH. + +mod common; + +mod compile; +mod config; +mod prove; +mod witness; diff --git a/crates/circomkit/tests/e2e/prove.rs b/crates/circomkit/tests/e2e/prove.rs new file mode 100644 index 0000000..7bada7d --- /dev/null +++ b/crates/circomkit/tests/e2e/prove.rs @@ -0,0 +1,111 @@ +use circomkit::Circomkit; +use circomkit::signals; + +use super::common::{TEST_PTAU, test_circomkit, workspace_root}; + +fn setup_multiplier(ck: &Circomkit) { + ck.compile("multiplier_3").unwrap(); + let ptau_path = workspace_root().join("tests/ptau").join(TEST_PTAU); + ck.setup("multiplier_3", Some(&ptau_path)).unwrap(); +} + +#[test] +fn full_prove_and_verify() { + let (ck, _guard) = test_circomkit(); + setup_multiplier(&ck); + + let input = signals! { "in" => vec![2_i64, 4, 10] }; + let proof_path = ck + .prove("multiplier_3", "prove_test", Some(&input)) + .unwrap(); + assert!(proof_path.exists()); + + let ok = ck.verify("multiplier_3", "prove_test").unwrap(); + assert!(ok, "proof should verify"); +} + +#[test] +fn verify_rejects_tampered_signals() { + let (ck, _guard) = test_circomkit(); + setup_multiplier(&ck); + + let input = signals! { "in" => vec![2_i64, 4, 10] }; + ck.prove("multiplier_3", "tamper_test", Some(&input)) + .unwrap(); + + // Tamper with the public signals file + let public_path = ck.paths.public_signals_path("multiplier_3", "tamper_test"); + std::fs::write(&public_path, "[\"999\"]").unwrap(); + + let ok = ck.verify("multiplier_3", "tamper_test").unwrap(); + assert!(!ok, "tampered proof should not verify"); +} + +/// The orchestrator surfaces capability errors before doing any work: the test +/// config compiles on bn128, but lambdaworks only supports bls12381. +#[test] +fn prove_rejects_unsupported_backend_curve() { + use circomkit::core::enums::ProvingBackendKind; + + let (mut ck, _guard) = test_circomkit(); + ck.config.prover.backend = ProvingBackendKind::Lambdaworks; + + let input = signals! { "in" => vec![2_i64, 4, 10] }; + let err = ck + .prove("multiplier_3", "cap_test", Some(&input)) + .expect_err("lambdaworks on bn128 must be rejected"); + + let msg = err.to_string().to_lowercase(); + assert!( + msg.contains("lambdaworks"), + "error should name the backend: {msg}" + ); + assert!( + msg.contains("curve"), + "error should mention the curve: {msg}" + ); +} + +/// The orchestrator honors `prover.backend`: switching to the native Arkworks +/// (BN254) prover produces a snarkjs-format proof that snarkjs then verifies. +#[cfg(feature = "prove-arkworks")] +#[test] +fn arkworks_backend_through_orchestrator() { + use circomkit::core::enums::ProvingBackendKind; + + let (mut ck, _guard) = test_circomkit(); + setup_multiplier(&ck); + + // Route proving through the native Arkworks backend (BN254 / bn128). + ck.config.prover.backend = ProvingBackendKind::Arkworks; + + let input = signals! { "in" => vec![2_i64, 4, 10] }; + let proof_path = ck.prove("multiplier_3", "ark_e2e", Some(&input)).unwrap(); + assert!(proof_path.exists()); + + // Same proving key snarkjs set up + snarkjs-format proof => snarkjs verifies it. + let ok = ck.verify("multiplier_3", "ark_e2e").unwrap(); + assert!(ok, "snarkjs should verify the arkworks-generated proof"); +} + +#[test] +fn witness_then_prove() { + let (ck, _guard) = test_circomkit(); + setup_multiplier(&ck); + + // Compute witness separately first + let input = signals! { "in" => vec![3_i64, 5, 7] }; + let wtns_path = ck + .witness("multiplier_3", "witness_test", Some(&input)) + .unwrap(); + assert!(wtns_path.exists()); + + // Then prove (will recompute witness via snarkjs, but the file exists) + let proof_path = ck + .prove("multiplier_3", "witness_test", Some(&input)) + .unwrap(); + assert!(proof_path.exists()); + + let ok = ck.verify("multiplier_3", "witness_test").unwrap(); + assert!(ok); +} diff --git a/crates/circomkit/tests/e2e/witness.rs b/crates/circomkit/tests/e2e/witness.rs new file mode 100644 index 0000000..f2fe136 --- /dev/null +++ b/crates/circomkit/tests/e2e/witness.rs @@ -0,0 +1,174 @@ +use circomkit::signals; +use num_bigint::BigInt; + +use super::common::test_circomkit; + +fn multiplier_tester() -> (circomkit::WitnessTester, std::sync::MutexGuard<'static, ()>) { + let (ck, guard) = test_circomkit(); + let config = ck.config.circuits["multiplier_3"].clone(); + let tester = ck.witness_tester("multiplier_3", config).unwrap(); + (tester, guard) +} + +#[test] +fn expect_pass_multiplier() { + let (tester, _guard) = multiplier_tester(); + + let input = signals! { "in" => vec![2_i64, 4, 10] }; + let output = signals! { "out" => 80_i64 }; + tester.expect_pass(&input, Some(&output)).unwrap(); +} + +#[test] +fn expect_pass_different_values() { + let (tester, _guard) = multiplier_tester(); + + let input = signals! { "in" => vec![3_i64, 5, 7] }; + let output = signals! { "out" => 105_i64 }; + tester.expect_pass(&input, Some(&output)).unwrap(); +} + +#[test] +fn expect_fail_input_contains_one() { + let (tester, _guard) = multiplier_tester(); + + // Multiplier rejects inputs containing 1 (IsZero check) + let input = signals! { "in" => vec![1_i64, 4, 10] }; + let err = tester.expect_fail(&input).unwrap(); + assert!(!err.is_empty()); +} + +#[test] +fn compute_output() { + let (tester, _guard) = multiplier_tester(); + + let input = signals! { "in" => vec![2_i64, 3, 5] }; + let output = tester.compute(&input, &["out"]).unwrap(); + + assert_eq!( + output["out"], + circomkit::SignalValue::Single(BigInt::from(30)) + ); +} + +#[test] +fn constraint_count() { + let (tester, _guard) = multiplier_tester(); + // Multiplier(3) with optimization=0: 15 constraints + tester.expect_constraint_count(15, true).unwrap(); +} + +#[test] +fn constraint_count_at_least() { + let (tester, _guard) = multiplier_tester(); + tester.expect_constraint_count(5, false).unwrap(); +} + +#[test] +fn arrays_pass() { + let (ck, _guard) = test_circomkit(); + let config = ck.config.circuits["arrays_2_3"].clone(); + let tester = ck.witness_tester("arrays_2_3", config).unwrap(); + + let input = signals! { + "in" => 1_i64, + "in1D" => vec![2_i64, 3], + "in2D" => vec![ + vec![4_i64, 5, 6], + vec![7_i64, 8, 9] + ], + }; + + // Arrays circuit just constrains relationships, no explicit output + tester.expect_pass(&input, None).unwrap(); +} + +#[test] +fn arrays_fail_bad_sequence() { + let (ck, _guard) = test_circomkit(); + let config = ck.config.circuits["arrays_2_3"].clone(); + let tester = ck.witness_tester("arrays_2_3", config).unwrap(); + + // in1D should be consecutive (in1D[0]+1 == in1D[1]) + let input = signals! { + "in" => 1_i64, + "in1D" => vec![2_i64, 5], + "in2D" => vec![ + vec![4_i64, 5, 6], + vec![7_i64, 8, 9] + ], + }; + + tester.expect_fail(&input).unwrap(); +} + +#[test] +fn errors_pass_valid() { + let (ck, _guard) = test_circomkit(); + let config = ck.config.circuits["errors"].clone(); + let tester = ck.witness_tester("errors", config).unwrap(); + + // in != 1, so in=0 is fine + let input = signals! { "in" => 0_i64, "inin" => vec![3_i64, 5] }; + let output = signals! { "out" => 15_i64 }; // 0 + (3 * 5) = 15 + tester.expect_pass(&input, Some(&output)).unwrap(); +} + +#[test] +fn errors_fail_assert() { + let (ck, _guard) = test_circomkit(); + let config = ck.config.circuits["errors"].clone(); + let tester = ck.witness_tester("errors", config).unwrap(); + + // in=1 triggers assert(in != 1) + let input = signals! { "in" => 1_i64, "inin" => vec![3_i64, 5] }; + tester.expect_fail(&input).unwrap(); +} + +#[test] +fn errors_fail_wrong_array_size() { + let (ck, _guard) = test_circomkit(); + let config = ck.config.circuits["errors"].clone(); + let tester = ck.witness_tester("errors", config).unwrap(); + + // inin expects 2 elements, giving 1 should fail + let input = signals! { "in" => 0_i64, "inin" => vec![3_i64] }; + let result = tester.calculate_witness(&input); + assert!(result.is_err()); +} + +#[test] +fn custom_templates_pass() { + let (ck, _guard) = test_circomkit(); + let config = ck.config.circuits["custom_mul"].clone(); + let tester = ck.witness_tester("custom_mul", config).unwrap(); + + let input = signals! { "in1" => 3_i64, "in2" => 7_i64 }; + let output = signals! { "out" => 21_i64 }; + tester.expect_pass(&input, Some(&output)).unwrap(); +} + +#[test] +fn custom_templates_wrong_output() { + let (ck, _guard) = test_circomkit(); + let config = ck.config.circuits["custom_mul"].clone(); + let tester = ck.witness_tester("custom_mul", config).unwrap(); + + // 3 * 7 = 21, not 42 + let input = signals! { "in1" => 3_i64, "in2" => 7_i64 }; + let wrong_output = signals! { "out" => 42_i64 }; + let result = tester.expect_pass(&input, Some(&wrong_output)); + assert!(result.is_err()); +} + +#[test] +fn tags_bounded_add_pass() { + let (ck, _guard) = test_circomkit(); + let config = ck.config.circuits["bounded_add_8"].clone(); + let tester = ck.witness_tester("bounded_add_8", config).unwrap(); + + // 100 + 50 = 150, both fit in 8 bits (max 255) + let input = signals! { "a" => 100_i64, "b" => 50_i64 }; + let output = signals! { "out" => 150_i64 }; + tester.expect_pass(&input, Some(&output)).unwrap(); +} diff --git a/examples/bun-sha256/.gitignore b/examples/bun-sha256/.gitignore deleted file mode 100644 index 6b58145..0000000 --- a/examples/bun-sha256/.gitignore +++ /dev/null @@ -1,122 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and *not* Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# builds -build -dist - -# circuit-specific powers of tau are ignored -*.ptau -# universal ptaus not ignored -!ptau/* -# temporary ptaus are ignored -tmp.ptau - -# is this still a thing lol -.DS_Store - -# ignore auto generated test circuits -circuits/test -ptau diff --git a/examples/bun-sha256/.vscode/extensions.json b/examples/bun-sha256/.vscode/extensions.json deleted file mode 100644 index 5fc8eb4..0000000 --- a/examples/bun-sha256/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["iden3.circom", "oven.bun-vscode"] -} diff --git a/examples/bun-sha256/.vscode/settings.json b/examples/bun-sha256/.vscode/settings.json deleted file mode 100644 index 963048a..0000000 --- a/examples/bun-sha256/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "jestrunner.jestCommand": "bun test" -} diff --git a/examples/bun-sha256/README.md b/examples/bun-sha256/README.md deleted file mode 100644 index e3b49bc..0000000 --- a/examples/bun-sha256/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Circomkit with Bun - -In this example, we use [Bun](https://bun.sh/) with the [SHA256](https://en.wikipedia.org/wiki/SHA-2) circuit. - -## Installation - -Simply do: - -```sh -bun install -``` - -## Usage - -You can see an example within [`src/index.ts`](./src/index.ts). Run it with: - -```sh -bun start -``` - -For the CLI, you can test the entire flow as follows: - -1. Compile circuit: `bunx circomkit compile sha256_32` -2. Prove with default input: `bunx circomkit prove sha256_32 default` -3. Verify the proof: `bunx circomkit verify sha256_32 default` -4. Create contract: `bunx circomkit contract sha256_32` -5. Create calldata: `bunx circomkit calldata sha256_32 default` - -Notice that we use `bunx` instead of `npx` to use Bun! - -## Testing - -Run tests with: - -```sh -bun test -``` diff --git a/examples/bun-sha256/bun.lockb b/examples/bun-sha256/bun.lockb deleted file mode 100755 index 8caf48cb022823e3e766ecacc13c0e9bf2b70fc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38543 zcmeHw2Urx#voGMHf|3;!6G)P<T5fcW2IRfWZ4cjoDqk#W=-}~PEu6<71)8SWDU0vPN(=$tHs2fEJ_(uNR za3fB5l$w8JxHLp&D32Wy$PMK%19|)~mXH}`EG;1>CYJLketUz9QJ?cVyUv>r;+?6y z&>^9V^vAnT=7kMS93yG^_ZnyfA+RYC>->*2PLv4aW_#x8- zVtf;}00prT7Zd9W^{*lA0%;|r(vaR2rGYGg5ZiTyyb_d?_N0Chl*>W+Fi4TlGyzi( z%rX<>01ph)SRs^5=NV1)oh6&vheC>cd?1yD6nTVl1;T%}V+XTBLx9ffj!o@?SpsHY zC@bg@AU&2~MmQVV>w`Q<*FSI?iXrwH>aqPa0WUm)B@B)SVX^%T zNU>ZBGAMr%q*y**lu*x43A<)ghmQpLOIF_MsNTJI;8Z7G*F)@AQbka5>mu#_iB=-OjM5TFx0$x z(y3;<;|Vr@deXzAk4DYu^hHBYNmXO4)7R%-rQ=`pnt$NkE6u`)Wxa^RjxG zVy`ZTF4su9Zp}Eac_EnL-uY^uPM_y@*B`(9?1&uFp46AFyK-{QHpgH#PfYvv{!1Z^ zPEHqn&9}Xjb`4Wcip-oVdBx&C3zfZ}DdWK|^Y#7uI( zJ$mZ9;>r{LD;f1u%isR9-L)t4j7KSZmkldqv#;p9=dXScoG;^9erb%+*)2UU6?XHV zu4(7kMb7$$XU_EzA2OdQ=Z)Llf7d7kNHP zR4*!07$H7O>*7@H9l^5Cd5@fiZtR*@t5vl6ZD;P&>U`DHY7IBkqFnd!ySbi@Irh;? za^Q$vW}UT0j~F#&iFGP7MZHk5_+ateRfB_awNA@c?Q}jE@b;d@6|H!eYRAIW$9A)v z7=Oj+J?b^<^ttd5yOhM~w;o(1<@2Jhly)m{+$^iNvQq7k+S2E0Bm6Ul`X|vFoGj>(Vc&P7llL(x-RB+~l09Vy)5Yo6b2rP!j9^a^cc~>#1GteOTjpq|0;% zpLbE;hGgcxIhwdKz4J5cEwX9HB9|R^?2$P$ec6r)rgwUuelY&fxolo~{EO_qrz?-g zymBua-r$gP$1~@`(tQb^I~7Oy9nSTXf4@LpMVn`#knu{T$6vRD0OZA~F z?^oL$ji$LwoR=tDTJ(8swWjf*!%rrUQnM`_rm7J0DodqMSu;~B&Om=5$Ny4C-IF7Y z=Y5!29dsp8@pb=XBd=xJhwW^nc(xZ_xn~^DDoLA>IqfDFmaG3#z`Gs>ZHNP5K9W4# z4%!t+`w$TxK^-8rS1y7t1&k%|heWKsys<68j{$}@B0QGs;y>*O1fL3cClMaYtlNRb zCItTp@D4Qou*|kA5WEFk*a9BNG}CMk0fL_{!Xt*1{SJONfav=PX z;#FYMJB##(bKrOFCkpUn{E;WpXip$=9svAM5r4#y^0sJ@cAo$bYX&uc5d-RIS0H#p z*hi!OfD9!&WZM-8J{SPQ0Z;P3+y6a)Hw8S(jaWjbEg?v|uYgDW!DB$Xu}GWX?Er}S zYp>pjTm&BpczY2ZZLqz8;7E=5PmLzNByJhSO)5BS0MO! zzz+jFf{;J#_1hH)z8LU^fXDG`Z{Lvt!AroRf$JyETP$nu7!bS@;K}?!{_T~4;Fkm5 z4)`Muo^O5|UjlfvA3~3$K&sV1+S$RvN!EXO-umtSrvjd=UpV%^+y9$1JPhS;^B)8Q z=R)iM@7mu2z#9V|Sht%uwk7&I2zb(eG6%4}tw8W~B0RAjQr=#?J{S$IzlcXHuEXsK zgbxSsp85GijBi*=;kL%`$uN%Th2_TuGX(jp$)BbJN<=35Jd|6ss70v_}2#UfpT zPXavZpX9NwJ%O|@0=yyMQFffWsKfRIg8u|~Tt5+mSX@Ke6A0c6HoRp0hNZN*Uv1GK z_z=M3`Uz%C>Ax);sVDetfFB}~AM4;)tX+ZN#o>Vs_rC~28Gd*E^8r5+@Th-`AWpji z;r|-&!$o)mlJd5Qkao6kZix3U`0gvl9!IQL!+OPj5_@jUyEW%@1d*=Yb z_fQlQGY34$ll0e|n`%hAQGg#T;*YYE^7i7F1D>q^i1}Up718kR#UdXfrvw-*&L1p8 ze0ymS{4l_i@yD{?o&O5}Pw)Tl;vWNkj7a~;pU4H5tp?K08x9;iMR){|@>apLc835z ziiU3sN9vpTz=nCO2#@yjyY@R4@DphKe^-A6fcK{1iF|FPM1ED}ru{$4juCE$?Ft0% z3;6Lg{&)`1oR(T#$^OZ_A!%DO5Prdc$NML?$FkqW zrvjeb{}78hXip&guL6EBP5-34EgGbqe2=E}8}-)Sdl%9scs}6C{inUM)A4zLNBIdo zl46_I0%`XR@Z|aZKjClPvt|85e!n|@QGmAw`B8t!|99Fwj%f7qF)SrYIABFMwmH1`+GkA!7JhiuL^=B5!SonAd@bbaWwNpr=@`2N6?! zQEC7wwud#4DmQ`@1E$yx_J&jndt@rmQ>+KurTT5vR4s-n$`4~o1x&HsAc&|RM~E04 zA)>v)+Cv3QQ4TnZpxTe1O2x$fJ5!_&dvz+bCq@q&nMgVOpIT60=`AVBAsG)4#vDDJAZY zuBXw(HGl+0*z@S3zVFg6e)QNJ_B4INGV%0Pb+6B^a%I2ORg_QGeCzzxn#I}iShFVJ zZ}EsTBVs10&r7fCZ?1MEBqDLk&ie{9y0`|Cz|ak?Pv4OCJ=Z96b3(H8z=m|!(?cu7 zrm06S>vDCy?lX&?(sP!*s1>_5VUMrZo5t*+Jqi-nRj=pyhUTdceP8c2fJT?BM@XA7 zWa0vqnTJms=vCh)9J+V+H*s9(CFgYMgk)?JmG2nliI4zIrd6^E~cAiI;{9>!rrcWAuH0( z4fDL;Lv3SoXe&VtBYVQ8mBOWSUFZ?Pz@}f}2bfLVn!)TlJ%71aM4c;HS zz2L9XUfvsx$0_)V_c)t=cf0zQtsNitPP{&AW*Uty{XCITQL~Gu5}s78y7}R;+OB@- zWs@!EZYkZep?6JL!-0Y~W6CF$giZQf`*eI>gZ~*Z_2{~_(l^9PtpCn`TAKfGo1rI- zF5WjtVC+pD5-y>Aa^if45snRKmd)$bb7#K{){W^8>*gQINKx7#%Qq{o%ehnulm~@m@p%!$>zsJ3%OA<)?V;61#B!mR_Zg_U?S? zRQT|6*mpsL1lv@ybD8se-7PsiIGHDdi|RiX&mR&t;bd8mu&c20)n{`W-7bVEqzqw? zKKtKhAI$9adP|V|+Vt$usm5{FE4y^4@X#8%exb*Km3>ZT>liBB?~-{jqwkSJZ@oV> z2D?1Eaci%2o`sdG&LbLK`hJz6rEGVrFd%Km`L#*AHw-!^Zy$I1P2<~fvo~LhNxpx4 zQEJhdybnh4g*tl!d(~tZURkwCH(}0}zWdIvmQSnkza&4EMwfn$!0@%=U)Xs#v~t+1 zwJrzLOAM!8Oz!_ATy=3D?;Nh}q@%)V-U>Py=d~5W2lYEVX6dKw8moZes{=0BE_s&v zbY1na`!u@r{XHY;nDfRdaxQ5v&p1D@(lYVZjegKk?cSM6^}ol)`+ssvT;VqCTBmBa z+lO4ced)Ylyu$&x0I_xNJ}23AF&@49Yc+k`=;yACxT)U5_g89|`Hop+dy8FvYsf77 zH8;P$E@4Jjdt?~r_(?jK?+Z7w^ZNMcUKibgoRYT^^)EIm-F6*zygFsIgl7d!UO1j@ z4h;9lf!*Kl5@(#SUb7--$?mvWsY=R+-e0?XXwL*CJ*gh<-)c^u^BF#_Kx2!pe0pU} z)-79?2gwrimRfDfog-mzok61u$EMAJQP!w9#OXCtF0*haC;QmdU_T?P!0^`v^)9RR zrAFx-Ty%94&+F2m$AP2oOe&GEA2wO#!n#{F1|BIVx>?$6m0w1u3&)YofuWNh`>>n8 zgsp|SiE-h?<4fl>cIvNh!#*~ZA$DcM9h8bcZ2xpb9Pq@ zDbP>Nk?fF&-^7yp1wPM^z(~|z(c8o?H}ZSGkaHT1)3@6Vx}tvO*3g&v(wozlPE0Gz zukzKFemZK?bICO~#Mio5yg#0qW#!dZa>?|0Q(k)|B+}^Oa~}ze2EDq4kx3yPe}K+cZdF`u(Yy#`~g!g;UB` zDQ?T5(WSo!XFQDGIJQQ~#OHW?g=6~RYW<{)onva2t3Ts)8xru!`TEwAUv$=19&+T) z7R&4Mg?7r? zDZ6gYERI-}wD)R&#_4aHW$uJ7tX$deMuJqxit2cNNJz-s=x_BSe596E&v{FutI|vr z)`yhb?tgo{&JN!u>EwL4;L5lVM~3#N$*FdFw;}I~+Edef6^BBj0QRZU37?JC>LzyBbHct(VP$RO_3&>l zhsMk_u#-+Pf9;t^zh98&VR3mb)r_?nX zb@l#SqgO8R?o`}g1%H{>n^oP0_U_4=i%xY91}m<4HfZM>v&|9bM~UC+YA7>s-l?GO zR*GLo+0p3sCPX1+T-i4}x4)yCSNU?SA-v#e1Kh9po$x#2Cga|F@`Hp3x#_W%52j2_ zk=Q8Qa{HLcm$(-TZ#`4qaHL$)(IC+$AVpD;MibK~~w_VpWJKufe^*yEuOO)yo|` z^MiGSW52zsGS|#9Gp2phl};UB>e;aDRc1k&l7VD=Zdv^f>3~(7XU9LP)h*UuxI@#2 zMpuJQckQN4wdUNVD&_MRZd!G0W=$Dm#W}YV*FT&-^UaN+z4W$0rHSvz@?+DTg2EoJ zK5Oq6l4>Psl3>2<#OkRt4K|p6rqR`;(~Td>y!Cvf%*3t>pIg>b>rh4G$!wlRHH^6?|I#(Tzq|i%!?-&8NFJ z9_$UgmUO~xvF~a}w}LUnySNXIkJ%)ZFY&HshK1tGOqqaFbJvDR9#iPd8gzQg+G9(4 zCrfL*?Rlhejq4>EU2Qtu9g|dU@B^acR&<)h<|LmwoxR6xe3et^jJl_HTur;C&95j| zJN2S>n&S93+B3CeOHz-i=|1WzrTQ`>S4>;0Xa@d9g{)_IZbkxQoVDtNEo$nVOZIc<3Nm7z4cx^%i-wQ651s@z#@P-E%Jp8j_Gto)ob z&u9H7XBbm0$HV_SE)1y=k(OML-`nGhUr)r+&z#+7tb$AU?`|ZRrn|l2;VwU zJ$>E+Zg^3KgtHfKo8KUnWA`^U>ghyJnR%4gEoS29xmjUT(;hx?t>}EVW6Y`5-J-)6 zD&9FqpBGF*6jBDG;z*~p8OCSr#+I;igJvvPJKyiyU|S2*>*FScEmd_}Uv|M{41egc z3e65mu^!1@%Gr^3co8A2GcuL7s#PmzM9}2Lb5;@6}7_xB4$^;>=P&IaGCm6*L?m}Y%JW&fl+y@bM0ll5{bLyN4AUN{v-qf5?h zkv1bHWTA@e?X9H+3zp1roLMzxD1Y?an-d>9b-ngT`j*(xn%;&_KlM2yy}_(5!6G&| zC?{8K?*4#g?mw6Q1dZkqO4EM7My3?)xaD&`_4_D4?myRa%eF-^7M%s+O?p5i2 zF1>bn^zH5r_pUZ%-aGRl;(gYL$1Kw!XFV{H4zxQStmva-ddY#_=ZnFO9 zxsvbB*&LtzYDsa(d*&v#d*ji|^Eb}=>(H0mZ?xUSjOgbYW`roD44>8P7k<~T+%5ff zGIisew~N*K)RiJHN-Ff(0UivKUrA+?T*kt;B)1sLw$lFK7;5&C$73YwC^(<$rE?1vi zOCKj~qTf)Xu&BgI^|R6QtrwPj@Af(=F7DR+xW0xRoozXZ_m^opd3wgEm&D$jO_LYi z6*ULO$jQd(Vd)E#hjn|QF6jIDYigFlyLmZE^<}FK4)z*3;W8)qb4F=q_@=y+pfzbl zGd}3vjR-wzfAdSsnLg5t`$|jX~^g|dEC7LI%_^}u(=kcAXR)tZ~fH+5@*f?)9Avxz2?9e7||o8 zU`q9VO|cWUH6OckKNvqh?EbOGo1PD)$9EX}V&H4bz%^XQO@?~D9^S9*WSO2%XFCj5 z>2Yg+l}lM?opIVUx;D*JLBAL06d!2dUEDHo=-H`rJ~7fPWSNO(eizrDoow+?>T%a9 znetI1C)Tk_u0I>nePib@yK+{RHQE}^W8_FPlh41H@Q_BAyf;DejJ_STrMF1ANaSSg z)w+4;i1^NPlfRm9H%3^hOY+jx*12iPUYoSme}Bh`pY5zv<$}~1SNyy?_Ipw>*DQed zX1yx?zKQQ&NMKBo)9byvJm4C?zCn0A(w}$9LFS%O2lj6JQl8w^kB&Ru)h*1r6R@P) z{L6MqHzSAcf2QDiC+C@t3A4k3r^-_0c{F)#2~kKHE;sIXJhMMS;hWESk2&Y241F`m z+*kWe2Wia}QxB~g+>OJuG5_>^(18A%jF)aOdl|8PP<+h_tyk5Z)`pBP>6`uGD2=Wi zoo@2lzx8(v?SFWY#@1KX6Z?YhV)Ki2(h*^6Vl*3;m0Tl&mju_b1v>qF&SBYV9VO*ZRNW~WW^xjoc|=5Po2cB$gs z*?A{)(DK5yGtGiyWM`ZCpk5#+?)0jd(HQo zW$;*kKx&!a*m2>4`&!kb^vYHYDhiy@RlH5;%DWRt2m!D*^zW-S9jk#PhZKteB;K}6qxkoR-e_iWSyqb z9ZaYD{JHwRSr)2O($r~QHk6Lhgs^bn@t2|tClD^ zRdk&wS@%sozjtjq-?cV%9{#48?9YbK>E2YF@KJ3=0ozPXWwLUX+tk4Ps2wvW-}n$Q z->&4*fsvOkJmi0QqoTEYuXEati4&dP*|D9UEq^N~CSG&&k*iHN6B^y2bha>L4d+&X!H=Md;& zFj(T8Y}PkX-C zDrq!mT+)Neh)q_WgBD+um-98NwZEC2G~CYJmEkq<@3&v1V{2BuGa509Mt1}u3Mr$9 z@TP@!XDQk0h&k0kPb_o2bcfHcd{?oKsg*C8r+?_UYW!pI=LT^T);6eGEUCDlB$K64 z8SRvP#k)g}%gDid%V~67>2$X-ydNvZG#0WwHCKI*+CFlbNyWiYGB!GWCBC|6iI2Lx zc!QfzQF8O0-i^jaKFYP?d4JtLlXhwFbBEG~*Jk@K&!N#BNvB)2YP8;C^!B@t&&nDTIFK5c~yIOI!MEfoaJ$Z}1?u?<+J^N9k zoyrBfi+#-KbSpOBgA6 zu5fZ~*F}kSV=c3;(ByTa(~UlC{PlTo>Y_vP5k>xs3c_SPe5NN2Oy3ePq1ME2-!|L# zD^G48V|$-cGvapSx5_8iUvAK|V>hmQruVXLLca95zlt9E zpT22Elh?hOD%kJxGa4oLqAzKk8}g)j>b-fVhddahyw>x$uI_zK_hBxdz8zki);ZRB z{`HfwwcGc+-)`oV>k}P&YW$#mH!pX&saNubMt2;Y?pxV&;yvCg@^>D6e^&13VZNl| zjXi7M)rLh5NZJ__oKzJ&>2|eg(em$iMs`_uI;~Eo?(H_8Iq#PB(_1gQZi2YkEE-+> z4uS;6>hBl0a~%9Vj!v;nlKybrCaSO6%vaXCf_A8cUom-kHKpg}E}8?1CYSAvU*BVu z*@FwN^Ce?0P10A+i(HhhF1_&#jqU_O6jFwBhe4(bUL@6rS}W@mS8OgB{`Sz~iF*c& zK6sz~Ov{LUK~Q?Gw`17uUY_Ij78aiW!sv8v^Z@H=p^HN{CG2v!eq}$6?nFA>4J*H| zE1Pd?=yx+!dwOp0y!o5v>6Gk$zYHxRrfY% z{}Z*d+;wV7GCkhY=z7rU_Ocs#^8NPMO5fE<2~RTn=m<-6^19!>f7JR~oyYf!bC0gR z#d?0*#;4Pw4F|OIrzu~G>u55l%&1t#e{-Pw*WKo98r?~Bx?Z98>(`gu7?67HnAVFT z7hQYrn8iWe-c9=E-A&d0Y-;ag#>G?j>q$Ag?K#=|>c~}lpRCrat#I4qrnK*o9dA%M z{W%N2TOollH2#9*mn=iasgdidGK(s5;@@rW^(ypn*`-d0x5MeqBbVj-{WMOeRDjWi0QaYEgdhTQskidf3CKd%SkNdpvf# zTH20+`-YAWM+69#NHJIDEA$CF*Gaj1z(KoZ_uN?C8Md2m99OVSO>y2MN7I8Bo$kAj zR|_gFUhmtje&uS>QtzyTbE8tiB#+4M`>xW({%-wyos{6RW$JqZ(z@PR{ye>U5Mz5o z$6Y19Awf3YhZ)@s&eP~lq0<$=ymgD5L+Vpoqr9!(I_((QV`y@2-Kt{0>JQ5XJp1}7 z@XW`;y)lhmyUJ!(E-xE@c|rF2zDLdFcfT_}+^D>L{v`p8t~Z@-;^qM|3CZadf#mr%%qA4y^iQX*117euh;* z)rqS#y7-+D35*e=`t=g({WZ54}EN7Q6yCamu)ac{nRsmtWdGKZAeo?T3j z4bWwdef%-6bW_DrZ$aq6&jAl#-93EUM3qLDe7A(O8L}G>s^*Lr4y|zB{VZ0|)9$fs zPTDd?xp%dyhfDs|Wwp11molDhv%7!lbiPom_PEN)*U_m5qP3$YmEVyYwe=nSTp7QA zB7t#5qq8~3Gx@%!%cDR;W`{ejgS6a&Cf=6Loi+IFbFE2ro&)xJ#C(fODR}1UrQhqL zrHV|%&2DGXx1Cyk$jbfTMf!U^KSC5zMuL@MX|V6{0eO>ooxRGg)#MlEhON)D3}3BR zwp)A8=IP58^iiy{>gzD(e&k}Q;xqbHo5r}Cxm`J+vn6p^#n+F!XnJ7L>0Wqbr59fT0+VjDp za`dV!#<&4Y{2M%EpXyJin-)CNJTKQ~rl#bWBXWv2zkhv`c5JX;l-NpximbSMpR3;Q zS^cF{zR$pI%O08KAMW&Uebkq&2_G7ZBFgVs|GmYsm`0aPr@Oznu;_!2PwRFkHa$ZcbAIc8s2TkLGr&Upbp62gqp%=`kOphM*cn&Df?fgl;7wq>Wa+@ zWk+*`VzKa13w$RM_Z#s4xG4-36-fFY6Z(G$L|IAvUABnBZ-)LS_4jxC_^16J4g62j z0M1AJ*6jcHdHEY#h5ufj=7fqk%sf_@jY88u+7uKN|R>fj=7f zqk%sf_@jY88u-7Yft8}yd7gny45V!Ze6}GsTp(nHh8hy5DuxsI9FD!3sj-@X8_VGZ z8mO78u|l~);k-cVXSI!gHwC2O2NBQe@T?z$A4JUKdlvF74@*?m0aEfiSAS6%ootq9?}R9m34#^zcoi1*a_r;zjfAxhygo90Cp&V?8UaUR6^5c@#H-+$q6wea_x z_%}lEyB_=o2fvrWZ(Hy?lo1f|J2?E79>06XZ`AR7a{TsN9U}g%kywcMZ3%v_f!|i( z_uKfbHGUV}AEE|C)Ug&sR2k|NRmO!l4I+Nu5Csv(1odtJkqJ>7A`2ppX$Zs!i1_U? zerJr|?&5d0MiB9L6gm(GKy-xY1aUCLArOZ`90t)CBH9Sr1loWKE$YIx9Yj5do+ucE zcoYmmYh#MC`9YL`C=L9c%dqE`Qk8 z!|~RFh~tLifI34RqP|hjsBau6)IE-sK19?X>JrN_k15&#+5_6hB#77t4~W=jv^CT_ z>IrQRzgKgII2Iy~?-+<9AUZ?DF~#wAgotB193mN8EE^)qyFfY$BB{r=t`JB6qYUYd zgotgi4Z&c!8$@DX$RGLQobZL{0}<`j8zR~|+WcfuO7i}Y=Rjmb3=pMx)8GO^X-rcp zZ9B!(a%!YCERmMY>xIb=OC;40Y$A^M0qHCe$`Wz}!X`_>noN4^vYCJm zeqHlBvVq=A4b82^el8oXMgNu!6^c^-T7qBKkS|?`hbQbQ4xNP<@mWTEF+q(PFoKyy zyq^)TPEZ4Oi1tSOr4c_+l-`UDVM!$()QD#&iW&$G_jy=&akPm~DGFm^2umgL!bZGH ziKszWiJvy&e@Zk8po5?AvA_xRQ$9F>q2||o9>EO#OIg*HPG9y=N$3TMtn~JHJsdlAzs{w zcPgj>nX#wD&l~Yy1vO@{BEcvS4|K${7KH&BT71+I-&^DK&_+1TOIMj1vTbPCg1GOPUNQxYDA3w zEgNN{z=!zIBfh}^g9Z;Z#LFJ>9>x%#V{B-NHN>wT@fRi=B#t;vG z#B&)n3Y6{42XjZMiElHJu0b~96_0rPf*NzU(}HZoZyxanCZYyC{kL7iC{Q;O;&YGq z5~DD1Z-T%6C-M&2a>oD+tS%;E#BU$*M+O+U)8i-*PlUw78q`2kDOxDUW|CK6Y&Arek}p<7D>F|0S3nh zhVIvVi04S+5l{wuqN zG5y8-fu8}Q>poaMMB>oDa23B}n`H1IF;?aE+psIf3K zwS)=uZ;T$S)fm)fh|<`m^v82J0Vgbq!#5ljBjoVIS)t>Fd~SGb zCU*LJx2^n?mEF+MGnUCc%(AWRGd*7@5ODaQjj6ZP=8X#+`9&GV0Yr$4x3;(}9wXa0 zR;0ntYltTCx!mNJkL8ZS84(Cv`GXwHWPtsCf@u^ zkVq2`Upz11plD&N@Bj{9B)aHH+&_{V8bEPkx5`S?92kkNfDJxh02@bc04LlGeQV=W z5anmtKNS2-oBA`OS%NT;6nsz>H;fY)IE@v>5>N_*1B8fB4okpkrHf?i1B}TfaK^pQ z53GY&d_HSND|G05ffhXr^l<-$^eA~F!B7Oz9FU&J58?2!jM5T^-wJ(NDNqt_tqDN02NZ&qr8;0~)`lQ0L-z09o3?>%?nIOMP#tKxY*IoS@Mil3VDmLKWG2)k zZl&9zb0YwXu7DvN8zDnny4sxiaEb+3_?L-u9S$y9A1yrWKwgkAp|K4ZJOIMD;ouux z$PR8r(B?J(Z@#9OQY8HOEH;P9iHTr^3%I=SRtWv0C6N0^2`CQ!qwK|>70L={a{`!@ zbZlNYnKW(?hjtsI{P1}xz4B80HuvV=UofEUS! zMY#3#v856Aq!|I00Ox#dsG)@wU|TZOEsK&Wg3k$!4B#+B1+ZlbU`F#<5ojY!YUpua z!G!ZYPB?63IdH`E>rL@Ln*zIk7EzjSYiY#OM8IMKLW<^pD|}mo1yoCh!nU>WxAYyb zEg8yU+rl<$3!u%{fQ0R68$%*GeFdE83S@;Na6}p6E)0x^dLRR9;|O4`a09?FNlkOU z)g8a+AQ@PQuBe5$En5*COj9W8QGgn-wl;AsW=#Q!jkhe`tqk73fH~|#t3h^K{h=r!zjVH+Mv|zV0b?Ejo|axuoHswFeY4vaa(<4 zMY9KrnBZ`WCNo#SWbuO{!#LqW0bGl27O=Ajj0|VvQVxZ<^aMaNc$AF}=CXt71+A#z zUu}W=zsf+N@E^6Vzymlpl;t1Fq0<+@#v+snOGf~1yo5Zs(ZF$$kQLMlwTj?TD!?$I+EX(#h$Ccj!?800(CDx4JwLQV zDs&u>!-)s>z!5Mxd_LTC$*?u63=BiaYlQ*yjTeo#rKSsN4z{)0{J;dDKjc9u6sz^A zg&L(KYhv7V-7al5_Y{!L*MMyMc1m8zpuk|@92QtI^+pC|1v5uWL-T7zS+rI_g_fg6 zqOHZK*^~j>d`)$lLPBo>IDy=74r(I;R?ry&80==fcj zaJ^`KWrOx26y9RmYTf*D9oD4qC}u=xqyYLRIw)_&`hK|o1HT{glzQ8mTlkRx1!Qqy zKPx&jZ+a-E?j+RnMgT|1VGHq|gUb+QrA?bV*cde3a9WY^A1#5|KT4=kY-`^Bz#M4& zkZ;%Biq;dr({j*n(E&m$y`ZUtQWu^yPzs{7+}8M#mx}-;mlW5wY*6&N5@4b$N>^>| z>8aPBfT2>*4L&)5wc>*pdDGNNPf;^Xt38lt$-t?fWt(=~^5O}w@cOAqTuNTdQPf&t z-P}fmrrJ|9%qaU1k&hOLF2dn(qZM+rRzMINGn-y#!g&Sg1I}BxY;K!E(VGDodKPp7 d??Bsn8g7;v(9r@W^{$ngmQ647{{Q>;{{U*sCcgjx diff --git a/examples/bun-sha256/circomkit.json b/examples/bun-sha256/circomkit.json deleted file mode 100644 index ded4944..0000000 --- a/examples/bun-sha256/circomkit.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": "2.1.2", - "protocol": "groth16", - "curve": "bn128", - "verbose": true -} diff --git a/examples/bun-sha256/circuits.json b/examples/bun-sha256/circuits.json deleted file mode 100644 index 9c5678d..0000000 --- a/examples/bun-sha256/circuits.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "sha256_32": { - "file": "sha256", - "template": "Sha256Bytes", - "params": [32] - } -} diff --git a/examples/bun-sha256/circuits/main/sha256_32.circom b/examples/bun-sha256/circuits/main/sha256_32.circom deleted file mode 100644 index 480112e..0000000 --- a/examples/bun-sha256/circuits/main/sha256_32.circom +++ /dev/null @@ -1,6 +0,0 @@ -// auto-generated by circomkit -pragma circom 2.1.2; - -include "../sha256.circom"; - -component main = Sha256Bytes(32); diff --git a/examples/bun-sha256/circuits/sha256.circom b/examples/bun-sha256/circuits/sha256.circom deleted file mode 100644 index 155b872..0000000 --- a/examples/bun-sha256/circuits/sha256.circom +++ /dev/null @@ -1,42 +0,0 @@ -pragma circom 2.0.0; - -include "circomlib/circuits/sha256/sha256.circom"; -include "circomlib/circuits/bitify.circom"; - -/** - * Wrapper around SHA256 to support bytes as input instead of bits - * @param N The number of input bytes - * @input in The input bytes - * @output out The SHA256 output of the n input bytes, in bytes - * - * SOURCE: https://github.com/celer-network/zk-benchmark/blob/main/circom/circuits/sha256/sha256_bytes.circom - */ -template Sha256Bytes(N) { - signal input in[N]; - signal output out[32]; - - // convert input bytes to bits - component byte_to_bits[N]; - for (var i = 0; i < N; i++) { - byte_to_bits[i] = Num2Bits(8); - byte_to_bits[i].in <== in[i]; - } - - // sha256 over bits - component sha256 = Sha256(N*8); - for (var i = 0; i < N; i++) { - for (var j = 0; j < 8; j++) { - sha256.in[i*8+j] <== byte_to_bits[i].out[7-j]; - } - } - - // convert output bytes to bits - component bits_to_bytes[32]; - for (var i = 0; i < 32; i++) { - bits_to_bytes[i] = Bits2Num(8); - for (var j = 0; j < 8; j++) { - bits_to_bytes[i].in[7-j] <== sha256.out[i*8+j]; - } - out[i] <== bits_to_bytes[i].out; - } -} diff --git a/examples/bun-sha256/inputs/sha256_32/default.json b/examples/bun-sha256/inputs/sha256_32/default.json deleted file mode 100644 index 8c463ad..0000000 --- a/examples/bun-sha256/inputs/sha256_32/default.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "in": [ - 116, 111, 100, 97, 121, 32, 105, 115, 32, 97, 32, 103, 111, 111, 100, 32, 100, 97, 121, 44, 32, 110, 111, 116, 32, - 101, 118, 101, 114, 121, 100, 97 - ] -} diff --git a/examples/bun-sha256/package.json b/examples/bun-sha256/package.json deleted file mode 100644 index 16ca2d2..0000000 --- a/examples/bun-sha256/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "description": "Circomkit examples", - "scripts": { - "start": "bun run ./src/index.ts", - "test": "bun test" - }, - "dependencies": { - "circomkit": "^0.3.0", - "circomlib": "^2.0.5" - }, - "devDependencies": { - "@types/bun": "latest", - "typescript": "^5.1.3" - }, - "prettier": { - "printWidth": 120, - "singleQuote": true - } -} diff --git a/examples/bun-sha256/src/index.ts b/examples/bun-sha256/src/index.ts deleted file mode 100644 index 399ae17..0000000 --- a/examples/bun-sha256/src/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { createHash } from 'crypto'; -import { Circomkit } from 'circomkit'; - -const PREIMAGE = Buffer.from('bunsbunsbunsbunsbuns'); -const PREIMAGE_BYTES = PREIMAGE.toJSON().data; - -// digest and its byte array -const DIGEST = createHash('sha256').update(new Uint8Array(PREIMAGE)).digest('hex'); -const DIGEST_BYTES = Buffer.from(DIGEST, 'hex').toJSON().data; - -const circomkit = new Circomkit({ - inspect: false, -}); -const circuitName = `sha256_${PREIMAGE_BYTES.length}`; - -console.info('Building circuit...'); -const buildPath = await circomkit.compile(circuitName, { - file: 'sha256', - template: 'Sha256Bytes', - params: [PREIMAGE_BYTES.length], -}); -console.info(`Compiled circuit to ${buildPath}`); - -console.info('Creating a witness...'); -const witnessPath = await circomkit.witness(circuitName, 'bunsbuns', { - in: PREIMAGE_BYTES, -}); -console.info(`Witness created at ${witnessPath}`); - -// https://github.com/oven-sh/bun/issues/11005 -// https://github.com/iden3/snarkjs/pull/490 -console.log('Cant prove with Bun yet!'); -// console.info('Running prover...'); -// const proofPath = await circomkit.prove(circuitName, 'bunsbuns', { -// in: PREIMAGE_BYTES, -// }); -// console.info('Done!'); diff --git a/examples/bun-sha256/tests/sha256.test.ts b/examples/bun-sha256/tests/sha256.test.ts deleted file mode 100644 index a4c4f45..0000000 --- a/examples/bun-sha256/tests/sha256.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { describe, it, beforeAll } from 'bun:test'; -import { WitnessTester } from 'circomkit'; -import { createHash } from 'crypto'; -import { Circomkit } from 'circomkit'; - -const circomkit = new Circomkit({ verbose: false }); - -describe('sha256', () => { - let circuit: WitnessTester<['in'], ['out']>; - - // number of bytes for the sha256 input - const NUM_BYTES = 36; - - // preimage and its byte array - const PREIMAGE = Buffer.from('today is a good day, not everyday is'); - const PREIMAGE_BYTES = PREIMAGE.toJSON().data; - - // digest and its byte array - const DIGEST = createHash('sha256').update(new Uint8Array(PREIMAGE)).digest('hex'); - const DIGEST_BYTES = Buffer.from(DIGEST, 'hex').toJSON().data; - - // circuit signals - const INPUT = { in: PREIMAGE_BYTES }; - const OUTPUT = { out: DIGEST_BYTES }; - - beforeAll(async () => { - circuit = await circomkit.WitnessTester(`sha256_${NUM_BYTES}`, { - file: 'sha256', - template: 'Sha256Bytes', - params: [NUM_BYTES], - }); - }); - - it('should compute hash correctly', async () => { - await circuit.expectPass(INPUT, OUTPUT); - }); - - it('should pass on correct witness', async () => { - const witness = await circuit.calculateWitness(INPUT); - await circuit.expectConstraintPass(witness); - }); - - it('should fail on fake witness', async () => { - const witness = await circuit.calculateWitness(INPUT); - const badWitness = await circuit.editWitness(witness, { - 'main.sha256.sha256compression[0].sigmaPlus[38].sigma0.out[1]': BigInt(1234), - 'main.sha256.sha256compression[0].sigmaPlus[38].sigma0.out[2]': BigInt(1234), - 'main.sha256.sha256compression[0].sigmaPlus[38].sigma0.out[3]': BigInt(1234), - 'main.sha256.sha256compression[0].sigmaPlus[38].sigma0.out[4]': BigInt(1234), - 'main.sha256.sha256compression[0].sigmaPlus[38].sigma0.out[5]': BigInt(1234), - }); - await circuit.expectConstraintFail(badWitness); - }); -}); diff --git a/examples/bun-sha256/tsconfig.json b/examples/bun-sha256/tsconfig.json deleted file mode 100644 index fd521c7..0000000 --- a/examples/bun-sha256/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - // Enable latest features - "lib": ["ESNext"], - "target": "ESNext", - "module": "ESNext", - "moduleDetection": "force", - "allowJs": true, - - // Bundler mode - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, - - // Best practices - "strict": true, - "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, - - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false - } -} diff --git a/hardhat.config.ts b/hardhat.config.ts deleted file mode 100644 index 607262a..0000000 --- a/hardhat.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {HardhatUserConfig} from 'hardhat/config'; -import '@nomicfoundation/hardhat-toolbox'; - -const config: HardhatUserConfig = { - solidity: '0.8.24', -}; - -export default config; diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index af7443f..0000000 --- a/jest.config.js +++ /dev/null @@ -1,19 +0,0 @@ -/** @type {import('ts-jest').JestConfigWithTsJest} */ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - verbose: true, - rootDir: './tests', - testTimeout: 100000, - globalTeardown: '/hooks/teardown.js', - forceExit: true, - detectOpenHandles: true, - transform: { - '^.+\\.test.(ts|js)$': [ - 'ts-jest', - { - tsconfig: './tsconfig.test.json', - }, - ], - }, -}; diff --git a/package.json b/package.json deleted file mode 100644 index ee4cc66..0000000 --- a/package.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "name": "circomkit", - "version": "0.3.5", - "description": "A Circom testing & development environment", - "author": "erhant", - "license": "MIT", - "scripts": { - "build": "pkgroll", - "prebuild": "rm -rf dist/", - "cli:nb": "node ./dist/cli.cjs", - "cli": "pnpm build && pnpm cli:nb", - "test": "jest", - "check": "npx tsc --noEmit", - "lint": "npx eslint '**/*.ts' && echo 'All good!'", - "format": "npx prettier --check ./src/**/*.ts ./tests/**/*.ts" - }, - "engines": { - "node": ">=12.0.0" - }, - "files": [ - "dist/", - "LICENSE", - "README.md" - ], - "bin": "./dist/cli.js", - "main": "./dist/index.cjs", - "module": "./dist/index.mjs", - "types": "./dist/index.d.cts", - "exports": { - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - }, - "import": { - "types": "./dist/index.d.mts", - "default": "./dist/index.mjs" - } - }, - "peerDependencies": { - "@types/snarkjs": "^0.7.x", - "snarkjs": "^0.7.x" - }, - "dependencies": { - "circom_tester": "^0.0.23", - "commander": "^12.1.0", - "loglevel": "^1.9.2" - }, - "devDependencies": { - "@commander-js/extra-typings": "^12.1.0", - "@nomicfoundation/hardhat-ethers": "^3.0.8", - "@nomicfoundation/hardhat-network-helpers": "^1.0.12", - "@nomicfoundation/hardhat-toolbox": "^5.0.0", - "@typechain/ethers-v6": "^0.5.1", - "@typechain/hardhat": "^9.1.0", - "@types/jest": "^29.5.14", - "@types/node": "^18.19.67", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "@typescript-eslint/parser": "^6.21.0", - "eslint": "^8.57.1", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.2.1", - "ethers": "^6.13.4", - "hardhat": "^2.22.16", - "jest": "^29.7.0", - "pkgroll": "^2.5.1", - "prettier": "^3.4.1", - "solc": "^0.8.28", - "ts-jest": "^29.2.5", - "ts-node": "^10.9.2", - "typescript": "^5.7.2" - }, - "prettier": { - "bracketSpacing": false, - "singleQuote": true, - "trailingComma": "es5", - "arrowParens": "avoid", - "printWidth": 120 - }, - "keywords": [ - "circom", - "zero knowledge", - "snarkjs", - "typescript", - "cli", - "tooling", - "blockchain" - ], - "homepage": "https://github.com/erhant/circomkit#readme", - "repository": { - "type": "git", - "url": "https://github.com/erhant/circomkit.git" - }, - "bugs": { - "url": "https://github.com/erhant/circomkit/issues/" - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index ef8918e..0000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,8374 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@types/snarkjs': - specifier: ^0.7.x - version: 0.7.8 - circom_tester: - specifier: ^0.0.19 - version: 0.0.19 - commander: - specifier: ^12.1.0 - version: 12.1.0 - loglevel: - specifier: ^1.9.2 - version: 1.9.2 - snarkjs: - specifier: ^0.7.x - version: 0.7.5 - devDependencies: - '@commander-js/extra-typings': - specifier: ^12.1.0 - version: 12.1.0(commander@12.1.0) - '@nomicfoundation/hardhat-ethers': - specifier: ^3.0.8 - version: 3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.12 - version: 1.0.12(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/hardhat-toolbox': - specifier: ^5.0.0 - version: 5.0.0(gxul7wxp54ybnadymvfaa7s5hm) - '@typechain/ethers-v6': - specifier: ^0.5.1 - version: 0.5.1(ethers@6.13.4)(typechain@8.3.2(typescript@5.7.2))(typescript@5.7.2) - '@typechain/hardhat': - specifier: ^9.1.0 - version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.4)(typechain@8.3.2(typescript@5.7.2))(typescript@5.7.2))(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))(typechain@8.3.2(typescript@5.7.2)) - '@types/jest': - specifier: ^29.5.14 - version: 29.5.14 - '@types/node': - specifier: ^18.19.67 - version: 18.19.67 - '@typescript-eslint/eslint-plugin': - specifier: ^6.21.0 - version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2) - '@typescript-eslint/parser': - specifier: ^6.21.0 - version: 6.21.0(eslint@8.57.1)(typescript@5.7.2) - eslint: - specifier: ^8.57.1 - version: 8.57.1 - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.1) - eslint-plugin-node: - specifier: ^11.1.0 - version: 11.1.0(eslint@8.57.1) - eslint-plugin-prettier: - specifier: ^5.2.1 - version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.4.1) - ethers: - specifier: ^6.13.4 - version: 6.13.4 - hardhat: - specifier: ^2.22.16 - version: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - pkgroll: - specifier: ^2.5.1 - version: 2.5.1(typescript@5.7.2) - prettier: - specifier: ^3.4.1 - version: 3.4.1 - solc: - specifier: ^0.8.28 - version: 0.8.28 - ts-jest: - specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)))(typescript@5.7.2) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@18.19.67)(typescript@5.7.2) - typescript: - specifier: ^5.7.2 - version: 5.7.2 - -packages: - - '@adraffy/ens-normalize@1.10.1': - resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.26.2': - resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.26.0': - resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.26.2': - resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.25.9': - resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.25.9': - resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.25.9': - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.26.0': - resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.26.2': - resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-bigint@7.8.3': - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-attributes@7.26.0': - resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-jsx@7.25.9': - resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-typescript@7.25.9': - resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/template@7.25.9': - resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.25.9': - resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.26.0': - resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} - engines: {node: '>=6.9.0'} - - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - - '@commander-js/extra-typings@12.1.0': - resolution: {integrity: sha512-wf/lwQvWAA0goIghcb91dQYpkLBcyhOhQNqG/VgWhnKzgt+UOMvra7EX/2fv70arm5RW+PUHoQHHDa6/p77Eqg==} - peerDependencies: - commander: ~12.1.0 - - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - - '@esbuild/aix-ppc64@0.23.1': - resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.23.1': - resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.23.1': - resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.23.1': - resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.23.1': - resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.23.1': - resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.23.1': - resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.23.1': - resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.23.1': - resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.23.1': - resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.23.1': - resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.23.1': - resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.23.1': - resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.23.1': - resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.23.1': - resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.23.1': - resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.23.1': - resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.23.1': - resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.23.1': - resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.23.1': - resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.23.1': - resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.23.1': - resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.23.1': - resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.23.1': - resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@eslint/js@8.57.1': - resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@ethereumjs/rlp@4.0.1': - resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} - engines: {node: '>=14'} - hasBin: true - - '@ethereumjs/util@8.1.0': - resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} - engines: {node: '>=14'} - - '@ethersproject/abi@5.7.0': - resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} - - '@ethersproject/abstract-provider@5.7.0': - resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} - - '@ethersproject/abstract-signer@5.7.0': - resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} - - '@ethersproject/address@5.6.1': - resolution: {integrity: sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==} - - '@ethersproject/address@5.7.0': - resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} - - '@ethersproject/base64@5.7.0': - resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} - - '@ethersproject/basex@5.7.0': - resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==} - - '@ethersproject/bignumber@5.7.0': - resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} - - '@ethersproject/bytes@5.7.0': - resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} - - '@ethersproject/constants@5.7.0': - resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} - - '@ethersproject/contracts@5.7.0': - resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==} - - '@ethersproject/hash@5.7.0': - resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} - - '@ethersproject/hdnode@5.7.0': - resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==} - - '@ethersproject/json-wallets@5.7.0': - resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==} - - '@ethersproject/keccak256@5.7.0': - resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} - - '@ethersproject/logger@5.7.0': - resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} - - '@ethersproject/networks@5.7.1': - resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} - - '@ethersproject/pbkdf2@5.7.0': - resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==} - - '@ethersproject/properties@5.7.0': - resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} - - '@ethersproject/providers@5.7.2': - resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==} - - '@ethersproject/random@5.7.0': - resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==} - - '@ethersproject/rlp@5.7.0': - resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} - - '@ethersproject/sha2@5.7.0': - resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==} - - '@ethersproject/signing-key@5.7.0': - resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} - - '@ethersproject/solidity@5.7.0': - resolution: {integrity: sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==} - - '@ethersproject/strings@5.7.0': - resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} - - '@ethersproject/transactions@5.7.0': - resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} - - '@ethersproject/units@5.7.0': - resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==} - - '@ethersproject/wallet@5.7.0': - resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==} - - '@ethersproject/web@5.7.1': - resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} - - '@ethersproject/wordlists@5.7.0': - resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==} - - '@fastify/busboy@2.1.1': - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - - '@humanwhocodes/config-array@0.13.0': - resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead - - '@iden3/bigarray@0.0.2': - resolution: {integrity: sha512-Xzdyxqm1bOFF6pdIsiHLLl3HkSLjbhqJHVyqaTxXt3RqXBEnmsUmEW47H7VOi/ak7TdkRpNkxjyK5Zbkm+y52g==} - - '@iden3/binfileutils@0.0.11': - resolution: {integrity: sha512-LylnJoZ0CTdgErnKY8OxohvW4K+p6UHD3sxt+3P9AmMyBQjYR4IpoqoYZZ+9aMj89cmCQ21UvdhndAx04er3NA==} - - '@iden3/binfileutils@0.0.12': - resolution: {integrity: sha512-naAmzuDufRIcoNfQ1d99d7hGHufLA3wZSibtr4dMe6ZeiOPV1KwOZWTJ1YVz4HbaWlpDuzVU72dS4ATQS4PXBQ==} - - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - - '@istanbuljs/load-nyc-config@1.1.0': - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - - '@istanbuljs/schema@0.1.3': - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - - '@jest/console@29.7.0': - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/core@29.7.0': - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/environment@29.7.0': - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect-utils@29.7.0': - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect@29.7.0': - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/fake-timers@29.7.0': - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/globals@29.7.0': - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/reporters@29.7.0': - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/source-map@29.6.3': - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-result@29.7.0': - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-sequencer@29.7.0': - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/transform@29.7.0': - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/types@29.6.3': - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - - '@metamask/eth-sig-util@4.0.1': - resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} - engines: {node: '>=12.0.0'} - - '@noble/curves@1.2.0': - resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} - - '@noble/curves@1.4.2': - resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - - '@noble/hashes@1.2.0': - resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} - - '@noble/hashes@1.3.2': - resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} - engines: {node: '>= 16'} - - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - - '@noble/hashes@1.6.1': - resolution: {integrity: sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==} - engines: {node: ^14.21.3 || >=16} - - '@noble/secp256k1@1.7.1': - resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@nomicfoundation/edr-darwin-arm64@0.6.5': - resolution: {integrity: sha512-A9zCCbbNxBpLgjS1kEJSpqxIvGGAX4cYbpDYCU2f3jVqOwaZ/NU761y1SvuCRVpOwhoCXqByN9b7HPpHi0L4hw==} - engines: {node: '>= 18'} - - '@nomicfoundation/edr-darwin-x64@0.6.5': - resolution: {integrity: sha512-x3zBY/v3R0modR5CzlL6qMfFMdgwd6oHrWpTkuuXnPFOX8SU31qq87/230f4szM+ukGK8Hi+mNq7Ro2VF4Fj+w==} - engines: {node: '>= 18'} - - '@nomicfoundation/edr-linux-arm64-gnu@0.6.5': - resolution: {integrity: sha512-HGpB8f1h8ogqPHTyUpyPRKZxUk2lu061g97dOQ/W4CxevI0s/qiw5DB3U3smLvSnBHKOzYS1jkxlMeGN01ky7A==} - engines: {node: '>= 18'} - - '@nomicfoundation/edr-linux-arm64-musl@0.6.5': - resolution: {integrity: sha512-ESvJM5Y9XC03fZg9KaQg3Hl+mbx7dsSkTIAndoJS7X2SyakpL9KZpOSYrDk135o8s9P9lYJdPOyiq+Sh+XoCbQ==} - engines: {node: '>= 18'} - - '@nomicfoundation/edr-linux-x64-gnu@0.6.5': - resolution: {integrity: sha512-HCM1usyAR1Ew6RYf5AkMYGvHBy64cPA5NMbaeY72r0mpKaH3txiMyydcHibByOGdQ8iFLWpyUdpl1egotw+Tgg==} - engines: {node: '>= 18'} - - '@nomicfoundation/edr-linux-x64-musl@0.6.5': - resolution: {integrity: sha512-nB2uFRyczhAvWUH7NjCsIO6rHnQrof3xcCe6Mpmnzfl2PYcGyxN7iO4ZMmRcQS7R1Y670VH6+8ZBiRn8k43m7A==} - engines: {node: '>= 18'} - - '@nomicfoundation/edr-win32-x64-msvc@0.6.5': - resolution: {integrity: sha512-B9QD/4DSSCFtWicO8A3BrsnitO1FPv7axB62wq5Q+qeJ50yJlTmyeGY3cw62gWItdvy2mh3fRM6L1LpnHiB77A==} - engines: {node: '>= 18'} - - '@nomicfoundation/edr@0.6.5': - resolution: {integrity: sha512-tAqMslLP+/2b2sZP4qe9AuGxG3OkQ5gGgHE4isUuq6dUVjwCRPFhAOhpdFl+OjY5P3yEv3hmq9HjUGRa2VNjng==} - engines: {node: '>= 18'} - - '@nomicfoundation/ethereumjs-common@4.0.4': - resolution: {integrity: sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==} - - '@nomicfoundation/ethereumjs-rlp@5.0.4': - resolution: {integrity: sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==} - engines: {node: '>=18'} - hasBin: true - - '@nomicfoundation/ethereumjs-tx@5.0.4': - resolution: {integrity: sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==} - engines: {node: '>=18'} - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true - - '@nomicfoundation/ethereumjs-util@9.0.4': - resolution: {integrity: sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==} - engines: {node: '>=18'} - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true - - '@nomicfoundation/hardhat-chai-matchers@2.0.6': - resolution: {integrity: sha512-Te1Uyo9oJcTCF0Jy9dztaLpshmlpjLf2yPtWXlXuLjMt3RRSmJLm/+rKVTW6gfadAEs12U/it6D0ZRnnRGiICQ==} - peerDependencies: - '@nomicfoundation/hardhat-ethers': ^3.0.0 - chai: ^4.2.0 - ethers: ^6.1.0 - hardhat: ^2.9.4 - - '@nomicfoundation/hardhat-ethers@3.0.8': - resolution: {integrity: sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==} - peerDependencies: - ethers: ^6.1.0 - hardhat: ^2.0.0 - - '@nomicfoundation/hardhat-ignition-ethers@0.15.4': - resolution: {integrity: sha512-vY30V4b788GSziW/nOd0L/4IPw6mwpluahLs4+gPUUKWaHHGMA8OIeHaYpRRljM1i0M/Kg1yIozrDM/aeRebkg==} - peerDependencies: - '@nomicfoundation/hardhat-ethers': ^3.0.4 - '@nomicfoundation/hardhat-ignition': ^0.15.4 - '@nomicfoundation/ignition-core': ^0.15.4 - ethers: ^6.7.0 - hardhat: ^2.18.0 - - '@nomicfoundation/hardhat-ignition@0.15.4': - resolution: {integrity: sha512-x1lhLN9ZRSJ9eiNY9AoinMdeQeU4LDQSQOIw90W9DiZIG/g9YUzcTEIY58QTi2TZOF8YFiF6vJqLSePCpi8R1Q==} - peerDependencies: - '@nomicfoundation/hardhat-verify': ^2.0.1 - hardhat: ^2.18.0 - - '@nomicfoundation/hardhat-network-helpers@1.0.12': - resolution: {integrity: sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==} - peerDependencies: - hardhat: ^2.9.5 - - '@nomicfoundation/hardhat-toolbox@5.0.0': - resolution: {integrity: sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==} - peerDependencies: - '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 - '@nomicfoundation/hardhat-ethers': ^3.0.0 - '@nomicfoundation/hardhat-ignition-ethers': ^0.15.0 - '@nomicfoundation/hardhat-network-helpers': ^1.0.0 - '@nomicfoundation/hardhat-verify': ^2.0.0 - '@typechain/ethers-v6': ^0.5.0 - '@typechain/hardhat': ^9.0.0 - '@types/chai': ^4.2.0 - '@types/mocha': '>=9.1.0' - '@types/node': '>=18.0.0' - chai: ^4.2.0 - ethers: ^6.4.0 - hardhat: ^2.11.0 - hardhat-gas-reporter: ^1.0.8 - solidity-coverage: ^0.8.1 - ts-node: '>=8.0.0' - typechain: ^8.3.0 - typescript: '>=4.5.0' - - '@nomicfoundation/hardhat-verify@2.0.7': - resolution: {integrity: sha512-jiYHBX+K6bBN0YhwFHQ5SWWc3dQZliM3pdgpH33C7tnsVACsX1ubZn6gZ9hfwlzG0tyjFM72XQhpaXQ56cE6Ew==} - peerDependencies: - hardhat: ^2.0.4 - - '@nomicfoundation/ignition-core@0.15.4': - resolution: {integrity: sha512-i379lH+xOLFdaDv0KiNma550ZXCHc5ZkmKYhM44xyLMKBlvX6skUVFkgUjjN1gvprgOIxc17GVQXlR1R5FhGZA==} - - '@nomicfoundation/ignition-ui@0.15.8': - resolution: {integrity: sha512-VUD5MsWrrv7E2P0AJO01pV8w8m66Du0uwBKXM0oUV5DRIzqm6eYHt9eCDb1KBINDpiFxOQiuyWQMdeKxgPp3qw==} - - '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2': - resolution: {integrity: sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==} - engines: {node: '>= 12'} - - '@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2': - resolution: {integrity: sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==} - engines: {node: '>= 12'} - - '@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2': - resolution: {integrity: sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==} - engines: {node: '>= 12'} - - '@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2': - resolution: {integrity: sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==} - engines: {node: '>= 12'} - - '@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2': - resolution: {integrity: sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==} - engines: {node: '>= 12'} - - '@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2': - resolution: {integrity: sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==} - engines: {node: '>= 12'} - - '@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2': - resolution: {integrity: sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==} - engines: {node: '>= 12'} - - '@nomicfoundation/solidity-analyzer@0.1.2': - resolution: {integrity: sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==} - engines: {node: '>= 12'} - - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - - '@pkgr/core@0.1.1': - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - - '@rollup/plugin-alias@5.1.1': - resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-commonjs@26.0.3': - resolution: {integrity: sha512-2BJcolt43MY+y5Tz47djHkodCC3c1VKVrBDKpVqHKpQ9z9S158kCCqB8NF6/gzxLdNlYW9abB3Ibh+kOWLp8KQ==} - engines: {node: '>=16.0.0 || 14 >= 14.17'} - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-inject@5.0.5': - resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-json@6.1.0': - resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-node-resolve@15.3.0': - resolution: {integrity: sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-replace@5.0.7': - resolution: {integrity: sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/pluginutils@5.1.3': - resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/rollup-android-arm-eabi@4.28.0': - resolution: {integrity: sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.28.0': - resolution: {integrity: sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.28.0': - resolution: {integrity: sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.28.0': - resolution: {integrity: sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.28.0': - resolution: {integrity: sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.28.0': - resolution: {integrity: sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.28.0': - resolution: {integrity: sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.28.0': - resolution: {integrity: sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.28.0': - resolution: {integrity: sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.28.0': - resolution: {integrity: sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-powerpc64le-gnu@4.28.0': - resolution: {integrity: sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.28.0': - resolution: {integrity: sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.28.0': - resolution: {integrity: sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.28.0': - resolution: {integrity: sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.28.0': - resolution: {integrity: sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-win32-arm64-msvc@4.28.0': - resolution: {integrity: sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.28.0': - resolution: {integrity: sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.28.0': - resolution: {integrity: sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==} - cpu: [x64] - os: [win32] - - '@scure/base@1.1.9': - resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} - - '@scure/bip32@1.1.5': - resolution: {integrity: sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==} - - '@scure/bip32@1.4.0': - resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} - - '@scure/bip39@1.1.1': - resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} - - '@scure/bip39@1.3.0': - resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} - - '@sentry/core@5.30.0': - resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} - engines: {node: '>=6'} - - '@sentry/hub@5.30.0': - resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} - engines: {node: '>=6'} - - '@sentry/minimal@5.30.0': - resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} - engines: {node: '>=6'} - - '@sentry/node@5.30.0': - resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} - engines: {node: '>=6'} - - '@sentry/tracing@5.30.0': - resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} - engines: {node: '>=6'} - - '@sentry/types@5.30.0': - resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} - engines: {node: '>=6'} - - '@sentry/utils@5.30.0': - resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} - engines: {node: '>=6'} - - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - - '@sinonjs/fake-timers@10.3.0': - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - - '@solidity-parser/parser@0.14.5': - resolution: {integrity: sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==} - - '@solidity-parser/parser@0.18.0': - resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} - - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - - '@typechain/ethers-v6@0.5.1': - resolution: {integrity: sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==} - peerDependencies: - ethers: 6.x - typechain: ^8.3.2 - typescript: '>=4.7.0' - - '@typechain/hardhat@9.1.0': - resolution: {integrity: sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==} - peerDependencies: - '@typechain/ethers-v6': ^0.5.1 - ethers: ^6.1.0 - hardhat: ^2.9.9 - typechain: ^8.3.2 - - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.6.8': - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.20.6': - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - - '@types/bn.js@4.11.6': - resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} - - '@types/bn.js@5.1.6': - resolution: {integrity: sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==} - - '@types/chai-as-promised@7.1.8': - resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} - - '@types/chai@4.3.16': - resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} - - '@types/concat-stream@1.6.1': - resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} - - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - - '@types/form-data@0.0.33': - resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} - - '@types/glob@7.2.0': - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - - '@types/graceful-fs@4.1.9': - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - - '@types/istanbul-lib-coverage@2.0.6': - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - - '@types/istanbul-lib-report@3.0.3': - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - - '@types/istanbul-reports@3.0.4': - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - - '@types/jest@29.5.14': - resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/lru-cache@5.1.1': - resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} - - '@types/minimatch@5.1.2': - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - - '@types/mocha@10.0.6': - resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} - - '@types/node@10.17.60': - resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} - - '@types/node@18.19.67': - resolution: {integrity: sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ==} - - '@types/node@22.7.5': - resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} - - '@types/node@8.10.66': - resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} - - '@types/pbkdf2@3.1.2': - resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} - - '@types/prettier@2.7.3': - resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} - - '@types/qs@6.9.17': - resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==} - - '@types/resolve@1.20.2': - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - - '@types/secp256k1@4.0.6': - resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} - - '@types/semver@7.5.8': - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - - '@types/snarkjs@0.7.8': - resolution: {integrity: sha512-x37Jsv1vx6I6RMJdfvYEmDUOLYgzYMecwlk13gniDOcN20xLVe9hy9DlQxWeCPirqpDY/jwugQSqCi2RxehU3g==} - - '@types/stack-utils@2.0.3': - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - - '@types/yargs-parser@21.0.3': - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - '@types/yargs@17.0.33': - resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - - '@typescript-eslint/eslint-plugin@6.21.0': - resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/parser@6.21.0': - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/scope-manager@6.21.0': - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@typescript-eslint/type-utils@6.21.0': - resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/types@6.21.0': - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@typescript-eslint/typescript-estree@6.21.0': - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/utils@6.21.0': - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - - '@typescript-eslint/visitor-keys@6.21.0': - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - - abbrev@1.0.9: - resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - - adm-zip@0.4.16: - resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} - engines: {node: '>=0.3.0'} - - aes-js@3.0.0: - resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} - - aes-js@4.0.0-beta.5: - resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} - - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - - aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - - amdefine@1.0.1: - resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} - engines: {node: '>=0.4.2'} - - ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - - ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - - ansi-regex@3.0.1: - resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} - engines: {node: '>=4'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - antlr4ts@0.5.0-alpha.4: - resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-back@3.1.0: - resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} - engines: {node: '>=6'} - - array-back@4.0.2: - resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} - engines: {node: '>=8'} - - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - - array-uniq@1.0.3: - resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} - engines: {node: '>=0.10.0'} - - asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - - astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - - async@1.5.2: - resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} - - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - axios@1.7.8: - resolution: {integrity: sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==} - - b4a@1.6.7: - resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} - - babel-jest@29.7.0: - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - - babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - - babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - babel-preset-current-node-syntax@1.1.0: - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 - - babel-preset-jest@29.6.3: - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base-x@3.0.10: - resolution: {integrity: sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==} - - bech32@1.1.4: - resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} - - bfj@7.1.0: - resolution: {integrity: sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==} - engines: {node: '>= 8.0.0'} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - blake2b-wasm@2.4.0: - resolution: {integrity: sha512-S1kwmW2ZhZFFFOghcx73+ZajEfKBqhP82JMssxtLVMxlaPea1p9uoLiUZ5WYyHn0KddwbLc+0vh4wR0KBNoT5w==} - - blakejs@1.2.1: - resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} - - bluebird@3.7.2: - resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - - bn.js@4.11.6: - resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} - - bn.js@4.12.1: - resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} - - bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - - boxen@5.1.2: - resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} - engines: {node: '>=10'} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - - browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - - browserify-aes@1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} - - browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - - bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} - - bs58check@2.1.2: - resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} - - bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - buffer-xor@1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} - - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - caniuse-lite@1.0.30001684: - resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==} - - caseless@0.12.0: - resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - - cbor@8.1.0: - resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} - engines: {node: '>=12.19'} - - cbor@9.0.2: - resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} - engines: {node: '>=16'} - - chai-as-promised@7.1.2: - resolution: {integrity: sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==} - peerDependencies: - chai: '>= 2.1.2 < 6' - - chai@4.5.0: - resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} - engines: {node: '>=4'} - - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - - charenc@0.0.2: - resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} - - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - check-types@11.2.3: - resolution: {integrity: sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==} - - child_process@1.0.2: - resolution: {integrity: sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==} - - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - - chokidar@4.0.1: - resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} - engines: {node: '>= 14.16.0'} - - ci-info@2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} - - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - - cipher-base@1.0.6: - resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} - engines: {node: '>= 0.10'} - - circom_runtime@0.1.21: - resolution: {integrity: sha512-qTkud630B/GK8y76hnOaaS1aNuF6prfV0dTrkeRsiJKnlP1ryQbP2FWLgDOPqn6aKyaPlam+Z+DTbBhkEzh8dA==} - hasBin: true - - circom_runtime@0.1.28: - resolution: {integrity: sha512-ACagpQ7zBRLKDl5xRZ4KpmYIcZDUjOiNRuxvXLqhnnlLSVY1Dbvh73TI853nqoR0oEbihtWmMSjgc5f+pXf/jQ==} - hasBin: true - - circom_tester@0.0.19: - resolution: {integrity: sha512-SNHaBsGxcBH6XsVWfsRbRPA7NF8m8AMKJI9dtJJCFGUtOTT2+zsoIqAwi50z6XCnO4TtjyXq7AeXa1PLHqT0tw==} - - cjs-module-lexer@1.4.1: - resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} - - clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - - cli-boxes@2.2.1: - resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} - engines: {node: '>=6'} - - cli-table3@0.5.1: - resolution: {integrity: sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==} - engines: {node: '>=6'} - - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - - co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - - collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - colors@1.4.0: - resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} - engines: {node: '>=0.1.90'} - - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - - command-exists@1.2.9: - resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} - - command-line-args@5.2.1: - resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} - engines: {node: '>=4.0.0'} - - command-line-usage@6.1.3: - resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} - engines: {node: '>=8.0.0'} - - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} - engines: {node: '>=18'} - - commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - concat-stream@1.6.2: - resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} - engines: {'0': node >= 0.8} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - - core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} - - create-hmac@1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - - create-jest@29.7.0: - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - crypt@0.0.2: - resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} - - death@1.1.0: - resolution: {integrity: sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==} - - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - - dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - - deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - - detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - - diff@5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} - engines: {node: '>=0.3.1'} - - difflib@0.2.4: - resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} - - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - - electron-to-chromium@1.5.67: - resolution: {integrity: sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ==} - - elliptic@6.5.4: - resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} - - elliptic@6.6.1: - resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} - - emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} - - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - - es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - esbuild@0.23.1: - resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} - engines: {node: '>=18'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - escodegen@1.14.3: - resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} - engines: {node: '>=4.0'} - hasBin: true - - escodegen@1.8.1: - resolution: {integrity: sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==} - engines: {node: '>=0.12.0'} - hasBin: true - - eslint-config-prettier@9.1.0: - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-plugin-es@3.0.1: - resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=4.19.1' - - eslint-plugin-node@11.1.0: - resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=5.16.0' - - eslint-plugin-prettier@5.2.1: - resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '*' - prettier: '>=3.0.0' - peerDependenciesMeta: - '@types/eslint': - optional: true - eslint-config-prettier: - optional: true - - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-utils@2.1.0: - resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} - engines: {node: '>=6'} - - eslint-visitor-keys@1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint@8.57.1: - resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. - hasBin: true - - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - esprima@1.2.2: - resolution: {integrity: sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==} - engines: {node: '>=0.4.0'} - hasBin: true - - esprima@2.7.3: - resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} - engines: {node: '>=0.10.0'} - hasBin: true - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@1.9.3: - resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} - engines: {node: '>=0.10.0'} - - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - eth-gas-reporter@0.2.27: - resolution: {integrity: sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==} - peerDependencies: - '@codechecks/client': ^0.1.0 - peerDependenciesMeta: - '@codechecks/client': - optional: true - - ethereum-bloom-filters@1.2.0: - resolution: {integrity: sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==} - - ethereum-cryptography@0.1.3: - resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} - - ethereum-cryptography@1.2.0: - resolution: {integrity: sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==} - - ethereum-cryptography@2.2.1: - resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} - - ethereumjs-abi@0.6.8: - resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} - deprecated: This library has been deprecated and usage is discouraged. - - ethereumjs-util@6.2.1: - resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} - - ethereumjs-util@7.1.5: - resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} - engines: {node: '>=10.0.0'} - - ethers@5.7.2: - resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==} - - ethers@6.13.4: - resolution: {integrity: sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==} - engines: {node: '>=14.0.0'} - - ethjs-unit@0.1.6: - resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} - engines: {node: '>=6.5.0', npm: '>=3'} - - ethjs-util@0.1.6: - resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} - engines: {node: '>=6.5.0', npm: '>=3'} - - evp_bytestokey@1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} - - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - - expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fast-uri@3.0.3: - resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - - fastfile@0.0.20: - resolution: {integrity: sha512-r5ZDbgImvVWCP0lA/cGNgQcZqR+aYdFx3u+CtJqUE510pBUVGMn4ulL/iRTI4tACTYsNJ736uzFxEBXesPAktA==} - - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - - fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - - fdir@6.4.2: - resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - ffjavascript@0.2.56: - resolution: {integrity: sha512-em6G5Lrj7ucIqj4TYEgyoHs/j99Urwwqa4+YxEVY2hggnpRimVj+noX5pZQTxI1pvtiekZI4rG65JBf0xraXrg==} - - ffjavascript@0.2.63: - resolution: {integrity: sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==} - - ffjavascript@0.3.0: - resolution: {integrity: sha512-l7sR5kmU3gRwDy8g0Z2tYBXy5ttmafRPFOqY7S6af5cq51JqJWt5eQ/lSR/rs2wQNbDYaYlQr5O+OSUf/oMLoQ==} - - ffjavascript@0.3.1: - resolution: {integrity: sha512-4PbK1WYodQtuF47D4pRI5KUg3Q392vuP5WjE1THSnceHdXwU3ijaoS0OqxTzLknCtz4Z2TtABzkBdBdMn3B/Aw==} - - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-replace@3.0.0: - resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} - engines: {node: '>=4.0.0'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - - flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - - fnv-plus@1.3.1: - resolution: {integrity: sha512-Gz1EvfOneuFfk4yG458dJ3TLJ7gV19q3OM/vVvvHf7eT02Hm1DleB4edsia6ahbKgAYxO9gvyQ1ioWZR+a00Yw==} - - follow-redirects@1.15.9: - resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - - foreground-child@3.3.0: - resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} - engines: {node: '>=14'} - - form-data@2.5.2: - resolution: {integrity: sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==} - engines: {node: '>= 0.12'} - - form-data@4.0.1: - resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} - engines: {node: '>= 6'} - - fp-ts@1.19.3: - resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} - - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - - fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} - - fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - - fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} - - fs-readdir-recursive@1.1.0: - resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - - get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - - get-port@3.2.0: - resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} - engines: {node: '>=4'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - ghost-testrpc@0.0.2: - resolution: {integrity: sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==} - hasBin: true - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - - glob@5.0.15: - resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} - deprecated: Glob versions prior to v9 are no longer supported - - glob@7.1.7: - resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} - deprecated: Glob versions prior to v9 are no longer supported - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported - - global-modules@2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} - - global-prefix@3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - - globby@10.0.2: - resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} - engines: {node: '>=8'} - - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - - gopd@1.1.0: - resolution: {integrity: sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA==} - engines: {node: '>= 0.4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true - - hardhat-gas-reporter@1.0.10: - resolution: {integrity: sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==} - peerDependencies: - hardhat: ^2.0.2 - - hardhat@2.22.16: - resolution: {integrity: sha512-d52yQZ09u0roL6GlgJSvtknsBtIuj9JrJ/U8VMzr/wue+gO5v2tQayvOX6llerlR57Zw2EOTQjLAt6RpHvjwHA==} - hasBin: true - peerDependencies: - ts-node: '*' - typescript: '*' - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true - - has-flag@1.0.0: - resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} - engines: {node: '>=0.10.0'} - - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hash-base@3.1.0: - resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} - engines: {node: '>=4'} - - hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - - heap@0.2.7: - resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} - - hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - - hoopy@0.1.4: - resolution: {integrity: sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==} - engines: {node: '>= 6.0.0'} - - html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - - http-basic@8.1.3: - resolution: {integrity: sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==} - engines: {node: '>=6.0.0'} - - http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - - http-response-object@3.0.2: - resolution: {integrity: sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==} - - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - immer@10.0.2: - resolution: {integrity: sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==} - - immutable@4.3.7: - resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - - interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - - io-ts@1.10.4: - resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} - - is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.15.1: - resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@2.0.0: - resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} - engines: {node: '>=4'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - - is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-hex-prefixed@1.0.0: - resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} - engines: {node: '>=6.5.0', npm: '>=3'} - - is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - - is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - - is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - istanbul-lib-coverage@3.2.2: - resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} - engines: {node: '>=8'} - - istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - - istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - - istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} - - istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - - istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} - engines: {node: '>=8'} - - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - - jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-cli@29.7.0: - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - jest-config@29.7.0: - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - - jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-pnp-resolver@1.2.3: - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - - jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest@29.7.0: - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json-stream-stringify@3.1.6: - resolution: {integrity: sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==} - engines: {node: '>=7.10.1'} - - json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - - jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - - jsonpath@1.1.1: - resolution: {integrity: sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==} - - jsonschema@1.4.1: - resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} - - keccak@3.0.4: - resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} - engines: {node: '>=10.0.0'} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - - kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - - leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - - levn@0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - - lodash.clonedeep@4.5.0: - resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} - - lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - loglevel@1.9.2: - resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} - engines: {node: '>= 0.6.0'} - - logplease@1.2.15: - resolution: {integrity: sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==} - - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - lru_map@0.3.3: - resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} - - magic-string@0.30.14: - resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==} - - make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - - markdown-table@1.1.3: - resolution: {integrity: sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==} - - md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} - - memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micro-ftch@0.3.1: - resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - - minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - - minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - - mnemonist@0.38.5: - resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} - - mocha@10.8.2: - resolution: {integrity: sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==} - engines: {node: '>= 14.0.0'} - hasBin: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoassert@2.0.0: - resolution: {integrity: sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==} - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - ndjson@2.0.0: - resolution: {integrity: sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==} - engines: {node: '>=10'} - hasBin: true - - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - - node-addon-api@2.0.2: - resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} - - node-addon-api@5.1.0: - resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} - - node-emoji@1.11.0: - resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} - - node-gyp-build@4.8.4: - resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} - hasBin: true - - node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - - nofilter@3.1.0: - resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} - engines: {node: '>=12.19'} - - nopt@3.0.6: - resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} - hasBin: true - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - number-to-bn@1.7.0: - resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} - engines: {node: '>=6.5.0', npm: '>=3'} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} - engines: {node: '>= 0.4'} - - obliterator@2.0.4: - resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - optionator@0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - ordinal@1.0.3: - resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} - - os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse-cache-control@1.0.1: - resolution: {integrity: sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==} - - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - - pbkdf2@3.1.2: - resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} - engines: {node: '>=0.12'} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} - engines: {node: '>=12'} - - pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - - pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - - pkgroll@2.5.1: - resolution: {integrity: sha512-rehzSpQ1T/gh+tlVSxlUeqUPR9W1ZtJXDG00cuussNeCPdS9w1Wv0MWxwL116HbugsTZTrd+lVem+ipinT2JUg==} - engines: {node: '>=18'} - hasBin: true - peerDependencies: - typescript: ^4.1 || ^5.0 - peerDependenciesMeta: - typescript: - optional: true - - possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - - prelude-ls@1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - - prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - - prettier@3.4.1: - resolution: {integrity: sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==} - engines: {node: '>=14'} - hasBin: true - - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - promise@8.3.0: - resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} - - prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - - qs@6.13.1: - resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} - engines: {node: '>=0.6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - r1csfile@0.0.41: - resolution: {integrity: sha512-Q1WDF3u1vYeAwjHo4YuddkA8Aq0TulbKjmGm99+Atn13Lf5fTsMZBnBV9T741w8iSyPFG6Uh6sapQby77sREqA==} - - r1csfile@0.0.48: - resolution: {integrity: sha512-kHRkKUJNaor31l05f2+RFzvcH5XSa7OfEfd/l4hzjte6NL6fjRkSMfZ4BjySW9wmfdwPOtq3mXurzPvPGEf5Tw==} - - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - - raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - - readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - readdirp@4.0.2: - resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} - engines: {node: '>= 14.16.0'} - - rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - - recursive-readdir@2.2.3: - resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} - engines: {node: '>=6.0.0'} - - reduce-flatten@2.0.0: - resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} - engines: {node: '>=6'} - - regexpp@3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - - req-cwd@2.0.0: - resolution: {integrity: sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==} - engines: {node: '>=4'} - - req-from@2.0.0: - resolution: {integrity: sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==} - engines: {node: '>=4'} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - - resolve-from@3.0.0: - resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} - engines: {node: '>=4'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - resolve.exports@2.0.2: - resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} - engines: {node: '>=10'} - - resolve@1.1.7: - resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} - - resolve@1.17.0: - resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} - - resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - - ripemd160@2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} - - rlp@2.2.7: - resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} - hasBin: true - - rollup@4.28.0: - resolution: {integrity: sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - sc-istanbul@0.4.6: - resolution: {integrity: sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==} - hasBin: true - - scrypt-js@3.0.1: - resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} - - secp256k1@4.0.4: - resolution: {integrity: sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==} - engines: {node: '>=18.0.0'} - - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - sha.js@2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true - - sha1@1.1.1: - resolution: {integrity: sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - - side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - - snarkjs@0.5.0: - resolution: {integrity: sha512-KWz8mZ2Y+6wvn6GGkQo6/ZlKwETdAGohd40Lzpwp5TUZCn6N6O4Az1SuX1rw/qREGL6Im+ycb19suCFE8/xaKA==} - hasBin: true - - snarkjs@0.7.5: - resolution: {integrity: sha512-h+3c4rXZKLhLuHk4LHydZCk/h5GcNvk5GjVKRRkHmfb6Ntf8gHOA9zea3g656iclRuhqQ3iKDWFgiD9ypLrKiA==} - hasBin: true - - solc@0.8.26: - resolution: {integrity: sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==} - engines: {node: '>=10.0.0'} - hasBin: true - - solc@0.8.28: - resolution: {integrity: sha512-AFCiJ+b4RosyyNhnfdVH4ZR1+TxiL91iluPjw0EJslIu4LXGM9NYqi2z5y8TqochC4tcH9QsHfwWhOIC9jPDKA==} - engines: {node: '>=10.0.0'} - hasBin: true - - solidity-coverage@0.8.12: - resolution: {integrity: sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw==} - hasBin: true - peerDependencies: - hardhat: ^2.11.0 - - source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.2.0: - resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} - engines: {node: '>=0.8.0'} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - split2@3.2.2: - resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} - - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - - stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} - - stacktrace-parser@0.1.10: - resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} - engines: {node: '>=6'} - - static-eval@2.0.2: - resolution: {integrity: sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==} - - statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - - string-format@2.0.0: - resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} - - string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - - string-width@2.1.1: - resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} - engines: {node: '>=4'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - - string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@4.0.0: - resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} - engines: {node: '>=4'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - - strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-hex-prefix@1.0.0: - resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} - engines: {node: '>=6.5.0', npm: '>=3'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - supports-color@3.2.3: - resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} - engines: {node: '>=0.8.0'} - - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - sync-request@6.1.0: - resolution: {integrity: sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==} - engines: {node: '>=8.0.0'} - - sync-rpc@1.3.6: - resolution: {integrity: sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==} - - synckit@0.9.2: - resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} - engines: {node: ^14.18.0 || >=16.0.0} - - table-layout@1.0.2: - resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} - engines: {node: '>=8.0.0'} - - table@6.8.2: - resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} - engines: {node: '>=10.0.0'} - - test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - - then-request@6.0.2: - resolution: {integrity: sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==} - engines: {node: '>=6.0.0'} - - through2@4.0.2: - resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} - - tinyglobby@0.2.10: - resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} - engines: {node: '>=12.0.0'} - - tmp-promise@3.0.3: - resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} - - tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - - tmp@0.2.3: - resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} - engines: {node: '>=14.14'} - - tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - - tryer@1.0.1: - resolution: {integrity: sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==} - - ts-api-utils@1.4.3: - resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - - ts-command-line-args@2.5.1: - resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} - hasBin: true - - ts-essentials@7.0.3: - resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} - peerDependencies: - typescript: '>=3.7.0' - - ts-jest@29.2.5: - resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - - tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - - tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - tsort@0.0.1: - resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} - - tweetnacl-util@0.15.1: - resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} - - tweetnacl@1.0.3: - resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} - - type-check@0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - type-detect@4.1.0: - resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} - engines: {node: '>=4'} - - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - type-fest@0.7.1: - resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} - engines: {node: '>=8'} - - typechain@8.3.2: - resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} - hasBin: true - peerDependencies: - typescript: '>=4.3.0' - - typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - - typescript@5.7.2: - resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} - engines: {node: '>=14.17'} - hasBin: true - - typical@4.0.0: - resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} - engines: {node: '>=8'} - - typical@5.2.0: - resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} - engines: {node: '>=8'} - - uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} - engines: {node: '>=0.8.0'} - hasBin: true - - underscore@1.12.1: - resolution: {integrity: sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==} - - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - - undici@5.28.4: - resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} - engines: {node: '>=14.0'} - - universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - - update-browserslist-db@1.1.1: - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - utf8@3.0.0: - resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - - v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} - - walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - - wasmbuilder@0.0.16: - resolution: {integrity: sha512-Qx3lEFqaVvp1cEYW7Bfi+ebRJrOiwz2Ieu7ZG2l7YyeSJIok/reEQCQCuicj/Y32ITIJuGIM9xZQppGx5LrQdA==} - - wasmcurves@0.2.0: - resolution: {integrity: sha512-3e2rbxdujOwaod657gxgmdhZNn+i1qKdHO3Y/bK+8E7bV8ttV/fu5FO4/WLBACF375cK0QDLOP+65Na63qYuWA==} - - wasmcurves@0.2.2: - resolution: {integrity: sha512-JRY908NkmKjFl4ytnTu5ED6AwPD+8VJ9oc94kdq7h5bIwbj0L4TDJ69mG+2aLs2SoCmGfqIesMWTEJjtYsoQXQ==} - - web-worker@1.2.0: - resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==} - - web-worker@1.3.0: - resolution: {integrity: sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==} - - web3-utils@1.10.4: - resolution: {integrity: sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==} - engines: {node: '>=8.0.0'} - - which-typed-array@1.1.16: - resolution: {integrity: sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==} - engines: {node: '>= 0.4'} - - which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - widest-line@3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - - wordwrapjs@4.0.1: - resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} - engines: {node: '>=8.0.0'} - - workerpool@6.5.1: - resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - ws@7.4.6: - resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} - - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@adraffy/ens-normalize@1.10.1': {} - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - - '@babel/code-frame@7.26.2': - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.26.2': {} - - '@babel/core@7.26.0': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.2 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.2 - '@babel/template': 7.25.9 - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 - convert-source-map: 2.0.0 - debug: 4.3.7(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.26.2': - dependencies: - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.0.2 - - '@babel/helper-compilation-targets@7.25.9': - dependencies: - '@babel/compat-data': 7.26.2 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-module-imports@7.25.9': - dependencies: - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.25.9 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.25.9': {} - - '@babel/helper-string-parser@7.25.9': {} - - '@babel/helper-validator-identifier@7.25.9': {} - - '@babel/helper-validator-option@7.25.9': {} - - '@babel/helpers@7.26.0': - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 - - '@babel/parser@7.26.2': - dependencies: - '@babel/types': 7.26.0 - - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/template@7.25.9': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - - '@babel/traverse@7.25.9': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 - debug: 4.3.7(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - '@babel/types@7.26.0': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - - '@bcoe/v8-coverage@0.2.3': {} - - '@commander-js/extra-typings@12.1.0(commander@12.1.0)': - dependencies: - commander: 12.1.0 - - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - - '@esbuild/aix-ppc64@0.23.1': - optional: true - - '@esbuild/android-arm64@0.23.1': - optional: true - - '@esbuild/android-arm@0.23.1': - optional: true - - '@esbuild/android-x64@0.23.1': - optional: true - - '@esbuild/darwin-arm64@0.23.1': - optional: true - - '@esbuild/darwin-x64@0.23.1': - optional: true - - '@esbuild/freebsd-arm64@0.23.1': - optional: true - - '@esbuild/freebsd-x64@0.23.1': - optional: true - - '@esbuild/linux-arm64@0.23.1': - optional: true - - '@esbuild/linux-arm@0.23.1': - optional: true - - '@esbuild/linux-ia32@0.23.1': - optional: true - - '@esbuild/linux-loong64@0.23.1': - optional: true - - '@esbuild/linux-mips64el@0.23.1': - optional: true - - '@esbuild/linux-ppc64@0.23.1': - optional: true - - '@esbuild/linux-riscv64@0.23.1': - optional: true - - '@esbuild/linux-s390x@0.23.1': - optional: true - - '@esbuild/linux-x64@0.23.1': - optional: true - - '@esbuild/netbsd-x64@0.23.1': - optional: true - - '@esbuild/openbsd-arm64@0.23.1': - optional: true - - '@esbuild/openbsd-x64@0.23.1': - optional: true - - '@esbuild/sunos-x64@0.23.1': - optional: true - - '@esbuild/win32-arm64@0.23.1': - optional: true - - '@esbuild/win32-ia32@0.23.1': - optional: true - - '@esbuild/win32-x64@0.23.1': - optional: true - - '@eslint-community/eslint-utils@4.4.1(eslint@8.57.1)': - dependencies: - eslint: 8.57.1 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.1': {} - - '@eslint/eslintrc@2.1.4': - dependencies: - ajv: 6.12.6 - debug: 4.3.7(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@8.57.1': {} - - '@ethereumjs/rlp@4.0.1': {} - - '@ethereumjs/util@8.1.0': - dependencies: - '@ethereumjs/rlp': 4.0.1 - ethereum-cryptography: 2.2.1 - micro-ftch: 0.3.1 - - '@ethersproject/abi@5.7.0': - dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - - '@ethersproject/abstract-provider@5.7.0': - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 - - '@ethersproject/abstract-signer@5.7.0': - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - - '@ethersproject/address@5.6.1': - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/rlp': 5.7.0 - - '@ethersproject/address@5.7.0': - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/rlp': 5.7.0 - - '@ethersproject/base64@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - - '@ethersproject/basex@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/properties': 5.7.0 - - '@ethersproject/bignumber@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - bn.js: 5.2.1 - - '@ethersproject/bytes@5.7.0': - dependencies: - '@ethersproject/logger': 5.7.0 - - '@ethersproject/constants@5.7.0': - dependencies: - '@ethersproject/bignumber': 5.7.0 - - '@ethersproject/contracts@5.7.0': - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 - - '@ethersproject/hash@5.7.0': - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - - '@ethersproject/hdnode@5.7.0': - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 - - '@ethersproject/json-wallets@5.7.0': - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - aes-js: 3.0.0 - scrypt-js: 3.0.1 - - '@ethersproject/keccak256@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - js-sha3: 0.8.0 - - '@ethersproject/logger@5.7.0': {} - - '@ethersproject/networks@5.7.1': - dependencies: - '@ethersproject/logger': 5.7.0 - - '@ethersproject/pbkdf2@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/sha2': 5.7.0 - - '@ethersproject/properties@5.7.0': - dependencies: - '@ethersproject/logger': 5.7.0 - - '@ethersproject/providers@5.7.2': - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 - bech32: 1.1.4 - ws: 7.4.6 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@ethersproject/random@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - - '@ethersproject/rlp@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - - '@ethersproject/sha2@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - hash.js: 1.1.7 - - '@ethersproject/signing-key@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - bn.js: 5.2.1 - elliptic: 6.5.4 - hash.js: 1.1.7 - - '@ethersproject/solidity@5.7.0': - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 - - '@ethersproject/strings@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - - '@ethersproject/transactions@5.7.0': - dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - - '@ethersproject/units@5.7.0': - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - - '@ethersproject/wallet@5.7.0': - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/json-wallets': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 - - '@ethersproject/web@5.7.1': - dependencies: - '@ethersproject/base64': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - - '@ethersproject/wordlists@5.7.0': - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - - '@fastify/busboy@2.1.1': {} - - '@humanwhocodes/config-array@0.13.0': - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.7(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/object-schema@2.0.3': {} - - '@iden3/bigarray@0.0.2': {} - - '@iden3/binfileutils@0.0.11': - dependencies: - fastfile: 0.0.20 - ffjavascript: 0.2.63 - - '@iden3/binfileutils@0.0.12': - dependencies: - fastfile: 0.0.20 - ffjavascript: 0.3.1 - - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - '@istanbuljs/load-nyc-config@1.1.0': - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - - '@istanbuljs/schema@0.1.3': {} - - '@jest/console@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - '@jest/environment@29.7.0': - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - jest-mock: 29.7.0 - - '@jest/expect-utils@29.7.0': - dependencies: - jest-get-type: 29.6.3 - - '@jest/expect@29.7.0': - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 18.19.67 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - '@jest/globals@29.7.0': - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/reporters@29.7.0': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 18.19.67 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - - '@jest/source-map@29.6.3': - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - '@jest/test-result@29.7.0': - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - - '@jest/test-sequencer@29.7.0': - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - - '@jest/transform@29.7.0': - dependencies: - '@babel/core': 7.26.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.6 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - - '@jest/types@29.6.3': - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 18.19.67 - '@types/yargs': 17.0.33 - chalk: 4.1.2 - - '@jridgewell/gen-mapping@0.3.5': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@metamask/eth-sig-util@4.0.1': - dependencies: - ethereumjs-abi: 0.6.8 - ethereumjs-util: 6.2.1 - ethjs-util: 0.1.6 - tweetnacl: 1.0.3 - tweetnacl-util: 0.15.1 - - '@noble/curves@1.2.0': - dependencies: - '@noble/hashes': 1.3.2 - - '@noble/curves@1.4.2': - dependencies: - '@noble/hashes': 1.4.0 - - '@noble/hashes@1.2.0': {} - - '@noble/hashes@1.3.2': {} - - '@noble/hashes@1.4.0': {} - - '@noble/hashes@1.6.1': {} - - '@noble/secp256k1@1.7.1': {} - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - - '@nomicfoundation/edr-darwin-arm64@0.6.5': {} - - '@nomicfoundation/edr-darwin-x64@0.6.5': {} - - '@nomicfoundation/edr-linux-arm64-gnu@0.6.5': {} - - '@nomicfoundation/edr-linux-arm64-musl@0.6.5': {} - - '@nomicfoundation/edr-linux-x64-gnu@0.6.5': {} - - '@nomicfoundation/edr-linux-x64-musl@0.6.5': {} - - '@nomicfoundation/edr-win32-x64-msvc@0.6.5': {} - - '@nomicfoundation/edr@0.6.5': - dependencies: - '@nomicfoundation/edr-darwin-arm64': 0.6.5 - '@nomicfoundation/edr-darwin-x64': 0.6.5 - '@nomicfoundation/edr-linux-arm64-gnu': 0.6.5 - '@nomicfoundation/edr-linux-arm64-musl': 0.6.5 - '@nomicfoundation/edr-linux-x64-gnu': 0.6.5 - '@nomicfoundation/edr-linux-x64-musl': 0.6.5 - '@nomicfoundation/edr-win32-x64-msvc': 0.6.5 - - '@nomicfoundation/ethereumjs-common@4.0.4': - dependencies: - '@nomicfoundation/ethereumjs-util': 9.0.4 - transitivePeerDependencies: - - c-kzg - - '@nomicfoundation/ethereumjs-rlp@5.0.4': {} - - '@nomicfoundation/ethereumjs-tx@5.0.4': - dependencies: - '@nomicfoundation/ethereumjs-common': 4.0.4 - '@nomicfoundation/ethereumjs-rlp': 5.0.4 - '@nomicfoundation/ethereumjs-util': 9.0.4 - ethereum-cryptography: 0.1.3 - - '@nomicfoundation/ethereumjs-util@9.0.4': - dependencies: - '@nomicfoundation/ethereumjs-rlp': 5.0.4 - ethereum-cryptography: 0.1.3 - - '@nomicfoundation/hardhat-chai-matchers@2.0.6(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(chai@4.5.0)(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))': - dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@types/chai-as-promised': 7.1.8 - chai: 4.5.0 - chai-as-promised: 7.1.2(chai@4.5.0) - deep-eql: 4.1.4 - ethers: 6.13.4 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - ordinal: 1.0.3 - - '@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))': - dependencies: - debug: 4.3.7(supports-color@8.1.1) - ethers: 6.13.4 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - lodash.isequal: 4.5.0 - transitivePeerDependencies: - - supports-color - - '@nomicfoundation/hardhat-ignition-ethers@0.15.4(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(@nomicfoundation/hardhat-ignition@0.15.4(@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(@nomicfoundation/ignition-core@0.15.4)(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))': - dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/hardhat-ignition': 0.15.4(@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/ignition-core': 0.15.4 - ethers: 6.13.4 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - - '@nomicfoundation/hardhat-ignition@0.15.4(@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))': - dependencies: - '@nomicfoundation/hardhat-verify': 2.0.7(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/ignition-core': 0.15.4 - '@nomicfoundation/ignition-ui': 0.15.8 - chalk: 4.1.2 - debug: 4.3.7(supports-color@8.1.1) - fs-extra: 10.1.0 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - prompts: 2.4.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - '@nomicfoundation/hardhat-network-helpers@1.0.12(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))': - dependencies: - ethereumjs-util: 7.1.5 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - - '@nomicfoundation/hardhat-toolbox@5.0.0(gxul7wxp54ybnadymvfaa7s5hm)': - dependencies: - '@nomicfoundation/hardhat-chai-matchers': 2.0.6(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(chai@4.5.0)(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/hardhat-ignition-ethers': 0.15.4(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(@nomicfoundation/hardhat-ignition@0.15.4(@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)))(@nomicfoundation/ignition-core@0.15.4)(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/hardhat-network-helpers': 1.0.12(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@nomicfoundation/hardhat-verify': 2.0.7(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - '@typechain/ethers-v6': 0.5.1(ethers@6.13.4)(typechain@8.3.2(typescript@5.7.2))(typescript@5.7.2) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.4)(typechain@8.3.2(typescript@5.7.2))(typescript@5.7.2))(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))(typechain@8.3.2(typescript@5.7.2)) - '@types/chai': 4.3.16 - '@types/mocha': 10.0.6 - '@types/node': 18.19.67 - chai: 4.5.0 - ethers: 6.13.4 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - hardhat-gas-reporter: 1.0.10(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - solidity-coverage: 0.8.12(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)) - ts-node: 10.9.2(@types/node@18.19.67)(typescript@5.7.2) - typechain: 8.3.2(typescript@5.7.2) - typescript: 5.7.2 - - '@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))': - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/address': 5.7.0 - cbor: 8.1.0 - chalk: 2.4.2 - debug: 4.3.7(supports-color@8.1.1) - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - lodash.clonedeep: 4.5.0 - semver: 6.3.1 - table: 6.8.2 - undici: 5.28.4 - transitivePeerDependencies: - - supports-color - - '@nomicfoundation/ignition-core@0.15.4': - dependencies: - '@ethersproject/address': 5.6.1 - '@nomicfoundation/solidity-analyzer': 0.1.2 - cbor: 9.0.2 - debug: 4.3.7(supports-color@8.1.1) - ethers: 6.13.4 - fs-extra: 10.1.0 - immer: 10.0.2 - lodash: 4.17.21 - ndjson: 2.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - '@nomicfoundation/ignition-ui@0.15.8': {} - - '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2': - optional: true - - '@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2': - optional: true - - '@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2': - optional: true - - '@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2': - optional: true - - '@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2': - optional: true - - '@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2': - optional: true - - '@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2': - optional: true - - '@nomicfoundation/solidity-analyzer@0.1.2': - optionalDependencies: - '@nomicfoundation/solidity-analyzer-darwin-arm64': 0.1.2 - '@nomicfoundation/solidity-analyzer-darwin-x64': 0.1.2 - '@nomicfoundation/solidity-analyzer-linux-arm64-gnu': 0.1.2 - '@nomicfoundation/solidity-analyzer-linux-arm64-musl': 0.1.2 - '@nomicfoundation/solidity-analyzer-linux-x64-gnu': 0.1.2 - '@nomicfoundation/solidity-analyzer-linux-x64-musl': 0.1.2 - '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.2 - - '@pkgjs/parseargs@0.11.0': - optional: true - - '@pkgr/core@0.1.1': {} - - '@rollup/plugin-alias@5.1.1(rollup@4.28.0)': - optionalDependencies: - rollup: 4.28.0 - - '@rollup/plugin-commonjs@26.0.3(rollup@4.28.0)': - dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.0) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 10.4.5 - is-reference: 1.2.1 - magic-string: 0.30.14 - optionalDependencies: - rollup: 4.28.0 - - '@rollup/plugin-inject@5.0.5(rollup@4.28.0)': - dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.0) - estree-walker: 2.0.2 - magic-string: 0.30.14 - optionalDependencies: - rollup: 4.28.0 - - '@rollup/plugin-json@6.1.0(rollup@4.28.0)': - dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.0) - optionalDependencies: - rollup: 4.28.0 - - '@rollup/plugin-node-resolve@15.3.0(rollup@4.28.0)': - dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.0) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.8 - optionalDependencies: - rollup: 4.28.0 - - '@rollup/plugin-replace@5.0.7(rollup@4.28.0)': - dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.0) - magic-string: 0.30.14 - optionalDependencies: - rollup: 4.28.0 - - '@rollup/pluginutils@5.1.3(rollup@4.28.0)': - dependencies: - '@types/estree': 1.0.6 - estree-walker: 2.0.2 - picomatch: 4.0.2 - optionalDependencies: - rollup: 4.28.0 - - '@rollup/rollup-android-arm-eabi@4.28.0': - optional: true - - '@rollup/rollup-android-arm64@4.28.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.28.0': - optional: true - - '@rollup/rollup-darwin-x64@4.28.0': - optional: true - - '@rollup/rollup-freebsd-arm64@4.28.0': - optional: true - - '@rollup/rollup-freebsd-x64@4.28.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.28.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.28.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.28.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.28.0': - optional: true - - '@rollup/rollup-linux-powerpc64le-gnu@4.28.0': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.28.0': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.28.0': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.28.0': - optional: true - - '@rollup/rollup-linux-x64-musl@4.28.0': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.28.0': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.28.0': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.28.0': - optional: true - - '@scure/base@1.1.9': {} - - '@scure/bip32@1.1.5': - dependencies: - '@noble/hashes': 1.2.0 - '@noble/secp256k1': 1.7.1 - '@scure/base': 1.1.9 - - '@scure/bip32@1.4.0': - dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.9 - - '@scure/bip39@1.1.1': - dependencies: - '@noble/hashes': 1.2.0 - '@scure/base': 1.1.9 - - '@scure/bip39@1.3.0': - dependencies: - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.9 - - '@sentry/core@5.30.0': - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/minimal': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - - '@sentry/hub@5.30.0': - dependencies: - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - - '@sentry/minimal@5.30.0': - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/types': 5.30.0 - tslib: 1.14.1 - - '@sentry/node@5.30.0': - dependencies: - '@sentry/core': 5.30.0 - '@sentry/hub': 5.30.0 - '@sentry/tracing': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - cookie: 0.4.2 - https-proxy-agent: 5.0.1 - lru_map: 0.3.3 - tslib: 1.14.1 - transitivePeerDependencies: - - supports-color - - '@sentry/tracing@5.30.0': - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/minimal': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - - '@sentry/types@5.30.0': {} - - '@sentry/utils@5.30.0': - dependencies: - '@sentry/types': 5.30.0 - tslib: 1.14.1 - - '@sinclair/typebox@0.27.8': {} - - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 - - '@sinonjs/fake-timers@10.3.0': - dependencies: - '@sinonjs/commons': 3.0.1 - - '@solidity-parser/parser@0.14.5': - dependencies: - antlr4ts: 0.5.0-alpha.4 - - '@solidity-parser/parser@0.18.0': {} - - '@tsconfig/node10@1.0.11': {} - - '@tsconfig/node12@1.0.11': {} - - '@tsconfig/node14@1.0.3': {} - - '@tsconfig/node16@1.0.4': {} - - '@typechain/ethers-v6@0.5.1(ethers@6.13.4)(typechain@8.3.2(typescript@5.7.2))(typescript@5.7.2)': - dependencies: - ethers: 6.13.4 - lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@5.7.2) - typechain: 8.3.2(typescript@5.7.2) - typescript: 5.7.2 - - '@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.4)(typechain@8.3.2(typescript@5.7.2))(typescript@5.7.2))(ethers@6.13.4)(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2))(typechain@8.3.2(typescript@5.7.2))': - dependencies: - '@typechain/ethers-v6': 0.5.1(ethers@6.13.4)(typechain@8.3.2(typescript@5.7.2))(typescript@5.7.2) - ethers: 6.13.4 - fs-extra: 9.1.0 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - typechain: 8.3.2(typescript@5.7.2) - - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 - - '@types/babel__generator@7.6.8': - dependencies: - '@babel/types': 7.26.0 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - - '@types/babel__traverse@7.20.6': - dependencies: - '@babel/types': 7.26.0 - - '@types/bn.js@4.11.6': - dependencies: - '@types/node': 18.19.67 - - '@types/bn.js@5.1.6': - dependencies: - '@types/node': 18.19.67 - - '@types/chai-as-promised@7.1.8': - dependencies: - '@types/chai': 4.3.16 - - '@types/chai@4.3.16': {} - - '@types/concat-stream@1.6.1': - dependencies: - '@types/node': 18.19.67 - - '@types/estree@1.0.6': {} - - '@types/form-data@0.0.33': - dependencies: - '@types/node': 18.19.67 - - '@types/glob@7.2.0': - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 18.19.67 - - '@types/graceful-fs@4.1.9': - dependencies: - '@types/node': 18.19.67 - - '@types/istanbul-lib-coverage@2.0.6': {} - - '@types/istanbul-lib-report@3.0.3': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - - '@types/istanbul-reports@3.0.4': - dependencies: - '@types/istanbul-lib-report': 3.0.3 - - '@types/jest@29.5.14': - dependencies: - expect: 29.7.0 - pretty-format: 29.7.0 - - '@types/json-schema@7.0.15': {} - - '@types/lru-cache@5.1.1': {} - - '@types/minimatch@5.1.2': {} - - '@types/mocha@10.0.6': {} - - '@types/node@10.17.60': {} - - '@types/node@18.19.67': - dependencies: - undici-types: 5.26.5 - - '@types/node@22.7.5': - dependencies: - undici-types: 6.19.8 - - '@types/node@8.10.66': {} - - '@types/pbkdf2@3.1.2': - dependencies: - '@types/node': 18.19.67 - - '@types/prettier@2.7.3': {} - - '@types/qs@6.9.17': {} - - '@types/resolve@1.20.2': {} - - '@types/secp256k1@4.0.6': - dependencies: - '@types/node': 18.19.67 - - '@types/semver@7.5.8': {} - - '@types/snarkjs@0.7.8': {} - - '@types/stack-utils@2.0.3': {} - - '@types/yargs-parser@21.0.3': {} - - '@types/yargs@17.0.33': - dependencies: - '@types/yargs-parser': 21.0.3 - - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)': - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.7.2) - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.7.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7(supports-color@8.1.1) - eslint: 8.57.1 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - semver: 7.6.3 - ts-api-utils: 1.4.3(typescript@5.7.2) - optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.7.2)': - dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7(supports-color@8.1.1) - eslint: 8.57.1 - optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@6.21.0': - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - - '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.7.2)': - dependencies: - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.7.2) - '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.7.2) - debug: 4.3.7(supports-color@8.1.1) - eslint: 8.57.1 - ts-api-utils: 1.4.3(typescript@5.7.2) - optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@6.21.0': {} - - '@typescript-eslint/typescript-estree@6.21.0(typescript@5.7.2)': - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7(supports-color@8.1.1) - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.3 - ts-api-utils: 1.4.3(typescript@5.7.2) - optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.7.2)': - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.7.2) - eslint: 8.57.1 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/visitor-keys@6.21.0': - dependencies: - '@typescript-eslint/types': 6.21.0 - eslint-visitor-keys: 3.4.3 - - '@ungap/structured-clone@1.2.0': {} - - abbrev@1.0.9: {} - - acorn-jsx@5.3.2(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn-walk@8.3.4: - dependencies: - acorn: 8.14.0 - - acorn@8.14.0: {} - - adm-zip@0.4.16: {} - - aes-js@3.0.0: {} - - aes-js@4.0.0-beta.5: {} - - agent-base@6.0.2: - dependencies: - debug: 4.3.7(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - aggregate-error@3.1.0: - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.0.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - amdefine@1.0.1: - optional: true - - ansi-align@3.0.1: - dependencies: - string-width: 4.2.3 - - ansi-colors@4.1.3: {} - - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 - - ansi-regex@3.0.1: {} - - ansi-regex@5.0.1: {} - - ansi-regex@6.1.0: {} - - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@5.2.0: {} - - ansi-styles@6.2.1: {} - - antlr4ts@0.5.0-alpha.4: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - arg@4.1.3: {} - - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 - - argparse@2.0.1: {} - - array-back@3.1.0: {} - - array-back@4.0.2: {} - - array-union@2.1.0: {} - - array-uniq@1.0.3: {} - - asap@2.0.6: {} - - assertion-error@1.1.0: {} - - astral-regex@2.0.0: {} - - async@1.5.2: {} - - async@3.2.6: {} - - asynckit@0.4.0: {} - - at-least-node@1.0.0: {} - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.0.0 - - axios@1.7.8: - dependencies: - follow-redirects: 1.15.9(debug@4.3.7) - form-data: 4.0.1 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - - b4a@1.6.7: {} - - babel-jest@29.7.0(@babel/core@7.26.0): - dependencies: - '@babel/core': 7.26.0 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.26.0) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-istanbul@6.1.1: - dependencies: - '@babel/helper-plugin-utils': 7.25.9 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-jest-hoist@29.6.3: - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.6 - - babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.0): - dependencies: - '@babel/core': 7.26.0 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.0) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.0) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.0) - '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.0) - - babel-preset-jest@29.6.3(@babel/core@7.26.0): - dependencies: - '@babel/core': 7.26.0 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) - - balanced-match@1.0.2: {} - - base-x@3.0.10: - dependencies: - safe-buffer: 5.2.1 - - bech32@1.1.4: {} - - bfj@7.1.0: - dependencies: - bluebird: 3.7.2 - check-types: 11.2.3 - hoopy: 0.1.4 - jsonpath: 1.1.1 - tryer: 1.0.1 - - binary-extensions@2.3.0: {} - - blake2b-wasm@2.4.0: - dependencies: - b4a: 1.6.7 - nanoassert: 2.0.0 - - blakejs@1.2.1: {} - - bluebird@3.7.2: {} - - bn.js@4.11.6: {} - - bn.js@4.12.1: {} - - bn.js@5.2.1: {} - - boxen@5.1.2: - dependencies: - ansi-align: 3.0.1 - camelcase: 6.3.0 - chalk: 4.1.2 - cli-boxes: 2.2.1 - string-width: 4.2.3 - type-fest: 0.20.2 - widest-line: 3.1.0 - wrap-ansi: 7.0.0 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - brorand@1.1.0: {} - - browser-stdout@1.3.1: {} - - browserify-aes@1.2.0: - dependencies: - buffer-xor: 1.0.3 - cipher-base: 1.0.6 - create-hash: 1.2.0 - evp_bytestokey: 1.0.3 - inherits: 2.0.4 - safe-buffer: 5.2.1 - - browserslist@4.24.2: - dependencies: - caniuse-lite: 1.0.30001684 - electron-to-chromium: 1.5.67 - node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.2) - - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 - - bs58@4.0.1: - dependencies: - base-x: 3.0.10 - - bs58check@2.1.2: - dependencies: - bs58: 4.0.1 - create-hash: 1.2.0 - safe-buffer: 5.2.1 - - bser@2.1.1: - dependencies: - node-int64: 0.4.0 - - buffer-from@1.1.2: {} - - buffer-xor@1.0.3: {} - - bytes@3.1.2: {} - - call-bind@1.0.7: - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - - callsites@3.1.0: {} - - camelcase@5.3.1: {} - - camelcase@6.3.0: {} - - caniuse-lite@1.0.30001684: {} - - caseless@0.12.0: {} - - cbor@8.1.0: - dependencies: - nofilter: 3.1.0 - - cbor@9.0.2: - dependencies: - nofilter: 3.1.0 - - chai-as-promised@7.1.2(chai@4.5.0): - dependencies: - chai: 4.5.0 - check-error: 1.0.3 - - chai@4.5.0: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.1.0 - - chalk@2.4.2: - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - char-regex@1.0.2: {} - - charenc@0.0.2: {} - - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - - check-types@11.2.3: {} - - child_process@1.0.2: {} - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - chokidar@4.0.1: - dependencies: - readdirp: 4.0.2 - - ci-info@2.0.0: {} - - ci-info@3.9.0: {} - - cipher-base@1.0.6: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - - circom_runtime@0.1.21: - dependencies: - ffjavascript: 0.2.56 - - circom_runtime@0.1.28: - dependencies: - ffjavascript: 0.3.1 - - circom_tester@0.0.19: - dependencies: - chai: 4.5.0 - child_process: 1.0.2 - ffjavascript: 0.2.63 - fnv-plus: 1.3.1 - r1csfile: 0.0.41 - snarkjs: 0.5.0 - tmp-promise: 3.0.3 - util: 0.12.5 - - cjs-module-lexer@1.4.1: {} - - clean-stack@2.2.0: {} - - cli-boxes@2.2.1: {} - - cli-table3@0.5.1: - dependencies: - object-assign: 4.1.1 - string-width: 2.1.1 - optionalDependencies: - colors: 1.4.0 - - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - co@4.6.0: {} - - collect-v8-coverage@1.0.2: {} - - color-convert@1.9.3: - dependencies: - color-name: 1.1.3 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.3: {} - - color-name@1.1.4: {} - - colors@1.4.0: {} - - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - - command-exists@1.2.9: {} - - command-line-args@5.2.1: - dependencies: - array-back: 3.1.0 - find-replace: 3.0.0 - lodash.camelcase: 4.3.0 - typical: 4.0.0 - - command-line-usage@6.1.3: - dependencies: - array-back: 4.0.2 - chalk: 2.4.2 - table-layout: 1.0.2 - typical: 5.2.0 - - commander@12.1.0: {} - - commander@8.3.0: {} - - commondir@1.0.1: {} - - concat-map@0.0.1: {} - - concat-stream@1.6.2: - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 2.3.8 - typedarray: 0.0.6 - - convert-source-map@2.0.0: {} - - cookie@0.4.2: {} - - core-util-is@1.0.3: {} - - create-hash@1.2.0: - dependencies: - cipher-base: 1.0.6 - inherits: 2.0.4 - md5.js: 1.3.5 - ripemd160: 2.0.2 - sha.js: 2.4.11 - - create-hmac@1.1.7: - dependencies: - cipher-base: 1.0.6 - create-hash: 1.2.0 - inherits: 2.0.4 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - - create-jest@29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - create-require@1.1.1: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - crypt@0.0.2: {} - - death@1.1.0: {} - - debug@4.3.7(supports-color@8.1.1): - dependencies: - ms: 2.1.3 - optionalDependencies: - supports-color: 8.1.1 - - decamelize@4.0.0: {} - - dedent@1.5.3: {} - - deep-eql@4.1.4: - dependencies: - type-detect: 4.1.0 - - deep-extend@0.6.0: {} - - deep-is@0.1.4: {} - - deepmerge@4.3.1: {} - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.1.0 - - delayed-stream@1.0.0: {} - - depd@2.0.0: {} - - detect-newline@3.1.0: {} - - diff-sequences@29.6.3: {} - - diff@4.0.2: {} - - diff@5.2.0: {} - - difflib@0.2.4: - dependencies: - heap: 0.2.7 - - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - - eastasianwidth@0.2.0: {} - - ejs@3.1.10: - dependencies: - jake: 10.9.2 - - electron-to-chromium@1.5.67: {} - - elliptic@6.5.4: - dependencies: - bn.js: 4.12.1 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - - elliptic@6.6.1: - dependencies: - bn.js: 4.12.1 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - - emittery@0.13.1: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - - enquirer@2.4.1: - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - - env-paths@2.2.1: {} - - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - - es-define-property@1.0.0: - dependencies: - get-intrinsic: 1.2.4 - - es-errors@1.3.0: {} - - esbuild@0.23.1: - optionalDependencies: - '@esbuild/aix-ppc64': 0.23.1 - '@esbuild/android-arm': 0.23.1 - '@esbuild/android-arm64': 0.23.1 - '@esbuild/android-x64': 0.23.1 - '@esbuild/darwin-arm64': 0.23.1 - '@esbuild/darwin-x64': 0.23.1 - '@esbuild/freebsd-arm64': 0.23.1 - '@esbuild/freebsd-x64': 0.23.1 - '@esbuild/linux-arm': 0.23.1 - '@esbuild/linux-arm64': 0.23.1 - '@esbuild/linux-ia32': 0.23.1 - '@esbuild/linux-loong64': 0.23.1 - '@esbuild/linux-mips64el': 0.23.1 - '@esbuild/linux-ppc64': 0.23.1 - '@esbuild/linux-riscv64': 0.23.1 - '@esbuild/linux-s390x': 0.23.1 - '@esbuild/linux-x64': 0.23.1 - '@esbuild/netbsd-x64': 0.23.1 - '@esbuild/openbsd-arm64': 0.23.1 - '@esbuild/openbsd-x64': 0.23.1 - '@esbuild/sunos-x64': 0.23.1 - '@esbuild/win32-arm64': 0.23.1 - '@esbuild/win32-ia32': 0.23.1 - '@esbuild/win32-x64': 0.23.1 - - escalade@3.2.0: {} - - escape-string-regexp@1.0.5: {} - - escape-string-regexp@2.0.0: {} - - escape-string-regexp@4.0.0: {} - - escodegen@1.14.3: - dependencies: - esprima: 4.0.1 - estraverse: 4.3.0 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.6.1 - - escodegen@1.8.1: - dependencies: - esprima: 2.7.3 - estraverse: 1.9.3 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.2.0 - - eslint-config-prettier@9.1.0(eslint@8.57.1): - dependencies: - eslint: 8.57.1 - - eslint-plugin-es@3.0.1(eslint@8.57.1): - dependencies: - eslint: 8.57.1 - eslint-utils: 2.1.0 - regexpp: 3.2.0 - - eslint-plugin-node@11.1.0(eslint@8.57.1): - dependencies: - eslint: 8.57.1 - eslint-plugin-es: 3.0.1(eslint@8.57.1) - eslint-utils: 2.1.0 - ignore: 5.3.2 - minimatch: 3.1.2 - resolve: 1.22.8 - semver: 6.3.1 - - eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.4.1): - dependencies: - eslint: 8.57.1 - prettier: 3.4.1 - prettier-linter-helpers: 1.0.0 - synckit: 0.9.2 - optionalDependencies: - eslint-config-prettier: 9.1.0(eslint@8.57.1) - - eslint-scope@7.2.2: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-utils@2.1.0: - dependencies: - eslint-visitor-keys: 1.3.0 - - eslint-visitor-keys@1.3.0: {} - - eslint-visitor-keys@3.4.3: {} - - eslint@8.57.1: - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) - '@eslint-community/regexpp': 4.12.1 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.1 - '@humanwhocodes/config-array': 0.13.0 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.3.7(supports-color@8.1.1) - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - - espree@9.6.1: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 3.4.3 - - esprima@1.2.2: {} - - esprima@2.7.3: {} - - esprima@4.0.1: {} - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@1.9.3: {} - - estraverse@4.3.0: {} - - estraverse@5.3.0: {} - - estree-walker@2.0.2: {} - - esutils@2.0.3: {} - - eth-gas-reporter@0.2.27: - dependencies: - '@solidity-parser/parser': 0.14.5 - axios: 1.7.8 - cli-table3: 0.5.1 - colors: 1.4.0 - ethereum-cryptography: 1.2.0 - ethers: 5.7.2 - fs-readdir-recursive: 1.1.0 - lodash: 4.17.21 - markdown-table: 1.1.3 - mocha: 10.8.2 - req-cwd: 2.0.0 - sha1: 1.1.1 - sync-request: 6.1.0 - transitivePeerDependencies: - - bufferutil - - debug - - utf-8-validate - - ethereum-bloom-filters@1.2.0: - dependencies: - '@noble/hashes': 1.6.1 - - ethereum-cryptography@0.1.3: - dependencies: - '@types/pbkdf2': 3.1.2 - '@types/secp256k1': 4.0.6 - blakejs: 1.2.1 - browserify-aes: 1.2.0 - bs58check: 2.1.2 - create-hash: 1.2.0 - create-hmac: 1.1.7 - hash.js: 1.1.7 - keccak: 3.0.4 - pbkdf2: 3.1.2 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - scrypt-js: 3.0.1 - secp256k1: 4.0.4 - setimmediate: 1.0.5 - - ethereum-cryptography@1.2.0: - dependencies: - '@noble/hashes': 1.2.0 - '@noble/secp256k1': 1.7.1 - '@scure/bip32': 1.1.5 - '@scure/bip39': 1.1.1 - - ethereum-cryptography@2.2.1: - dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 - - ethereumjs-abi@0.6.8: - dependencies: - bn.js: 4.12.1 - ethereumjs-util: 6.2.1 - - ethereumjs-util@6.2.1: - dependencies: - '@types/bn.js': 4.11.6 - bn.js: 4.12.1 - create-hash: 1.2.0 - elliptic: 6.6.1 - ethereum-cryptography: 0.1.3 - ethjs-util: 0.1.6 - rlp: 2.2.7 - - ethereumjs-util@7.1.5: - dependencies: - '@types/bn.js': 5.1.6 - bn.js: 5.2.1 - create-hash: 1.2.0 - ethereum-cryptography: 0.1.3 - rlp: 2.2.7 - - ethers@5.7.2: - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/contracts': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/json-wallets': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/providers': 5.7.2 - '@ethersproject/random': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/solidity': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/units': 5.7.0 - '@ethersproject/wallet': 5.7.0 - '@ethersproject/web': 5.7.1 - '@ethersproject/wordlists': 5.7.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - ethers@6.13.4: - dependencies: - '@adraffy/ens-normalize': 1.10.1 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@types/node': 22.7.5 - aes-js: 4.0.0-beta.5 - tslib: 2.7.0 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - ethjs-unit@0.1.6: - dependencies: - bn.js: 4.11.6 - number-to-bn: 1.7.0 - - ethjs-util@0.1.6: - dependencies: - is-hex-prefixed: 1.0.0 - strip-hex-prefix: 1.0.0 - - evp_bytestokey@1.0.3: - dependencies: - md5.js: 1.3.5 - safe-buffer: 5.2.1 - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - exit@0.1.2: {} - - expect@29.7.0: - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - - fast-deep-equal@3.1.3: {} - - fast-diff@1.3.0: {} - - fast-glob@3.3.2: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fast-uri@3.0.3: {} - - fastfile@0.0.20: {} - - fastq@1.17.1: - dependencies: - reusify: 1.0.4 - - fb-watchman@2.0.2: - dependencies: - bser: 2.1.1 - - fdir@6.4.2(picomatch@4.0.2): - optionalDependencies: - picomatch: 4.0.2 - - ffjavascript@0.2.56: - dependencies: - wasmbuilder: 0.0.16 - wasmcurves: 0.2.0 - web-worker: 1.3.0 - - ffjavascript@0.2.63: - dependencies: - wasmbuilder: 0.0.16 - wasmcurves: 0.2.2 - web-worker: 1.2.0 - - ffjavascript@0.3.0: - dependencies: - wasmbuilder: 0.0.16 - wasmcurves: 0.2.2 - web-worker: 1.2.0 - - ffjavascript@0.3.1: - dependencies: - wasmbuilder: 0.0.16 - wasmcurves: 0.2.2 - web-worker: 1.2.0 - - file-entry-cache@6.0.1: - dependencies: - flat-cache: 3.2.0 - - filelist@1.0.4: - dependencies: - minimatch: 5.1.6 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-replace@3.0.0: - dependencies: - array-back: 3.1.0 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@3.2.0: - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - rimraf: 3.0.2 - - flat@5.0.2: {} - - flatted@3.3.2: {} - - fnv-plus@1.3.1: {} - - follow-redirects@1.15.9(debug@4.3.7): - optionalDependencies: - debug: 4.3.7(supports-color@8.1.1) - - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - - foreground-child@3.3.0: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - form-data@2.5.2: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - safe-buffer: 5.2.1 - - form-data@4.0.1: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - - fp-ts@1.19.3: {} - - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - - fs-extra@7.0.1: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - - fs-extra@8.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - - fs-extra@9.1.0: - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - - fs-readdir-recursive@1.1.0: {} - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - - get-func-name@2.0.2: {} - - get-intrinsic@1.2.4: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - - get-package-type@0.1.0: {} - - get-port@3.2.0: {} - - get-stream@6.0.1: {} - - ghost-testrpc@0.0.2: - dependencies: - chalk: 2.4.2 - node-emoji: 1.11.0 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@10.4.5: - dependencies: - foreground-child: 3.3.0 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - - glob@5.0.15: - dependencies: - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - glob@7.1.7: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - - global-modules@2.0.0: - dependencies: - global-prefix: 3.0.0 - - global-prefix@3.0.0: - dependencies: - ini: 1.3.8 - kind-of: 6.0.3 - which: 1.3.1 - - globals@11.12.0: {} - - globals@13.24.0: - dependencies: - type-fest: 0.20.2 - - globby@10.0.2: - dependencies: - '@types/glob': 7.2.0 - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - glob: 7.2.3 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 - - globby@11.1.0: - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 - - gopd@1.1.0: - dependencies: - get-intrinsic: 1.2.4 - - graceful-fs@4.2.11: {} - - graphemer@1.4.0: {} - - handlebars@4.7.8: - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - - hardhat-gas-reporter@1.0.10(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)): - dependencies: - array-uniq: 1.0.3 - eth-gas-reporter: 0.2.27 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - sha1: 1.1.1 - transitivePeerDependencies: - - '@codechecks/client' - - bufferutil - - debug - - utf-8-validate - - hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2): - dependencies: - '@ethersproject/abi': 5.7.0 - '@metamask/eth-sig-util': 4.0.1 - '@nomicfoundation/edr': 0.6.5 - '@nomicfoundation/ethereumjs-common': 4.0.4 - '@nomicfoundation/ethereumjs-tx': 5.0.4 - '@nomicfoundation/ethereumjs-util': 9.0.4 - '@nomicfoundation/solidity-analyzer': 0.1.2 - '@sentry/node': 5.30.0 - '@types/bn.js': 5.1.6 - '@types/lru-cache': 5.1.1 - adm-zip: 0.4.16 - aggregate-error: 3.1.0 - ansi-escapes: 4.3.2 - boxen: 5.1.2 - chokidar: 4.0.1 - ci-info: 2.0.0 - debug: 4.3.7(supports-color@8.1.1) - enquirer: 2.4.1 - env-paths: 2.2.1 - ethereum-cryptography: 1.2.0 - ethereumjs-abi: 0.6.8 - find-up: 5.0.0 - fp-ts: 1.19.3 - fs-extra: 7.0.1 - immutable: 4.3.7 - io-ts: 1.10.4 - json-stream-stringify: 3.1.6 - keccak: 3.0.4 - lodash: 4.17.21 - mnemonist: 0.38.5 - mocha: 10.8.2 - p-map: 4.0.0 - picocolors: 1.1.1 - raw-body: 2.5.2 - resolve: 1.17.0 - semver: 6.3.1 - solc: 0.8.26(debug@4.3.7) - source-map-support: 0.5.21 - stacktrace-parser: 0.1.10 - tinyglobby: 0.2.10 - tsort: 0.0.1 - undici: 5.28.4 - uuid: 8.3.2 - ws: 7.5.10 - optionalDependencies: - ts-node: 10.9.2(@types/node@18.19.67)(typescript@5.7.2) - typescript: 5.7.2 - transitivePeerDependencies: - - bufferutil - - c-kzg - - supports-color - - utf-8-validate - - has-flag@1.0.0: {} - - has-flag@3.0.0: {} - - has-flag@4.0.0: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.0 - - has-proto@1.0.3: {} - - has-symbols@1.0.3: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.0.3 - - hash-base@3.1.0: - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.2 - safe-buffer: 5.2.1 - - hash.js@1.1.7: - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - he@1.2.0: {} - - heap@0.2.7: {} - - hmac-drbg@1.0.1: - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - - hoopy@0.1.4: {} - - html-escaper@2.0.2: {} - - http-basic@8.1.3: - dependencies: - caseless: 0.12.0 - concat-stream: 1.6.2 - http-response-object: 3.0.2 - parse-cache-control: 1.0.1 - - http-errors@2.0.0: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - - http-response-object@3.0.2: - dependencies: - '@types/node': 10.17.60 - - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.3.7(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - human-signals@2.1.0: {} - - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - - ignore@5.3.2: {} - - immer@10.0.2: {} - - immutable@4.3.7: {} - - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - - imurmurhash@0.1.4: {} - - indent-string@4.0.0: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - ini@1.3.8: {} - - interpret@1.4.0: {} - - io-ts@1.10.4: - dependencies: - fp-ts: 1.19.3 - - is-arguments@1.1.1: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - - is-arrayish@0.2.1: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-callable@1.2.7: {} - - is-core-module@2.15.1: - dependencies: - hasown: 2.0.2 - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@2.0.0: {} - - is-fullwidth-code-point@3.0.0: {} - - is-generator-fn@2.1.0: {} - - is-generator-function@1.0.10: - dependencies: - has-tostringtag: 1.0.2 - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-hex-prefixed@1.0.0: {} - - is-module@1.0.0: {} - - is-number@7.0.0: {} - - is-path-inside@3.0.3: {} - - is-plain-obj@2.1.0: {} - - is-reference@1.2.1: - dependencies: - '@types/estree': 1.0.6 - - is-stream@2.0.1: {} - - is-typed-array@1.1.13: - dependencies: - which-typed-array: 1.1.16 - - is-unicode-supported@0.1.0: {} - - isarray@1.0.0: {} - - isexe@2.0.0: {} - - istanbul-lib-coverage@3.2.2: {} - - istanbul-lib-instrument@5.2.1: - dependencies: - '@babel/core': 7.26.0 - '@babel/parser': 7.26.2 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - istanbul-lib-instrument@6.0.3: - dependencies: - '@babel/core': 7.26.0 - '@babel/parser': 7.26.2 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - istanbul-lib-report@3.0.1: - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 - - istanbul-lib-source-maps@4.0.1: - dependencies: - debug: 4.3.7(supports-color@8.1.1) - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - - istanbul-reports@3.1.7: - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jake@10.9.2: - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - - jest-changed-files@29.7.0: - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - - jest-circus@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.3 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-cli@29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest-config@29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)): - dependencies: - '@babel/core': 7.26.0 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.0) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 18.19.67 - ts-node: 10.9.2(@types/node@18.19.67)(typescript@5.7.2) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-diff@29.7.0: - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-docblock@29.7.0: - dependencies: - detect-newline: 3.1.0 - - jest-each@29.7.0: - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - - jest-environment-node@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - jest-get-type@29.6.3: {} - - jest-haste-map@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 18.19.67 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - - jest-leak-detector@29.7.0: - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-matcher-utils@29.7.0: - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-message-util@29.7.0: - dependencies: - '@babel/code-frame': 7.26.2 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - - jest-mock@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - jest-util: 29.7.0 - - jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - optionalDependencies: - jest-resolve: 29.7.0 - - jest-regex-util@29.6.3: {} - - jest-resolve-dependencies@29.7.0: - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - jest-resolve@29.7.0: - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.8 - resolve.exports: 2.0.2 - slash: 3.0.0 - - jest-runner@29.7.0: - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - - jest-runtime@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - cjs-module-lexer: 1.4.1 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - - jest-snapshot@29.7.0: - dependencies: - '@babel/core': 7.26.0 - '@babel/generator': 7.26.2 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) - '@babel/types': 7.26.0 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - jest-util@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - - jest-validate@29.7.0: - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - - jest-watcher@29.7.0: - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - - jest-worker@29.7.0: - dependencies: - '@types/node': 18.19.67 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - jest@29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - js-sha3@0.8.0: {} - - js-tokens@4.0.0: {} - - js-yaml@3.14.1: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - jsesc@3.0.2: {} - - json-buffer@3.0.1: {} - - json-parse-even-better-errors@2.3.1: {} - - json-schema-traverse@0.4.1: {} - - json-schema-traverse@1.0.0: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json-stream-stringify@3.1.6: {} - - json-stringify-safe@5.0.1: {} - - json5@2.2.3: {} - - jsonfile@4.0.0: - optionalDependencies: - graceful-fs: 4.2.11 - - jsonfile@6.1.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - jsonpath@1.1.1: - dependencies: - esprima: 1.2.2 - static-eval: 2.0.2 - underscore: 1.12.1 - - jsonschema@1.4.1: {} - - keccak@3.0.4: - dependencies: - node-addon-api: 2.0.2 - node-gyp-build: 4.8.4 - readable-stream: 3.6.2 - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - kind-of@6.0.3: {} - - kleur@3.0.3: {} - - leven@3.1.0: {} - - levn@0.3.0: - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lines-and-columns@1.2.4: {} - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.camelcase@4.3.0: {} - - lodash.clonedeep@4.5.0: {} - - lodash.isequal@4.5.0: {} - - lodash.memoize@4.1.2: {} - - lodash.merge@4.6.2: {} - - lodash.truncate@4.4.2: {} - - lodash@4.17.21: {} - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - loglevel@1.9.2: {} - - logplease@1.2.15: {} - - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - - lru-cache@10.4.3: {} - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - lru_map@0.3.3: {} - - magic-string@0.30.14: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - - make-dir@4.0.0: - dependencies: - semver: 7.6.3 - - make-error@1.3.6: {} - - makeerror@1.0.12: - dependencies: - tmpl: 1.0.5 - - markdown-table@1.1.3: {} - - md5.js@1.3.5: - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - safe-buffer: 5.2.1 - - memorystream@0.3.1: {} - - merge-stream@2.0.0: {} - - merge2@1.4.1: {} - - micro-ftch@0.3.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mimic-fn@2.1.0: {} - - minimalistic-assert@1.0.1: {} - - minimalistic-crypto-utils@1.0.1: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.1 - - minimatch@9.0.3: - dependencies: - brace-expansion: 2.0.1 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.1 - - minimist@1.2.8: {} - - minipass@7.1.2: {} - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - mkdirp@1.0.4: {} - - mnemonist@0.38.5: - dependencies: - obliterator: 2.0.4 - - mocha@10.8.2: - dependencies: - ansi-colors: 4.1.3 - browser-stdout: 1.3.1 - chokidar: 3.6.0 - debug: 4.3.7(supports-color@8.1.1) - diff: 5.2.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 8.1.0 - he: 1.2.0 - js-yaml: 4.1.0 - log-symbols: 4.1.0 - minimatch: 5.1.6 - ms: 2.1.3 - serialize-javascript: 6.0.2 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - workerpool: 6.5.1 - yargs: 16.2.0 - yargs-parser: 20.2.9 - yargs-unparser: 2.0.0 - - ms@2.1.3: {} - - nanoassert@2.0.0: {} - - natural-compare@1.4.0: {} - - ndjson@2.0.0: - dependencies: - json-stringify-safe: 5.0.1 - minimist: 1.2.8 - readable-stream: 3.6.2 - split2: 3.2.2 - through2: 4.0.2 - - neo-async@2.6.2: {} - - node-addon-api@2.0.2: {} - - node-addon-api@5.1.0: {} - - node-emoji@1.11.0: - dependencies: - lodash: 4.17.21 - - node-gyp-build@4.8.4: {} - - node-int64@0.4.0: {} - - node-releases@2.0.18: {} - - nofilter@3.1.0: {} - - nopt@3.0.6: - dependencies: - abbrev: 1.0.9 - - normalize-path@3.0.0: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - number-to-bn@1.7.0: - dependencies: - bn.js: 4.11.6 - strip-hex-prefix: 1.0.0 - - object-assign@4.1.1: {} - - object-inspect@1.13.3: {} - - obliterator@2.0.4: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - optionator@0.8.3: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.5 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - ordinal@1.0.3: {} - - os-tmpdir@1.0.2: {} - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - p-map@4.0.0: - dependencies: - aggregate-error: 3.1.0 - - p-try@2.2.0: {} - - package-json-from-dist@1.0.1: {} - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse-cache-control@1.0.1: {} - - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.26.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-parse@1.0.7: {} - - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - - path-type@4.0.0: {} - - pathval@1.1.1: {} - - pbkdf2@3.1.2: - dependencies: - create-hash: 1.2.0 - create-hmac: 1.1.7 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - picomatch@4.0.2: {} - - pify@4.0.1: {} - - pirates@4.0.6: {} - - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - - pkgroll@2.5.1(typescript@5.7.2): - dependencies: - '@rollup/plugin-alias': 5.1.1(rollup@4.28.0) - '@rollup/plugin-commonjs': 26.0.3(rollup@4.28.0) - '@rollup/plugin-inject': 5.0.5(rollup@4.28.0) - '@rollup/plugin-json': 6.1.0(rollup@4.28.0) - '@rollup/plugin-node-resolve': 15.3.0(rollup@4.28.0) - '@rollup/plugin-replace': 5.0.7(rollup@4.28.0) - '@rollup/pluginutils': 5.1.3(rollup@4.28.0) - esbuild: 0.23.1 - magic-string: 0.30.14 - rollup: 4.28.0 - optionalDependencies: - typescript: 5.7.2 - - possible-typed-array-names@1.0.0: {} - - prelude-ls@1.1.2: {} - - prelude-ls@1.2.1: {} - - prettier-linter-helpers@1.0.0: - dependencies: - fast-diff: 1.3.0 - - prettier@2.8.8: {} - - prettier@3.4.1: {} - - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - process-nextick-args@2.0.1: {} - - promise@8.3.0: - dependencies: - asap: 2.0.6 - - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - - proxy-from-env@1.1.0: {} - - punycode@2.3.1: {} - - pure-rand@6.1.0: {} - - qs@6.13.1: - dependencies: - side-channel: 1.0.6 - - queue-microtask@1.2.3: {} - - r1csfile@0.0.41: - dependencies: - '@iden3/bigarray': 0.0.2 - '@iden3/binfileutils': 0.0.11 - fastfile: 0.0.20 - ffjavascript: 0.2.56 - - r1csfile@0.0.48: - dependencies: - '@iden3/bigarray': 0.0.2 - '@iden3/binfileutils': 0.0.12 - fastfile: 0.0.20 - ffjavascript: 0.3.0 - - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - raw-body@2.5.2: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - - react-is@18.3.1: {} - - readable-stream@2.3.8: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - readdirp@4.0.2: {} - - rechoir@0.6.2: - dependencies: - resolve: 1.22.8 - - recursive-readdir@2.2.3: - dependencies: - minimatch: 3.1.2 - - reduce-flatten@2.0.0: {} - - regexpp@3.2.0: {} - - req-cwd@2.0.0: - dependencies: - req-from: 2.0.0 - - req-from@2.0.0: - dependencies: - resolve-from: 3.0.0 - - require-directory@2.1.1: {} - - require-from-string@2.0.2: {} - - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 - - resolve-from@3.0.0: {} - - resolve-from@4.0.0: {} - - resolve-from@5.0.0: {} - - resolve.exports@2.0.2: {} - - resolve@1.1.7: {} - - resolve@1.17.0: - dependencies: - path-parse: 1.0.7 - - resolve@1.22.8: - dependencies: - is-core-module: 2.15.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - reusify@1.0.4: {} - - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - - ripemd160@2.0.2: - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - - rlp@2.2.7: - dependencies: - bn.js: 5.2.1 - - rollup@4.28.0: - dependencies: - '@types/estree': 1.0.6 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.28.0 - '@rollup/rollup-android-arm64': 4.28.0 - '@rollup/rollup-darwin-arm64': 4.28.0 - '@rollup/rollup-darwin-x64': 4.28.0 - '@rollup/rollup-freebsd-arm64': 4.28.0 - '@rollup/rollup-freebsd-x64': 4.28.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.28.0 - '@rollup/rollup-linux-arm-musleabihf': 4.28.0 - '@rollup/rollup-linux-arm64-gnu': 4.28.0 - '@rollup/rollup-linux-arm64-musl': 4.28.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.28.0 - '@rollup/rollup-linux-riscv64-gnu': 4.28.0 - '@rollup/rollup-linux-s390x-gnu': 4.28.0 - '@rollup/rollup-linux-x64-gnu': 4.28.0 - '@rollup/rollup-linux-x64-musl': 4.28.0 - '@rollup/rollup-win32-arm64-msvc': 4.28.0 - '@rollup/rollup-win32-ia32-msvc': 4.28.0 - '@rollup/rollup-win32-x64-msvc': 4.28.0 - fsevents: 2.3.3 - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - safe-buffer@5.1.2: {} - - safe-buffer@5.2.1: {} - - safer-buffer@2.1.2: {} - - sc-istanbul@0.4.6: - dependencies: - abbrev: 1.0.9 - async: 1.5.2 - escodegen: 1.8.1 - esprima: 2.7.3 - glob: 5.0.15 - handlebars: 4.7.8 - js-yaml: 3.14.1 - mkdirp: 0.5.6 - nopt: 3.0.6 - once: 1.4.0 - resolve: 1.1.7 - supports-color: 3.2.3 - which: 1.3.1 - wordwrap: 1.0.0 - - scrypt-js@3.0.1: {} - - secp256k1@4.0.4: - dependencies: - elliptic: 6.6.1 - node-addon-api: 5.1.0 - node-gyp-build: 4.8.4 - - semver@5.7.2: {} - - semver@6.3.1: {} - - semver@7.6.3: {} - - serialize-javascript@6.0.2: - dependencies: - randombytes: 2.1.0 - - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.1.0 - has-property-descriptors: 1.0.2 - - setimmediate@1.0.5: {} - - setprototypeof@1.2.0: {} - - sha.js@2.4.11: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - - sha1@1.1.1: - dependencies: - charenc: 0.0.2 - crypt: 0.0.2 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - shelljs@0.8.5: - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - - side-channel@1.0.6: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.3 - - signal-exit@3.0.7: {} - - signal-exit@4.1.0: {} - - sisteransi@1.0.5: {} - - slash@3.0.0: {} - - slice-ansi@4.0.0: - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - - snarkjs@0.5.0: - dependencies: - '@iden3/binfileutils': 0.0.11 - bfj: 7.1.0 - blake2b-wasm: 2.4.0 - circom_runtime: 0.1.21 - ejs: 3.1.10 - fastfile: 0.0.20 - ffjavascript: 0.2.56 - js-sha3: 0.8.0 - logplease: 1.2.15 - r1csfile: 0.0.41 - - snarkjs@0.7.5: - dependencies: - '@iden3/binfileutils': 0.0.12 - bfj: 7.1.0 - blake2b-wasm: 2.4.0 - circom_runtime: 0.1.28 - ejs: 3.1.10 - fastfile: 0.0.20 - ffjavascript: 0.3.1 - js-sha3: 0.8.0 - logplease: 1.2.15 - r1csfile: 0.0.48 - - solc@0.8.26(debug@4.3.7): - dependencies: - command-exists: 1.2.9 - commander: 8.3.0 - follow-redirects: 1.15.9(debug@4.3.7) - js-sha3: 0.8.0 - memorystream: 0.3.1 - semver: 5.7.2 - tmp: 0.0.33 - transitivePeerDependencies: - - debug - - solc@0.8.28: - dependencies: - command-exists: 1.2.9 - commander: 8.3.0 - follow-redirects: 1.15.9(debug@4.3.7) - js-sha3: 0.8.0 - memorystream: 0.3.1 - semver: 5.7.2 - tmp: 0.0.33 - transitivePeerDependencies: - - debug - - solidity-coverage@0.8.12(hardhat@2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2)): - dependencies: - '@ethersproject/abi': 5.7.0 - '@solidity-parser/parser': 0.18.0 - chalk: 2.4.2 - death: 1.1.0 - difflib: 0.2.4 - fs-extra: 8.1.0 - ghost-testrpc: 0.0.2 - global-modules: 2.0.0 - globby: 10.0.2 - hardhat: 2.22.16(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2))(typescript@5.7.2) - jsonschema: 1.4.1 - lodash: 4.17.21 - mocha: 10.8.2 - node-emoji: 1.11.0 - pify: 4.0.1 - recursive-readdir: 2.2.3 - sc-istanbul: 0.4.6 - semver: 7.6.3 - shelljs: 0.8.5 - web3-utils: 1.10.4 - - source-map-support@0.5.13: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.2.0: - dependencies: - amdefine: 1.0.1 - optional: true - - source-map@0.6.1: {} - - split2@3.2.2: - dependencies: - readable-stream: 3.6.2 - - sprintf-js@1.0.3: {} - - stack-utils@2.0.6: - dependencies: - escape-string-regexp: 2.0.0 - - stacktrace-parser@0.1.10: - dependencies: - type-fest: 0.7.1 - - static-eval@2.0.2: - dependencies: - escodegen: 1.14.3 - - statuses@2.0.1: {} - - string-format@2.0.0: {} - - string-length@4.0.2: - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - - string-width@2.1.1: - dependencies: - is-fullwidth-code-point: 2.0.0 - strip-ansi: 4.0.0 - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - - string_decoder@1.1.1: - dependencies: - safe-buffer: 5.1.2 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - strip-ansi@4.0.0: - dependencies: - ansi-regex: 3.0.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - - strip-bom@4.0.0: {} - - strip-final-newline@2.0.0: {} - - strip-hex-prefix@1.0.0: - dependencies: - is-hex-prefixed: 1.0.0 - - strip-json-comments@3.1.1: {} - - supports-color@3.2.3: - dependencies: - has-flag: 1.0.0 - - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - sync-request@6.1.0: - dependencies: - http-response-object: 3.0.2 - sync-rpc: 1.3.6 - then-request: 6.0.2 - - sync-rpc@1.3.6: - dependencies: - get-port: 3.2.0 - - synckit@0.9.2: - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.8.1 - - table-layout@1.0.2: - dependencies: - array-back: 4.0.2 - deep-extend: 0.6.0 - typical: 5.2.0 - wordwrapjs: 4.0.1 - - table@6.8.2: - dependencies: - ajv: 8.17.1 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - test-exclude@6.0.0: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - - text-table@0.2.0: {} - - then-request@6.0.2: - dependencies: - '@types/concat-stream': 1.6.1 - '@types/form-data': 0.0.33 - '@types/node': 8.10.66 - '@types/qs': 6.9.17 - caseless: 0.12.0 - concat-stream: 1.6.2 - form-data: 2.5.2 - http-basic: 8.1.3 - http-response-object: 3.0.2 - promise: 8.3.0 - qs: 6.13.1 - - through2@4.0.2: - dependencies: - readable-stream: 3.6.2 - - tinyglobby@0.2.10: - dependencies: - fdir: 6.4.2(picomatch@4.0.2) - picomatch: 4.0.2 - - tmp-promise@3.0.3: - dependencies: - tmp: 0.2.3 - - tmp@0.0.33: - dependencies: - os-tmpdir: 1.0.2 - - tmp@0.2.3: {} - - tmpl@1.0.5: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - toidentifier@1.0.1: {} - - tryer@1.0.1: {} - - ts-api-utils@1.4.3(typescript@5.7.2): - dependencies: - typescript: 5.7.2 - - ts-command-line-args@2.5.1: - dependencies: - chalk: 4.1.2 - command-line-args: 5.2.1 - command-line-usage: 6.1.3 - string-format: 2.0.0 - - ts-essentials@7.0.3(typescript@5.7.2): - dependencies: - typescript: 5.7.2 - - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)))(typescript@5.7.2): - dependencies: - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2)) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.6.3 - typescript: 5.7.2 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.26.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.0) - - ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 18.19.67 - acorn: 8.14.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.7.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - - tslib@1.14.1: {} - - tslib@2.7.0: {} - - tslib@2.8.1: {} - - tsort@0.0.1: {} - - tweetnacl-util@0.15.1: {} - - tweetnacl@1.0.3: {} - - type-check@0.3.2: - dependencies: - prelude-ls: 1.1.2 - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-detect@4.0.8: {} - - type-detect@4.1.0: {} - - type-fest@0.20.2: {} - - type-fest@0.21.3: {} - - type-fest@0.7.1: {} - - typechain@8.3.2(typescript@5.7.2): - dependencies: - '@types/prettier': 2.7.3 - debug: 4.3.7(supports-color@8.1.1) - fs-extra: 7.0.1 - glob: 7.1.7 - js-sha3: 0.8.0 - lodash: 4.17.21 - mkdirp: 1.0.4 - prettier: 2.8.8 - ts-command-line-args: 2.5.1 - ts-essentials: 7.0.3(typescript@5.7.2) - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - - typedarray@0.0.6: {} - - typescript@5.7.2: {} - - typical@4.0.0: {} - - typical@5.2.0: {} - - uglify-js@3.19.3: - optional: true - - underscore@1.12.1: {} - - undici-types@5.26.5: {} - - undici-types@6.19.8: {} - - undici@5.28.4: - dependencies: - '@fastify/busboy': 2.1.1 - - universalify@0.1.2: {} - - universalify@2.0.1: {} - - unpipe@1.0.0: {} - - update-browserslist-db@1.1.1(browserslist@4.24.2): - dependencies: - browserslist: 4.24.2 - escalade: 3.2.0 - picocolors: 1.1.1 - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - utf8@3.0.0: {} - - util-deprecate@1.0.2: {} - - util@0.12.5: - dependencies: - inherits: 2.0.4 - is-arguments: 1.1.1 - is-generator-function: 1.0.10 - is-typed-array: 1.1.13 - which-typed-array: 1.1.16 - - uuid@8.3.2: {} - - v8-compile-cache-lib@3.0.1: {} - - v8-to-istanbul@9.3.0: - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 - - walker@1.0.8: - dependencies: - makeerror: 1.0.12 - - wasmbuilder@0.0.16: {} - - wasmcurves@0.2.0: - dependencies: - wasmbuilder: 0.0.16 - - wasmcurves@0.2.2: - dependencies: - wasmbuilder: 0.0.16 - - web-worker@1.2.0: {} - - web-worker@1.3.0: {} - - web3-utils@1.10.4: - dependencies: - '@ethereumjs/util': 8.1.0 - bn.js: 5.2.1 - ethereum-bloom-filters: 1.2.0 - ethereum-cryptography: 2.2.1 - ethjs-unit: 0.1.6 - number-to-bn: 1.7.0 - randombytes: 2.1.0 - utf8: 3.0.0 - - which-typed-array@1.1.16: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.1.0 - has-tostringtag: 1.0.2 - - which@1.3.1: - dependencies: - isexe: 2.0.0 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - widest-line@3.1.0: - dependencies: - string-width: 4.2.3 - - word-wrap@1.2.5: {} - - wordwrap@1.0.0: {} - - wordwrapjs@4.0.1: - dependencies: - reduce-flatten: 2.0.0 - typical: 5.2.0 - - workerpool@6.5.1: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - - wrappy@1.0.2: {} - - write-file-atomic@4.0.2: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - - ws@7.4.6: {} - - ws@7.5.10: {} - - ws@8.17.1: {} - - y18n@5.0.8: {} - - yallist@3.1.1: {} - - yargs-parser@20.2.9: {} - - yargs-parser@21.1.1: {} - - yargs-unparser@2.0.0: - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yn@3.1.1: {} - - yocto-queue@0.1.0: {} diff --git a/schema.json b/schema.json new file mode 100644 index 0000000..64edc15 --- /dev/null +++ b/schema.json @@ -0,0 +1,451 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CircomkitConfig", + "description": "Top-level circomkit configuration.", + "type": "object", + "properties": { + "circuits": { + "description": "Circuit definitions, keyed by circuit name.", + "default": {}, + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/CircuitConfig" + } + }, + "compiler": { + "description": "Compiler settings.", + "default": { + "c": false, + "circomPath": "circom", + "include": ["./node_modules"], + "inspect": true, + "optimization": 1, + "outDir": "./build", + "prime": "bn128", + "r1cs": true, + "srcDir": "./circuits", + "sym": true, + "verbose": true, + "wasm": true + }, + "allOf": [ + { + "$ref": "#/definitions/CompilerConfig" + } + ] + }, + "logLevel": { + "description": "Log level.", + "default": "info", + "allOf": [ + { + "$ref": "#/definitions/LogLevel" + } + ] + }, + "prover": { + "description": "Prover settings.", + "default": { + "backend": "snarkjs", + "groth16": { + "askForEntropy": false, + "numContributions": 1 + }, + "inputDir": "./inputs", + "protocol": "groth16", + "ptauDir": "./ptau", + "verbose": true + }, + "allOf": [ + { + "$ref": "#/definitions/ProverConfig" + } + ] + }, + "version": { + "description": "Circom version for pragma.", + "default": "2.1.0", + "type": "string" + }, + "witness": { + "description": "Witness generation settings.", + "default": { + "calculator": "wasm" + }, + "allOf": [ + { + "$ref": "#/definitions/WitnessConfig" + } + ] + } + }, + "definitions": { + "CircuitConfig": { + "description": "Per-circuit configuration.", + "type": "object", + "required": ["file", "template"], + "properties": { + "file": { + "description": "Path to the circuit template file (relative to `src_dir`, without extension).", + "type": "string" + }, + "overrides": { + "description": "Per-circuit config overrides.", + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/CircuitOverrides" + }, + { + "type": "null" + } + ] + }, + "params": { + "description": "Template parameters.", + "default": [], + "type": "array", + "items": true + }, + "pubs": { + "description": "Public input signal names.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "template": { + "description": "Name of the circom template to instantiate.", + "type": "string" + }, + "usesCustomTemplates": { + "description": "Whether the circuit uses custom templates (custom pragma).", + "default": false, + "type": "boolean" + } + } + }, + "CircuitOverrides": { + "description": "Per-circuit overrides that merge on top of global config.", + "type": "object", + "properties": { + "compiler": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/PartialCompilerConfig" + }, + { + "type": "null" + } + ] + }, + "prover": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/PartialProverConfig" + }, + { + "type": "null" + } + ] + }, + "version": { + "default": null, + "type": ["string", "null"] + } + } + }, + "CompilerConfig": { + "description": "Compiler configuration.", + "type": "object", + "properties": { + "c": { + "description": "Generate C witness calculator.", + "default": false, + "type": "boolean" + }, + "circomPath": { + "description": "Path to the circom binary.", + "default": "circom", + "type": "string" + }, + "include": { + "description": "Include paths for circom (e.g. `node_modules`).", + "default": ["./node_modules"], + "type": "array", + "items": { + "type": "string" + } + }, + "inspect": { + "description": "Run constraint inspection during compilation.", + "default": true, + "type": "boolean" + }, + "optimization": { + "description": "Optimization level (0, 1, 2, or higher for O2round).", + "default": 1, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "outDir": { + "description": "Output directory for build artifacts.", + "default": "./build", + "type": "string" + }, + "prime": { + "description": "Prime field for circuit compilation.", + "default": "bn128", + "allOf": [ + { + "$ref": "#/definitions/Prime" + } + ] + }, + "r1cs": { + "description": "Generate R1CS file.", + "default": true, + "type": "boolean" + }, + "srcDir": { + "description": "Source directory for circuit templates.", + "default": "./circuits", + "type": "string" + }, + "sym": { + "description": "Generate symbol file.", + "default": true, + "type": "boolean" + }, + "verbose": { + "description": "Whether circom should output verbose logs.", + "default": true, + "type": "boolean" + }, + "wasm": { + "description": "Generate WASM witness calculator.", + "default": true, + "type": "boolean" + } + } + }, + "Groth16Options": { + "description": "Groth16-specific prover options.", + "type": "object", + "properties": { + "askForEntropy": { + "description": "Whether to prompt for entropy during contributions.", + "default": false, + "type": "boolean" + }, + "numContributions": { + "description": "Number of phase-2 contributions.", + "default": 1, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + }, + "LogLevel": { + "description": "Log level for circomkit operations.", + "type": "string", + "enum": ["trace", "debug", "info", "warn", "error", "silent"] + }, + "PartialCompilerConfig": { + "type": "object", + "properties": { + "c": { + "default": null, + "type": ["boolean", "null"] + }, + "circomPath": { + "default": null, + "type": ["string", "null"] + }, + "inspect": { + "default": null, + "type": ["boolean", "null"] + }, + "optimization": { + "default": null, + "type": ["integer", "null"], + "format": "uint32", + "minimum": 0.0 + }, + "outDir": { + "default": null, + "type": ["string", "null"] + }, + "prime": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Prime" + }, + { + "type": "null" + } + ] + }, + "r1cs": { + "default": null, + "type": ["boolean", "null"] + }, + "srcDir": { + "default": null, + "type": ["string", "null"] + }, + "sym": { + "default": null, + "type": ["boolean", "null"] + }, + "verbose": { + "default": null, + "type": ["boolean", "null"] + }, + "wasm": { + "default": null, + "type": ["boolean", "null"] + } + } + }, + "PartialProverConfig": { + "type": "object", + "properties": { + "backend": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/ProvingBackendKind" + }, + { + "type": "null" + } + ] + }, + "inputDir": { + "default": null, + "type": ["string", "null"] + }, + "protocol": { + "default": null, + "anyOf": [ + { + "$ref": "#/definitions/Protocol" + }, + { + "type": "null" + } + ] + }, + "ptauDir": { + "default": null, + "type": ["string", "null"] + }, + "verbose": { + "default": null, + "type": ["boolean", "null"] + } + } + }, + "Prime": { + "description": "Finite field / elliptic curve prime.", + "type": "string", + "enum": [ + "bn128", + "bls12381", + "goldilocks", + "grumpkin", + "pallas", + "vesta", + "secq256r1" + ] + }, + "Protocol": { + "description": "Zero-knowledge proof protocol.", + "type": "string", + "enum": ["groth16", "plonk", "fflonk"] + }, + "ProverConfig": { + "description": "Prover configuration.", + "type": "object", + "properties": { + "backend": { + "description": "Proving backend.", + "default": "snarkjs", + "allOf": [ + { + "$ref": "#/definitions/ProvingBackendKind" + } + ] + }, + "groth16": { + "description": "Groth16-specific options.", + "default": { + "askForEntropy": false, + "numContributions": 1 + }, + "allOf": [ + { + "$ref": "#/definitions/Groth16Options" + } + ] + }, + "inputDir": { + "description": "Directory for circuit input JSON files.", + "default": "./inputs", + "type": "string" + }, + "protocol": { + "description": "Proof protocol to use.", + "default": "groth16", + "allOf": [ + { + "$ref": "#/definitions/Protocol" + } + ] + }, + "ptauDir": { + "description": "Directory for Powers of Tau files.", + "default": "./ptau", + "type": "string" + }, + "verbose": { + "description": "Whether snarkjs should log verbosely.", + "default": true, + "type": "boolean" + } + } + }, + "ProvingBackendKind": { + "description": "Proving backend kind.", + "type": "string", + "enum": ["snarkjs", "arkworks", "lambdaworks"] + }, + "WitnessBackend": { + "description": "Witness calculator backend.", + "type": "string", + "enum": ["wasm", "c"] + }, + "WitnessConfig": { + "description": "Witness generation configuration.", + "type": "object", + "properties": { + "calculator": { + "description": "Which witness calculator backend to use.", + "default": "wasm", + "allOf": [ + { + "$ref": "#/definitions/WitnessBackend" + } + ] + } + } + } + } +} diff --git a/src/cli.ts b/src/cli.ts deleted file mode 100644 index a34fabb..0000000 --- a/src/cli.ts +++ /dev/null @@ -1,297 +0,0 @@ -#!/usr/bin/env node -import {Command} from '@commander-js/extra-typings'; -import {Circomkit} from './core'; -import {existsSync, readFileSync, readdirSync, writeFileSync} from 'fs'; -import {prettyStringify} from './utils'; -import {exec} from 'child_process'; -import {teardown} from './utils/teardown'; - -const CONFIG_PATH = './circomkit.json'; - -function cli(args: string[]) { - const circomkit = new Circomkit(existsSync(CONFIG_PATH) ? JSON.parse(readFileSync(CONFIG_PATH, 'utf-8')) : {}); - - /////////////////////////////////////////////////////////////////////////////// - const circuit = new Command('compile') - .description('compile the circuit') - .argument('[pattern]', 'Circuit name or pattern (defaults to ".*" for all circuits)') - .action(async pattern => { - const circuits = circomkit.readCircuits(); - const circuitNames = Object.keys(circuits); - - if (!pattern) pattern = '.*'; - - const regex = new RegExp(`^${pattern}$`); - const matchingCircuits = circuitNames.filter(name => regex.test(name)); - - if (matchingCircuits.length === 0) { - circomkit.log.info('No circuits found matching pattern:', pattern); - return; - } - - for (const circuitName of matchingCircuits) { - circomkit.log.info(`Compiling ${circuitName}...`); - const path = await circomkit.compile(circuitName); - circomkit.log.info(`Built at: ${path}`); - } - }); - - /////////////////////////////////////////////////////////////////////////////// - const instantiate = new Command('instantiate') - .description('create the main component') - .argument('', 'Circuit name') - .action(async circuit => { - const path = circomkit.instantiate(circuit); - circomkit.log.info('Created at:', path); - }); - - /////////////////////////////////////////////////////////////////////////////// - const info = new Command('info') - .description('print circuit information') - .argument('', 'Circuit name') - .action(async circuit => { - const info = await circomkit.info(circuit); - console.log(`Prime Field: ${info.primeName}`); - console.log(`Number of Wires: ${info.wires}`); - console.log(`Number of Constraints: ${info.constraints}`); - console.log(`Number of Private Inputs: ${info.privateInputs}`); - console.log(`Number of Public Inputs: ${info.publicInputs}`); - console.log(`Number of Public Outputs: ${info.publicOutputs}`); - console.log(`Number of Labels: ${info.labels}`); - }); - - /////////////////////////////////////////////////////////////////////////////// - const clear = new Command('clear') - .description('clear circuit build artifacts') - .argument('', 'Circuit name') - .action(async circuit => { - await circomkit.clear(circuit); - circomkit.log.info('Cleaned.'); - }); - - /////////////////////////////////////////////////////////////////////////////// - const init = new Command('init') - .description('initialize a new Circomkit project') - .argument('[dir]', 'Directory') - .action(async dir => { - const cmd = `git clone https://github.com/erhant/circomkit-examples.git ${dir ?? '.'}`; - circomkit.log.info(cmd); - - const result = await new Promise<{stdout: string; stderr: string}>((resolve, reject) => - exec(cmd, (error, stdout, stderr) => (error ? reject(error) : resolve({stdout, stderr}))) - ); - - circomkit.log.info(result.stdout); - if (result.stderr) { - circomkit.log.info(result.stderr); - } - - circomkit.log.info('Circomkit project initialized! ✨'); - }); - - /////////////////////////////////////////////////////////////////////////////// - const json = new Command('json') - .description('export JSON files') - .addCommand( - new Command('r1cs') - .description('export r1cs') - .argument('', 'Circuit name') - .option('-p, --print', 'Print JSON without saving it') - .action(async (circuit, options) => { - const {json, path} = await circomkit.json('r1cs', circuit); - if (options.print) { - console.log(prettyStringify(json)); - } else { - writeFileSync(path, prettyStringify(json)); - circomkit.log.info('Exported R1CS at: ' + path); - } - }) - ) - .addCommand( - new Command('zkey') - .description('export prover key') - .argument('', 'Circuit name') - .option('-p, --print', 'Print JSON without saving it') - .action(async (circuit, options) => { - const {json, path} = await circomkit.json('zkey', circuit); - if (options.print) { - console.log(prettyStringify(json)); - } else { - writeFileSync(path, prettyStringify(json)); - circomkit.log.info('Exported prover key at: ' + path); - } - }) - ) - .addCommand( - new Command('wtns') - .description('export witness') - .argument('', 'Circuit name') - .argument('', 'Input name') - .option('-p, --print', 'Print JSON without saving it') - .action(async (circuit, input, options) => { - const {json, path} = await circomkit.json('wtns', circuit, input); - if (options.print) { - console.log(prettyStringify(json)); - } else { - writeFileSync(path, prettyStringify(json)); - circomkit.log.info('Exported witness at: ' + path); - } - }) - ); - - /////////////////////////////////////////////////////////////////////////////// - const contract = new Command('contract') - .description('export Solidity verifier contract') - .argument('', 'Circuit name') - .action(async circuit => { - const path = await circomkit.contract(circuit); - circomkit.log.info('Created at: ' + path); - }); - - /////////////////////////////////////////////////////////////////////////////// - const calldata = new Command('calldata') - .description('export calldata for a verifier contract') - .argument('', 'Circuit name') - .argument('', 'Input name') - .action(async (circuit, input) => { - const calldata = await circomkit.calldata(circuit, input); - circomkit.log.info(calldata); - }); - - /////////////////////////////////////////////////////////////////////////////// - const vkey = new Command('vkey') - .description('extract verification key') - .argument('', 'Circuit name') - .argument('[pkeyPath]', 'Prover key path') - .action(async (circuit, pkeyPath) => { - const path = await circomkit.vkey(circuit, pkeyPath); - circomkit.log.info('Created at: ' + path); - }); - - /////////////////////////////////////////////////////////////////////////////// - const prove = new Command('prove') - .description('generate zk-proof') - .argument('', 'Circuit name') - .argument('', 'Input name') - .action(async (circuit, input) => { - const path = await circomkit.prove(circuit, input); - circomkit.log.info('Generated at: ' + path); - }); - - /////////////////////////////////////////////////////////////////////////////// - const verify = new Command('verify') - .description('verify zk-proof') - .argument('', 'Circuit name') - .argument('', 'Input name') - .action(async (circuit, input) => { - const ok = await circomkit.verify(circuit, input); - if (ok) { - circomkit.log.info('Verification successful.'); - } else { - circomkit.log.info('Verification failed!'); - } - }); - - /////////////////////////////////////////////////////////////////////////////// - const witness = new Command('witness') - .description('compute witness') - .argument('', 'Circuit name') - .argument('', 'Input name') - .action(async (circuit, input) => { - const path = await circomkit.witness(circuit, input); - circomkit.log.info('Witness created: ' + path); - }); - - /////////////////////////////////////////////////////////////////////////////// - const setup = new Command('setup') - .description('commence circuit-specific setup') - .argument('', 'Circuit name') - .argument('[ptauPath]', 'Path to PTAU') - .action(async (circuit, ptauPath) => { - const {proverKeyPath, verifierKeyPath} = await circomkit.setup(circuit, ptauPath); - circomkit.log.info('Prover key created: ' + proverKeyPath); - circomkit.log.info('Verifier key created: ' + verifierKeyPath); - }); - - /////////////////////////////////////////////////////////////////////////////// - const ptau = new Command('ptau') - .description('download PTAU file') - .argument('', 'Circuit name') - .action(async circuit => { - const path = await circomkit.ptau(circuit); - circomkit.log.info('PTAU ready at: ' + path); - }); - - /////////////////////////////////////////////////////////////////////////////// - const list = new Command('list').description('list circuits & instances').action(async () => { - const templates = readdirSync(circomkit.config.dirCircuits) - .filter(path => path.endsWith('.circom')) - .map(path => path.slice(0, -'.circom'.length)); - circomkit.log.info( - `Template Files (${circomkit.config.dirCircuits}):\n` + templates.map((c, i) => ` ${i + 1}. ${c}`).join('\n') - ); - - const circuits = circomkit.readCircuits(); - circomkit.log.info( - `\nCircuit Names (${circomkit.config.circuits}):\n` + - Object.keys(circuits) - .map((c, i) => ` ${i + 1}. ${c}`) - .join('\n') - ); - }); - - /////////////////////////////////////////////////////////////////////////////// - const config = new Command('config').description('print configuration').action(() => { - circomkit.log.info(circomkit.config); - }); - - /////////////////////////////////////////////////////////////////////////////// - new Command() - .name('circomkit') - .description('Circom testing & development toolkit') - // none - .addCommand(init) - .addCommand(config) - .addCommand(list) - .addCommand(json) - // - .addCommand(circuit) - .addCommand(instantiate) - .addCommand(info) - .addCommand(clear) - .addCommand(contract) - .addCommand(vkey) - .addCommand(ptau) - .addCommand(setup) - // - .addCommand(prove) - .addCommand(witness) - .addCommand(verify) - .addCommand(calldata) - // teardown to terminate SnarkJS, otherwise hangs the program - .hook('postAction', async () => await teardown()) - .parse(args); - - // TODO: test graceful exits - /** - * We have to exit forcefully, as SnarkJS CLI does too. - * In their code, each function returns a code, with the - * succesfull ones returning 0. If an error is thrown, - * that error is logged and process is exited with error code 1. - * - * See https://github.com/iden3/snarkjs/blob/master/cli.js#L348 - */ - // function exit(code: number) { - // // eslint-disable-next-line no-process-exit - // process.exit(code); - // } - - // cli() - // .then(code => exit(code)) - // .catch(err => { - // console.error(err); - // exit(1); - // }); -} - -cli(process.argv); diff --git a/src/configs/index.ts b/src/configs/index.ts deleted file mode 100644 index cf2e1d2..0000000 --- a/src/configs/index.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type {LogLevelDesc} from 'loglevel'; - -export const PROTOCOLS = ['groth16', 'plonk', 'fflonk'] as const; -export const PRIMES = ['bn128', 'bls12381', 'goldilocks', 'grumpkin', 'pallas', 'vesta', 'secq256r1'] as const; - -export type CircomkitConfig = { - /** Protocol (proof system) to be used. */ - protocol: (typeof PROTOCOLS)[number]; - /** - * Primes supported by Circom, as described for the `-p` option. - * @see https://github.com/iden3/circom/blob/master/program_structure/src/utils/constants.rs - */ - prime: (typeof PRIMES)[number]; - /** Circuit configurations path. */ - circuits: string; - /** Directory to read circuits from. */ - dirCircuits: string; - /** Directory to read inputs from. */ - dirInputs: string; - /** Directory to download PTAU files. */ - dirPtau: string; - /** Directory to output circuit build files. */ - dirBuild: string; - /** Path to circom executable */ - circomPath: string; - /** Number of contributions */ - groth16numContributions: number; - /** Ask user input to create entropy */ - groth16askForEntropy: boolean; - /** Version number for main components. */ - version: `${number}.${number}.${number}`; - /** - * [Optimization level](https://docs.circom.io/getting-started/compilation-options/#flags-and-options-related-to-the-r1cs-optimization). - * See [`circom/src/input_user.rs`](https://github.com/iden3/circom/blob/master/circom/src/input_user.rs#L249). - * - `undefined`: Follow Circom default. (=v2.2.0: 1) - * - `0`: No simplification is applied. - * - `1`: Only applies `var` to `var` and `var` to `constant` simplification. - * - `2`: Full constraint simplificiation via Gaussian eliminations. - * - `>2`: Any number higher than 2 will use `--O2round` with the number as simplification rounds. - */ - optimization: number | undefined; - /** Does an additional check over the constraints produced. */ - inspect: boolean; - /** Include paths as libraries during compilation. */ - include: string[]; - /** Pass logger to SnarkJS to see its logs in addition to Circomkit. */ - verbose: boolean; - /** Log level used by the internal logger. */ - logLevel: LogLevelDesc; - /** Whether to generate the C witness calculator. */ - cWitness: boolean; - /** Whether to generate the WASM witness calculator. */ - wasmWitness: boolean; - /** Whether to print Solidity copy-pasteable calldata. */ - prettyCalldata: false; -}; - -/** Default configurations */ -export const DEFAULT = Object.seal>({ - // general settings - protocol: 'groth16', - prime: 'bn128', - version: '2.1.0', - // directories & paths - circuits: './circuits.json', - dirPtau: './ptau', - dirCircuits: './circuits', - dirInputs: './inputs', - dirBuild: './build', - circomPath: 'circom', - // compiler-specific - optimization: undefined, - inspect: true, - include: ['./node_modules'], - cWitness: false, - wasmWitness: true, - // groth16 phase-2 settings - groth16numContributions: 1, - groth16askForEntropy: false, - // solidity & calldata - prettyCalldata: false, - // logger - logLevel: 'INFO', - verbose: true, -}); diff --git a/src/core/index.ts b/src/core/index.ts deleted file mode 100644 index 5d2ff03..0000000 --- a/src/core/index.ts +++ /dev/null @@ -1,536 +0,0 @@ -import * as snarkjs from 'snarkjs'; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-expect-error -import {wasm as wasm_tester} from 'circom_tester'; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-expect-error -import {c as c_tester} from 'circom_tester'; -import {writeFileSync, readFileSync, existsSync, mkdirSync, rmSync, renameSync} from 'fs'; -import {readFile, rm, writeFile} from 'fs/promises'; -import {randomBytes} from 'crypto'; -import loglevel from 'loglevel'; -import {downloadPtau, getPtauName} from '../utils/ptau'; -import type {CircuitConfig, CircuitSignals, CircomTester} from '../types'; -import {WitnessTester, ProofTester} from '../testers'; -import {prettyStringify} from '../utils'; -import {CircomkitConfig, DEFAULT, PRIMES, PROTOCOLS} from '../configs'; -import {compileCircuit, instantiateCircuit, readR1CSInfo, getCalldata} from '../functions'; -import {CircomkitPath} from './pathing'; - -/** - * Circomkit is an opinionated wrapper around many SnarkJS functions. - * - * It abstracts away all the path and commands by providing a simple interface, - * built around just providing the circuit name and the input name. - * - * ```ts - * const circomkit = new Circomkit() - * ``` - * - * It also provides a **WitnessTester** and a **ProofTester** module which use Chai assertions within. - * - * ```ts - * const witnessTester = await circomkit.WitnessTester(circuitName, circuitConfig) - * const proofTester = await circomkit.ProofTester(circuitName) - * ``` - */ -export class Circomkit { - public readonly config: CircomkitConfig; - public readonly log: loglevel.Logger; - public readonly path: CircomkitPath; - - /** A logger reference to be passed into SnarkJS functions. If `verbose` is set to `false`, this logger will be undefined. */ - private readonly snarkjsLogger: loglevel.Logger | undefined; - - constructor(overrides: Partial = {}) { - // override default options with the user-provided ones - // we can do this via two simple spreads because both objects are single depth - const config: CircomkitConfig = { - ...DEFAULT, - ...overrides, - }; - - this.config = JSON.parse(JSON.stringify(config)) as CircomkitConfig; - this.log = loglevel.getLogger('Circomkit'); - this.log.setLevel(this.config.logLevel); - - // logger for SnarkJS, accepted as an optional argument within their functions - this.snarkjsLogger = this.config.verbose ? this.log : undefined; - - // sanity checks - if (!PRIMES.includes(this.config.prime)) { - throw new Error('Invalid prime in configuration.'); - } - if (!PROTOCOLS.includes(this.config.protocol)) { - throw new Error('Invalid protocol in configuration.'); - } - if (this.config.optimization !== undefined && typeof this.config.optimization !== 'number') { - throw new Error('Invalid optimization level.'); - } - if (typeof this.config.optimization === 'number' && this.config.optimization < 0) { - this.log.warn('Optimization level must be at least 0, setting it to 0.'); - this.config.optimization = 0; - } - - // PLONK protocol requires optimization level to be 1 - if (this.config.protocol === 'plonk' && this.config.optimization !== 1) { - this.log.warn( - 'Optimization level for PLONK must be 1.\n', - 'See: https://docs.circom.io/circom-language/circom-insight/simplification/' - ); - this.config.optimization = 1; - } - - this.path = new CircomkitPath(this.config); - } - - /** Returns the contents of `circuits.json`. */ - readCircuits(): Record { - return JSON.parse(readFileSync(this.config.circuits, 'utf-8')); - } - - /** Returns a single circuit config from `circuits.json`. */ - readCircuitConfig(circuit: string): CircuitConfig { - const circuits = this.readCircuits(); - if (!(circuit in circuits)) { - throw new Error('No such circuit in ' + this.config.circuits); - } - return circuits[circuit] as CircuitConfig; - } - - /** Clear build files and the `main` component of a circuit. */ - async clear(circuit: string): Promise { - await Promise.all([ - rm(this.path.ofCircuit(circuit, 'dir'), {recursive: true, force: true}), - rm(this.path.ofCircuit(circuit, 'main'), {force: true}), - ]); - } - - /** Export a verification key (vKey) from a proving key (zKey). */ - async vkey(circuit: string, pkeyPath?: string): Promise { - const vkeyPath = this.path.ofCircuit(circuit, 'vkey'); - - // check if it exists - if (pkeyPath === undefined) { - pkeyPath = this.path.ofCircuit(circuit, 'pkey'); - } - - if (!existsSync(pkeyPath)) { - throw new Error('There must be a prover key for this circuit to extract a verification key.'); - } - - // extract it - const vkey = await snarkjs.zKey.exportVerificationKey(pkeyPath, this.snarkjsLogger); - writeFileSync(vkeyPath, prettyStringify(vkey)); - - return vkeyPath; - } - - /** Returns circuit information. */ - async info(circuit: string) { - return await readR1CSInfo(this.path.ofCircuit(circuit, 'r1cs')); - } - - /** Downloads the phase-1 setup PTAU file for a circuit based on it's number of constraints. - * - * The downloaded PTAU files can be seen at [SnarkJS docs](https://github.com/iden3/snarkjs#7-prepare-phase-2). - * Note that this may take a while if the circuit is large and thus a larger PTAU is needed. - * - * This function only works when the used prime is `bn128`. - * - * @returns path of the downloaded PTAU file - */ - async ptau(circuit: string): Promise { - // @todo check for performance gains when larger PTAUs are found instead of the target PTAU - const {constraints} = await this.info(circuit); - const ptauName = getPtauName(constraints); - const ptauPath = this.path.ofPtau(ptauName); - - if (existsSync(ptauPath)) { - // return if ptau exists already - return ptauPath; - } else { - /// otherwise download it - if (this.config.prime !== 'bn128') { - throw new Error('Auto-downloading PTAU only allowed for bn128 at the moment.'); - } - - mkdirSync(this.config.dirPtau, {recursive: true}); - - this.log.info(`Downloading ${ptauName}, this may take a while.`); - return await downloadPtau(ptauName, this.config.dirPtau); - } - } - - /** Compile the circuit. - * - * A circuit configuration can be passed optionally; if not, the - * config will be read from `circuits.json` at the working directory. - * - * @returns path of the build directory - */ - async compile(circuit: string, config?: CircuitConfig) { - const targetPath = this.instantiate(circuit, config); - this.log.debug('Main component created at: ' + targetPath); - - const outDir = this.path.ofCircuit(circuit, 'dir'); - - const {stdout, stderr} = await compileCircuit(this.config, targetPath, outDir); - if (this.config.verbose) { - this.log.info(stdout); - } - if (stderr) { - this.log.error(stderr); - } - return outDir; - } - - /** Exports a solidity contract for the verifier. - * @returns path of the exported Solidity contract - */ - async contract(circuit: string) { - const pkey = this.path.ofCircuit(circuit, 'pkey'); - const template = readFileSync(`./node_modules/snarkjs/templates/verifier_${this.config.protocol}.sol.ejs`, 'utf-8'); - const contractCode = await snarkjs.zKey.exportSolidityVerifier( - pkey, - {[this.config.protocol]: template}, - this.snarkjsLogger - ); - - const contractPath = this.path.ofCircuit(circuit, 'sol'); - writeFileSync(contractPath, contractCode); - return contractPath; - } - - /** Export calldata to call a Verifier contract. - * - * @returns calldata - */ - async calldata(circuit: string, input: string, pretty?: boolean): Promise { - const pubs: snarkjs.PublicSignals = JSON.parse( - await readFile(this.path.ofCircuitWithInput(circuit, input, 'pubs'), 'utf-8') - ); - const proof: snarkjs.Groth16Proof & snarkjs.PlonkProof & snarkjs.FflonkProof = JSON.parse( - await readFile(this.path.ofCircuitWithInput(circuit, input, 'proof'), 'utf-8') - ); - - const res = getCalldata(proof, pubs, pretty ?? this.config.prettyCalldata); - return res; - } - - /** Instantiate the `main` component. - * - * If `circuitConfig` argument is omitted, this function will look for it at `circuits.json` - * in the working directory, and throw an error if no entry is found for the circuit. - * - * When config is read from file, `dir` defaults to `main`, otherwise `dir` defaults to `test`. - * This is done to make it so that when CLI is used circuits are created under `main`, and when - * we use Circomkit programmatically (e.g. during testing) circuits are created under `test` - * unless specified otherwise. - * - * @returns path of the created main component - */ - instantiate(circuit: string, circuitConfig?: CircuitConfig) { - if (!circuitConfig) { - const circuitConfigFile = this.readCircuitConfig(circuit); - circuitConfig = { - ...circuitConfigFile, - dir: circuitConfigFile.dir || 'main', - version: circuitConfigFile.version || this.config.version, - }; - } - - const circomSource = readFileSync(`${this.config.dirCircuits}/${circuitConfig.file}.circom`, 'utf8'); - - // TODO: do we need regex here? - const usesCustomTemplates = - circuitConfig.usesCustomTemplates ?? - circomSource - .replace(/\/\/.*|\/\*[\s\S]*?\*\//g, '') // remove single and multi-line comments - .includes('pragma custom_templates;'); - - // directory to output the file - const directory = circuitConfig.dir || 'test'; - - // add "../" to the filename in include, one for each "/" in directory name - // if none, the prefix becomes empty string - const filePrefixMatches = directory.match(/\//g); - let file = circuitConfig.file; - if (filePrefixMatches !== null) { - file = '../'.repeat(filePrefixMatches.length) + file; - } - - const config: Required = { - file: file, - template: circuitConfig.template, - // Precedence: per-circuit override > this.config.version > "2.0.0". See #123. - version: circuitConfig.version || this.config.version || '2.0.0', - dir: directory, - pubs: circuitConfig.pubs || [], - params: circuitConfig.params || [], - usesCustomTemplates, - }; - - const targetDir = `${this.config.dirCircuits}/${directory}`; - const targetPath = `${targetDir}/${circuit}.circom`; - - instantiateCircuit(config, targetDir, targetPath); - - return targetPath; - } - - /** Generate a proof. - * - * If `data` is not passed, the input data will be read from `inputs//.json`. - * - * @returns path of the directory where public signals and proof are created - */ - async prove(circuit: string, input: string, data?: CircuitSignals): Promise { - // create WASM if needed - const wasmPath = this.path.ofCircuit(circuit, 'wasm'); - if (!existsSync(wasmPath)) { - this.log.warn('WASM file does not exist, creating it now...'); - await this.compile(circuit); - } - - // create PKEY if needed - const pkeyPath = this.path.ofCircuit(circuit, 'pkey'); - if (!existsSync(pkeyPath)) { - this.log.warn('Prover key does not exist, creating it now...'); - await this.setup(circuit); - } - - const jsonInput = data ?? JSON.parse(readFileSync(this.path.ofCircuitWithInput(circuit, input, 'in'), 'utf-8')); - - const {proof, publicSignals} = await snarkjs[this.config.protocol].fullProve( - jsonInput, - wasmPath, - pkeyPath, - this.snarkjsLogger - ); - - const dir = this.path.ofCircuitWithInput(circuit, input, 'dir'); - mkdirSync(dir, {recursive: true}); - await Promise.all([ - writeFile(this.path.ofCircuitWithInput(circuit, input, 'pubs'), prettyStringify(publicSignals)), - writeFile(this.path.ofCircuitWithInput(circuit, input, 'proof'), prettyStringify(proof)), - ]); - return dir; - } - - /** Commence a circuit-specific setup. - * - * If `ptauPath` argument is omitted, this function will try to automatically download it. - * See the {@link ptau} method for more information about this. - * - * @returns path of the verifier key and prover key - */ - async setup(circuit: string, ptauPath?: string): Promise<{proverKeyPath: string; verifierKeyPath: string}> { - const r1csPath = this.path.ofCircuit(circuit, 'r1cs'); - const pkeyPath = this.path.ofCircuit(circuit, 'pkey'); - const vkeyPath = this.path.ofCircuit(circuit, 'vkey'); - - // create R1CS if needed - if (!existsSync(r1csPath)) { - this.log.warn('R1CS does not exist, creating it now.'); - await this.compile(circuit); - } - - // get ptau path - if (ptauPath === undefined) { - if (this.config.prime !== 'bn128') { - throw new Error('Can not download PTAU file when using a prime field other than bn128'); - } - ptauPath = await this.ptau(circuit); - } else if (!existsSync(ptauPath)) { - // if the provided path does not exist, we can download it anyways - this.log.warn('PTAU path was given but no PTAU exists there, downloading it anyways.'); - ptauPath = await this.ptau(circuit); - } - - // circuit specific setup - this.log.info('Beginning setup phase!'); - if (this.config.protocol === 'groth16') { - // Groth16 needs a circuit specific setup - - // generate genesis zKey - let curZkey = this.path.ofZkey(circuit, 0); - await snarkjs.zKey.newZKey(r1csPath, ptauPath, curZkey, this.snarkjsLogger); - - // make contributions - for (let contrib = 1; contrib <= this.config.groth16numContributions; contrib++) { - const nextZkey = this.path.ofZkey(circuit, contrib); - - // entropy, if user wants to prompt give undefined - this.log.info(`Making contribution: ${contrib}`); - await snarkjs.zKey.contribute( - curZkey, - nextZkey, - `${circuit}_${contrib}`, - this.config.groth16askForEntropy ? undefined : randomBytes(32), // entropy - this.snarkjsLogger - ); - - // remove current key, and move on to next one - rmSync(curZkey); - curZkey = nextZkey; - } - - // finally, rename the resulting key to pkey - renameSync(curZkey, pkeyPath); - } else { - // PLONK or FFLONK don't need specific setup - await snarkjs[this.config.protocol].setup(r1csPath, ptauPath, pkeyPath, this.snarkjsLogger); - } - - // export verification key - const vkey = await snarkjs.zKey.exportVerificationKey(pkeyPath, this.snarkjsLogger); - writeFileSync(vkeyPath, prettyStringify(vkey)); - return {verifierKeyPath: vkeyPath, proverKeyPath: pkeyPath}; - } - - /** Verify a proof for some public signals. - * @returns `true` if verification is successful, `false` otherwise. - */ - async verify(circuit: string, input: string): Promise { - const [vkey, pubs, proof] = ( - await Promise.all( - [ - this.path.ofCircuit(circuit, 'vkey'), - this.path.ofCircuitWithInput(circuit, input, 'pubs'), - this.path.ofCircuitWithInput(circuit, input, 'proof'), - ].map(path => readFile(path, 'utf-8')) - ) - ).map(content => JSON.parse(content)); - - return await snarkjs[this.config.protocol].verify(vkey, pubs, proof, this.snarkjsLogger); - } - - /** Calculates the witness for the given circuit and input. - * - * If `data` is not passed, the input data will be read from `inputs//.json`. - * - * @returns path of the created witness - */ - async witness(circuit: string, input: string, data?: CircuitSignals): Promise { - const wasmPath = this.path.ofCircuit(circuit, 'wasm'); - if (!existsSync(wasmPath)) { - this.log.warn('WASM file does not exist, creating it now...'); - await this.compile(circuit); - } - const wtnsPath = this.path.ofCircuitWithInput(circuit, input, 'wtns'); - const outDir = this.path.ofCircuitWithInput(circuit, input, 'dir'); - const jsonInput = data ?? JSON.parse(readFileSync(this.path.ofCircuitWithInput(circuit, input, 'in'), 'utf-8')); - - mkdirSync(outDir, {recursive: true}); - await snarkjs.wtns.calculate(jsonInput, wasmPath, wtnsPath); - return wtnsPath; - } - - /** Exports a JSON input file for some circuit with the given object. - * - * This is useful for testing real circuits, or creating an input programmatically. - * Overwrites an existing input. - * - * @returns path of the created input file - */ - input(circuit: string, input: string, data: CircuitSignals): string { - const inputPath = this.path.ofCircuitWithInput(circuit, input, 'in'); - if (existsSync(inputPath)) { - this.log.warn('Input file exists already, overwriting it.'); - } - writeFileSync(inputPath, prettyStringify(data)); - return inputPath; - } - - /** Export a circuit artifact in JSON format. - * - * Returns the JSON object itself, and the path that it would be exported to with - * respect to the Circomkit configuration. - * - * @returns a JSON object or the path that it would be exported to. - */ - async json(target: 'r1cs' | 'zkey', circuit: string): Promise<{json: object; path: string}>; - async json(target: 'wtns', circuit: string, input: string): Promise<{json: object; path: string}>; - async json(target: 'r1cs' | 'zkey' | 'wtns', circuit: string, input?: string): Promise<{json: object; path: string}> { - let json: object; - let path: string; - - switch (target) { - // R1CS - case 'r1cs': { - path = this.path.ofCircuit(circuit, 'r1cs'); - json = await snarkjs.r1cs.exportJson(path, undefined); // internal log didnt make sense - break; - } - // Prover key - case 'zkey': { - // must be groth16, others give error (tested at snarkjs v0.7.0) - if (this.config.protocol !== 'groth16') { - throw new Error('Exporting zKey to JSON is only supported for Groth16 at the moment.'); - } - - path = this.path.ofCircuit(circuit, 'pkey'); - json = await snarkjs.zKey.exportJson(path); - break; - } - // Witness - case 'wtns': { - if (!input) throw new Error('Expected input'); - path = this.path.ofCircuitWithInput(circuit, input, 'wtns'); - json = await snarkjs.wtns.exportJson(path); - break; - } - default: - target satisfies never; - throw new Error('Unknown export target: ' + target); - } - - return { - json, - path: path + '.json', - }; - } - - /** Compiles the circuit and returns a witness tester instance. */ - async WitnessTester( - circuit: string, - circuitConfig: CircuitConfig & {recompile?: boolean}, - tester: 'wasm' | 'c' = 'wasm' - ) { - circuitConfig.dir ??= 'test'; // defaults to test directory - - const targetPath = this.instantiate(circuit, circuitConfig); - const circomWasmTester: CircomTester = await (tester === 'wasm' ? wasm_tester : c_tester)(targetPath, { - output: undefined, // this makes tests to be created under /tmp - prime: this.config.prime, - verbose: this.config.verbose, - O: typeof this.config.optimization === 'number' ? Math.min(this.config.optimization, 1) : undefined, // tester doesnt have O2 - json: false, - include: this.config.include, - wasm: true, - sym: true, - recompile: circuitConfig.recompile ?? true, - }); - - return new WitnessTester(circomWasmTester); - } - - /** Returns a proof tester. */ - async ProofTester( - circuit: string, - protocol: P - ) { - const wasmPath = this.path.ofCircuit(circuit, 'wasm'); - const pkeyPath = this.path.ofCircuit(circuit, 'pkey'); - const vkeyPath = this.path.ofCircuit(circuit, 'vkey'); - - const missingPaths = [wasmPath, pkeyPath, vkeyPath].filter(p => !existsSync(p)); - if (missingPaths.length !== 0) { - throw new Error('Missing files: ' + missingPaths.join(', ')); - } - - return new ProofTester(wasmPath, pkeyPath, vkeyPath, protocol); - } -} diff --git a/src/core/pathing.ts b/src/core/pathing.ts deleted file mode 100644 index 8f9857a..0000000 --- a/src/core/pathing.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type {CircomkitConfig} from '../configs'; - -/** Utility class to handle path abstractions. - * - * This class takes in a reference to the Circomkit configuration and provides the correct pathing. - */ -export class CircomkitPath { - constructor(private readonly config: CircomkitConfig) {} - - /** - * Computes a path that requires a circuit name. - * - * @param circuit The name of the circuit. - * @param kind The kind of file to compute the path for. - */ - ofCircuit(circuit: string, kind: 'main' | 'sym' | 'pkey' | 'vkey' | 'wasm' | 'sol' | 'dir' | 'r1cs'): string { - const dir = `${this.config.dirBuild}/${circuit}`; - switch (kind) { - case 'dir': - return dir; - case 'main': - return `${this.config.dirCircuits}/main/${circuit}.circom`; - case 'r1cs': - return `${dir}/${circuit}.r1cs`; - case 'sym': - return `${dir}/${circuit}.sym`; - case 'wasm': - return `${dir}/${circuit}_js/${circuit}.wasm`; - case 'pkey': - return `${dir}/${this.config.protocol}_pkey.zkey`; - case 'vkey': - return `${dir}/${this.config.protocol}_vkey.json`; - case 'sol': - return `${dir}/${this.config.protocol}_verifier.sol`; - default: - kind satisfies never; - throw new Error('Invalid kind: ' + kind); - } - } - - /** - * Computes a path that requires a circuit and an input name. - * - * @param circuit The name of the circuit. - * @param input The name of the input. - * @param kind The kind of file to compute the path for. - */ - ofCircuitWithInput(circuit: string, input: string, kind: 'pubs' | 'proof' | 'wtns' | 'in' | 'dir'): string { - const dir = `${this.config.dirBuild}/${circuit}/${input}`; - switch (kind) { - case 'dir': - return dir; - case 'wtns': - return `${dir}/witness.wtns`; - case 'pubs': - return `${dir}/public.json`; - case 'proof': - return `${dir}/${this.config.protocol}_proof.json`; - case 'in': - return `${this.config.dirInputs}/${circuit}/${input}.json`; - default: - kind satisfies never; - throw new Error('Invalid type: ' + kind); - } - } - - /** - * Given a PTAU name, returns the relative path. - * - * @param ptauName The name of the PTAU file, e.g. `powersOfTau28_hez_final_08.ptau`. - */ - ofPtau(ptauName: string): string { - return `${this.config.dirPtau}/${ptauName}`; - } - - /** - * Given a circuit & id name, returns the relative path of the phase-2 PTAU. - * - * This is used in particular by Groth16's circuit-specific setup phase. - * - * @param circuit The name of the circuit. - * @param id The id of the zKey. - */ - ofZkey(circuit: string, id: number): string { - return `${this.config.dirBuild}/${circuit}/${circuit}_${id}.zkey`; - } -} diff --git a/src/functions/calldata.ts b/src/functions/calldata.ts deleted file mode 100644 index 6c59cf2..0000000 --- a/src/functions/calldata.ts +++ /dev/null @@ -1,122 +0,0 @@ -import type {FflonkProof, Groth16Proof, PlonkProof, PublicSignals} from 'snarkjs'; - -/** - * Returns a calldata for the given proof & public signals, with regards to a Solidity verifier contract. - * - * @param proof a SnarkJS proof, the protocol is derived from `protocol` field within the proof. - * @param pubs public signals - * @param pretty whether to print Solidity compatible output - * @returns calldata as a string - */ -export function getCalldata( - proof: FflonkProof & Groth16Proof & PlonkProof, - pubs: PublicSignals, - pretty: boolean = false -) { - const pubsCalldata: string = publicSignalsCalldata(pubs, pretty); - let proofCalldata: string; - switch (proof.protocol) { - case 'groth16': - proofCalldata = groth16Calldata(proof, pretty); - break; - case 'plonk': - proofCalldata = plonkCalldata(proof, pretty); - break; - case 'fflonk': - proofCalldata = fflonkCalldata(proof, pretty); - break; - default: - throw 'Unknown protocol:' + proof.protocol; - } - - return `\n${proofCalldata}\n\n${pubsCalldata}\n`; -} - -function publicSignalsCalldata(pubs: PublicSignals, pretty: boolean): string { - const pubs256 = valuesToPaddedUint256s(pubs); - if (pretty) { - return `uint[${pubs.length}] memory pubs = [\n ${pubs256.join(',\n ')}\n];`; - } else { - return `[${pubs256.map(s => `"${s}"`).join(',')}]`; - } -} - -function fflonkCalldata(proof: FflonkProof, pretty: boolean): string { - // prettier-ignore - const vals = valuesToPaddedUint256s([ - proof.polynomials.C1[0], proof.polynomials.C1[1], - proof.polynomials.C2[0], proof.polynomials.C2[1], - proof.polynomials.W1[0], proof.polynomials.W1[1], - proof.polynomials.W2[0], proof.polynomials.W2[1], - proof.evaluations.ql, proof.evaluations.qr, proof.evaluations.qm, - proof.evaluations.qo, proof.evaluations.qc, - proof.evaluations.s1, proof.evaluations.s2, proof.evaluations.s3, - proof.evaluations.a, proof.evaluations.b, proof.evaluations.c, - proof.evaluations.z, proof.evaluations.zw, - proof.evaluations.t1w, proof.evaluations.t2w, - proof.evaluations.inv, - ]); - - if (pretty) { - return `uint256[24] memory proof = [\n ${vals.join(',\n ')}\n];`; - } else { - return `[${withQuotes(vals).join(',')}]`; - } -} - -function plonkCalldata(proof: PlonkProof, pretty: boolean = false) { - // prettier-ignore - const vals = valuesToPaddedUint256s([ - proof.A[0], proof.A[1], proof.B[0], proof.B[1], proof.C[0], proof.C[1], - proof.Z[0], proof.Z[1], - proof.T1[0], proof.T1[1], proof.T2[0], proof.T2[1], proof.T3[0], proof.T3[1], - proof.Wxi[0], proof.Wxi[1], - proof.Wxiw[0], proof.Wxiw[1], - proof.eval_a, proof.eval_b, proof.eval_c, - proof.eval_s1, proof.eval_s2, - proof.eval_zw, - ]); - - if (pretty) { - return `uint[24] memory proof = [\n ${vals.join(',\n ')}\n];`; - } else { - return `[${withQuotes(vals).join(',')}]`; - } -} - -function groth16Calldata(proof: Groth16Proof, pretty: boolean) { - const pA = valuesToPaddedUint256s([proof.pi_a[0], proof.pi_a[1]]); - // note that pB are reversed, the indexing is [1] and [0] instead of [0] and [1]. - const pB0 = valuesToPaddedUint256s([proof.pi_b[0][1], proof.pi_b[0][0]]); - const pB1 = valuesToPaddedUint256s([proof.pi_b[1][1], proof.pi_b[1][0]]); - const pC = valuesToPaddedUint256s([proof.pi_c[0], proof.pi_c[1]]); - - if (pretty) { - // the eternal struggle between "should i use a template literal" or "join with \n" - return [ - `uint[2] memory pA = [\n ${pA.join(',\n ')}\n];`, - `uint[2][2] memory pB = [\n [\n ${pB0.join(',\n ')}\n ],\n [\n ${pB1.join(',\n ')}\n ]\n];`, - `uint[2] memory pC = [\n ${pC.join(',\n ')}\n];`, - ].join('\n'); - } else { - return [ - `[${withQuotes(pA).join(', ')}]`, - `[[${withQuotes(pB0).join(', ')}], [${withQuotes(pB1).join(', ')}]]`, - `[${withQuotes(pC).join(', ')}]`, - ].join('\n'); - } -} - -/** Converts each hex-string in the array to 32-bytes long hexadecimal with 0x prefix. */ -function valuesToPaddedUint256s(values: string[]) { - return values.map(hexStr => { - const ans = '0x' + BigInt(hexStr).toString(16).padStart(64, '0'); - if (ans.length !== 66) throw new Error('uint256 overflow: ' + hexStr); - return ans; - }); -} - -/** Wraps each string in the array with double quotes. */ -function withQuotes(vals: string[]) { - return vals.map(val => `"${val}"`); -} diff --git a/src/functions/circuit.ts b/src/functions/circuit.ts deleted file mode 100644 index cb55ed2..0000000 --- a/src/functions/circuit.ts +++ /dev/null @@ -1,82 +0,0 @@ -import {existsSync, mkdirSync, writeFileSync} from 'fs'; -import {exec} from 'child_process'; -import type {CircuitConfig} from '../types'; -import type {CircomkitConfig} from '../configs'; - -// @todo make compilation config a separate entity derived from CircomkitConfig and be Partial. - -/** Compile the circuit using the given configuration. - * - * @param config The Circomkit configuration for the compiler. - * @param targetPath The path to the target circuit file with the main component. - * @param outDir The output directory for the compiled circuit. - * @returns The `stdout` and `stderr` of the compilation process. - */ -export async function compileCircuit(config: CircomkitConfig, targetPath: string, outDir: string) { - mkdirSync(outDir, {recursive: true}); - - // prettier-ignore - let flags = `--sym --r1cs -p ${config.prime} -o ${outDir}`; - if (config.include.length > 0) flags += ' ' + config.include.map(path => `-l ${path}`).join(' '); - if (config.verbose) flags += ' --verbose'; - if (config.inspect) flags += ' --inspect'; - if (config.cWitness) flags += ' --c'; - if (config.wasmWitness) flags += ' --wasm'; - if (typeof config.optimization === 'number') { - if (config.optimization > 2) { - // --O2round - flags += ` --O2round ${config.optimization}`; - } else { - // --O0, --O1 or --O2 - flags += ` --O${config.optimization}`; - } - } - - // call `circom` as a sub-process - try { - const result = await new Promise<{stdout: string; stderr: string}>((resolve, reject) => { - exec(`${config.circomPath} ${flags} ${targetPath}`, (error, stdout, stderr) => { - if (error === null) { - resolve({stdout, stderr}); - } else { - reject(error); - } - }); - }); - - return {...result}; - } catch (e) { - throw new Error('Compiler error:\n' + e); - } -} - -/** - * Programmatically creates the `main` component of a template circuit. - * @param config circuit configuration - * @param targetDir directory to save the circuit file - * @param targetPath name of the circuit file - */ -export function instantiateCircuit(config: Required, targetDir: string, targetPath: string) { - const circuitCode = makeCircuit(config); - - if (!existsSync(targetDir)) { - mkdirSync(targetDir, {recursive: true}); - } - - writeFileSync(targetPath, circuitCode); -} - -/** Builds the source code for a `main` component based on the circuit config, kind of like `ejs.render`. - * - * **Be very careful when editing this file.** */ -export function makeCircuit(config: Required) { - const {version, usesCustomTemplates, file, pubs, template, params} = config; - - return `// auto-generated by circomkit -pragma circom ${version}; -${usesCustomTemplates ? 'pragma custom_templates;\n' : ''} -include "../${file}.circom"; - -component main${pubs.length === 0 ? '' : ' {public[' + pubs.join(', ') + ']}'} = ${template}(${params.join(', ')}); -`; -} diff --git a/src/functions/index.ts b/src/functions/index.ts deleted file mode 100644 index c3a94f5..0000000 --- a/src/functions/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './r1cs'; -export * from './circuit'; -export * from './calldata'; diff --git a/src/functions/r1cs.ts b/src/functions/r1cs.ts deleted file mode 100644 index 05bd7cb..0000000 --- a/src/functions/r1cs.ts +++ /dev/null @@ -1,115 +0,0 @@ -import {ReadPosition, openSync, readSync} from 'fs'; -import {primeToName} from '../utils'; - -/** - * Some fields for the R1CS information, many other fields are omitted in this type. - */ -export type R1CSInfoType = { - wires: number; - constraints: number; - privateInputs: number; - publicInputs: number; - publicOutputs: number; - useCustomGates: boolean; - labels: number; - prime: bigint; - primeName: string; -}; - -/** Read the information about the circuit by extracting it from the R1CS file. - * - * This implementation follows the specs at [`iden3/r1csfile`](https://github.com/iden3/r1csfile/blob/master/doc/r1cs_bin_format.md) - * and is inspired from the work by [PSE's `p0tion`](https://github.com/privacy-scaling-explorations/p0tion/blob/f88bcee5d499dce975d0592ed10b21aa8d73bbd2/packages/actions/src/helpers/utils.ts#L413) - * and by [Weijiekoh's `circom-helper`](https://github.com/weijiekoh/circom-helper/blob/master/ts/read_num_inputs.ts#L5). - * - * @param r1csPath The path to the R1CS file. - * @returns The information about the circuit, as gathered from the R1CS header. - */ -export async function readR1CSInfo(r1csPath: string): Promise { - let pointer = 0; - - const r1csInfoType: R1CSInfoType = { - wires: 0, - constraints: 0, - privateInputs: 0, - publicInputs: 0, - publicOutputs: 0, - useCustomGates: false, - labels: 0, - prime: BigInt(0), - primeName: '', - }; - - // open the file (read mode). - const fd = openSync(r1csPath, 'r'); - - // get 'number of section' (jump magic r1cs and version1 data). - const numberOfSections = readBytesFromFile(fd, 0, 4, 8); - pointer = 12; - - for (let i = Number(numberOfSections); i >= 0; i--) { - const sectionType = Number(readBytesFromFile(fd, 0, 4, pointer)); - pointer += 4; - - const sectionSize = Number(readBytesFromFile(fd, 0, 8, pointer)); - pointer += 8; - - // @todo the docs of `read` indicate that if pointer is `null`, the pointer will actually move w.r.t length - // we may actually use that instead of adding to point as done below - - switch (sectionType) { - // header section. - case 1: - // field size (skip). - pointer += 4; - - r1csInfoType.prime = readBytesFromFile(fd, 0, 32, pointer).toString() as unknown as bigint; - pointer += 32; - - r1csInfoType.wires = Number(readBytesFromFile(fd, 0, 4, pointer)); - pointer += 4; - - r1csInfoType.publicOutputs = Number(readBytesFromFile(fd, 0, 4, pointer)); - pointer += 4; - - r1csInfoType.publicInputs = Number(readBytesFromFile(fd, 0, 4, pointer)); - pointer += 4; - - r1csInfoType.privateInputs = Number(readBytesFromFile(fd, 0, 4, pointer)); - pointer += 4; - - r1csInfoType.labels = Number(readBytesFromFile(fd, 0, 8, pointer)); - pointer += 8; - - r1csInfoType.constraints = Number(readBytesFromFile(fd, 0, 4, pointer)); - pointer += 4; - break; - // custom gates list section (plonk only). - case 4: - r1csInfoType.useCustomGates = Number(readBytesFromFile(fd, 0, 4, pointer)) > 0; - - pointer += Number(sectionSize); - break; - default: - pointer += Number(sectionSize); - break; - } - } - - r1csInfoType.primeName = primeToName[r1csInfoType.prime.toString() as `${bigint}`]; - return r1csInfoType; -} - -/** Reads a specified number of bytes from a file and converts them to a `BigInt`. - * - * @param offset The position in `buffer` to write the data to. - * @param length The number of bytes to read. - * @param position Where to begin reading from in the file. - */ -export function readBytesFromFile(fd: number, offset: number, length: number, position: ReadPosition): BigInt { - const buffer = Buffer.alloc(length); - - readSync(fd, buffer, offset, length, position); - - return BigInt(`0x${buffer.reverse().toString('hex')}`); -} diff --git a/src/functions/symbols.ts b/src/functions/symbols.ts deleted file mode 100644 index 0adf2f9..0000000 --- a/src/functions/symbols.ts +++ /dev/null @@ -1 +0,0 @@ -// TODO: add symbol viewer here diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 7497357..0000000 --- a/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export {Circomkit} from './core'; - -export type {ProofTester, WitnessTester} from './testers/'; -export type {CircuitSignals, CircuitConfig} from './types'; -export type {CircomkitConfig} from './configs'; diff --git a/src/testers/index.ts b/src/testers/index.ts deleted file mode 100644 index 652d8d6..0000000 --- a/src/testers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './witnessTester'; -export * from './proofTester'; diff --git a/src/testers/proofTester.ts b/src/testers/proofTester.ts deleted file mode 100644 index cd29236..0000000 --- a/src/testers/proofTester.ts +++ /dev/null @@ -1,81 +0,0 @@ -import type {FflonkProof, Groth16Proof, PlonkProof, PublicSignals} from 'snarkjs'; -import * as snarkjs from 'snarkjs'; -import {readFileSync} from 'fs'; -import type {CircuitSignals} from '../types/'; -import type {CircomkitConfig} from '../configs'; -import {AssertionError} from 'node:assert'; - -/** A tester that is able to generate proofs & verify them. - * Use `expectFail` and `expectPass` to test out evaluations. */ -export class ProofTester { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public readonly verificationKey: any; - - constructor( - readonly wasmPath: string, - readonly pkeyPath: string, - readonly vkeyPath: string, - readonly protocol: P - ) { - this.verificationKey = JSON.parse(readFileSync(vkeyPath).toString()) as typeof this.verificationKey; - if (this.verificationKey.protocol !== protocol) { - throw new Error('Protocol mismatch.'); - } - } - - /** Generate a proof for the witness computed from the given input signals. */ - async prove(input: CircuitSignals): Promise<{proof: Groth16Proof; publicSignals: PublicSignals}>; - async prove(input: CircuitSignals): Promise<{proof: PlonkProof; publicSignals: PublicSignals}>; - async prove(input: CircuitSignals): Promise<{proof: FflonkProof; publicSignals: PublicSignals}>; - async prove( - input: CircuitSignals - ): Promise< - | {proof: Groth16Proof; publicSignals: PublicSignals} - | {proof: PlonkProof; publicSignals: PublicSignals} - | {proof: FflonkProof; publicSignals: PublicSignals} - > { - return snarkjs[this.protocol].fullProve(input, this.wasmPath, this.pkeyPath, undefined); - } - - /** Returns the verification result of a proof for some public signals. */ - async verify(proof: Groth16Proof, publicSignals: PublicSignals): Promise; - async verify(proof: PlonkProof, publicSignals: PublicSignals): Promise; - async verify(proof: FflonkProof, publicSignals: PublicSignals): Promise; - async verify(proof: Groth16Proof | PlonkProof | FflonkProof, publicSignals: PublicSignals): Promise { - return await snarkjs[this.protocol].verify( - this.verificationKey, - publicSignals, - proof as Groth16Proof & PlonkProof & FflonkProof - ); - } - - /** Expects a verification to pass for this proof and public signals. */ - async expectPass(proof: Groth16Proof, publicSignals: PublicSignals): Promise; - async expectPass(proof: PlonkProof, publicSignals: PublicSignals): Promise; - async expectPass(proof: FflonkProof, publicSignals: PublicSignals): Promise; - async expectPass(proof: Groth16Proof | PlonkProof | FflonkProof, publicSignals: PublicSignals): Promise { - const ok = await this.verify(proof as Groth16Proof & PlonkProof & FflonkProof, publicSignals); - if (!ok) { - throw new AssertionError({ - message: 'Expected proof to be verified.', - expected: true, - actual: false, - }); - } - } - - /** Expects a verification to fail for this proof and public signals. */ - async expectFail(proof: Groth16Proof, publicSignals: PublicSignals): Promise; - async expectFail(proof: PlonkProof, publicSignals: PublicSignals): Promise; - async expectFail(proof: FflonkProof, publicSignals: PublicSignals): Promise; - async expectFail(proof: Groth16Proof | PlonkProof | FflonkProof, publicSignals: PublicSignals): Promise { - const ok = await this.verify(proof as Groth16Proof & PlonkProof & FflonkProof, publicSignals); - if (ok) { - throw new AssertionError({ - message: 'Expected proof to be not verified.', - expected: false, - actual: true, - }); - } - } -} diff --git a/src/testers/witnessTester.ts b/src/testers/witnessTester.ts deleted file mode 100644 index bc94a2f..0000000 --- a/src/testers/witnessTester.ts +++ /dev/null @@ -1,368 +0,0 @@ -import {AssertionError} from 'node:assert'; -import type {CircomTester, WitnessType, CircuitSignals, SymbolsType, SignalValueType} from '../types/'; -import path from 'node:path'; -import fs from 'node:fs'; - -// @todo detect optimized symbols https://github.com/erhant/circomkit/issues/80 - -/** A utility class to test your circuits. Use `expectFail` and `expectPass` to test out evaluations. */ -export class WitnessTester { - /** A dictionary of symbols, see {@link loadSymbols} */ - private symbols: SymbolsType | undefined; - /** List of constraints, see {@link loadConstraints} */ - private constraints: unknown[] | undefined; - - constructor( - /** The underlying `circom_tester` object */ - private readonly circomTester: CircomTester - ) {} - - /** Assert that constraints are valid for a given witness. */ - async expectConstraintPass(witness: WitnessType): Promise { - return this.circomTester.checkConstraints(witness); - } - - /** - * Assert that constraints are NOT valid for a given witness. - * This is useful to test if a fake witness (a witness from a - * dishonest prover) can still be valid, which would indicate - * that there are soundness errors in the circuit. - */ - async expectConstraintFail(witness: WitnessType): Promise { - await this.expectConstraintPass(witness).then( - () => { - throw new AssertionError({message: 'Expected constraints to not match.'}); - }, - err => { - if (err.message !== "Constraint doesn't match") { - throw new AssertionError({message: err.message}); - } - } - ); - } - - /** Compute witness given the input signals. */ - async calculateWitness(input: CircuitSignals): Promise { - return this.circomTester.calculateWitness(input, false); - } - - /** Returns the number of constraints. */ - async getConstraintCount() { - if (this.constraints === undefined) { - await this.loadConstraints(); - } - const numConstraints = this.constraints!.length; - return numConstraints; - } - - /** Asserts that the circuit has enough constraints. - * - * By default, this function checks if there **at least** `expected` many constraints in the circuit. - * If `exact` option is set to `true`, it will also check if the number of constraints is exactly equal to - * the `expected` amount. - * - * If first check fails, it means the circuit is under-constrained. If the second check fails, it means - * the circuit is over-constrained. - */ - async expectConstraintCount(expected: number, exact?: boolean) { - const count = await this.getConstraintCount(); - if (count < expected) { - throw new AssertionError({ - message: 'Circuit is under-constrained', - expected, - actual: count, - }); - } - - if (exact && count !== expected) { - throw new AssertionError({ - message: 'Circuit is over-constrained', - expected, - actual: count, - }); - } - } - - /** Expect a witness computation to fail in the circuit. - * - * See [here](https://github.com/iden3/circom/blob/master/code_producers/src/wasm_elements/common/witness_calculator.js#L21) - * for the list of errors that may occur during witness calculation. - * Most of the time, you will be expecting an assertion error. - * - * @returns the error message. - */ - async expectFail(input: CircuitSignals): Promise { - return await this.calculateWitness(input).then( - () => { - throw new AssertionError({ - message: 'Expected witness calculation to fail.', - }); - }, - err => { - const errorMessage = (err as Error).message; - - const isExpectedError = [ - 'Error: Assert Failed.', // a constraint failure (most common) - 'Not enough values for input signal', // few inputs than expected for a signal - 'Too many values for input signal', // more inputs than expected for a signal - 'Not all inputs have been set.', // few inputs than expected for many signals - ].some(msg => errorMessage.startsWith(msg)); - - // throw unhandled error anyways - if (!isExpectedError) throw err; - - return errorMessage; - } - ); - } - - /** Expect an input to pass assertions and match the output. - * - * If `output` is omitted, it will only check for constraints to pass. - */ - async expectPass(input: CircuitSignals, output?: CircuitSignals) { - const witness = await this.calculateWitness(input); - await this.expectConstraintPass(witness); - if (output) { - await this.assertOut(witness, output); - } - } - - /** - * Computes the witness. - * This is a shorthand for calculating the witness and calling {@link readWitnessSignals} on the result. - */ - async compute(input: CircuitSignals, signals: string[] | OUT): Promise { - // compute witness & check constraints - const witness = await this.calculateWitness(input); - await this.expectConstraintPass(witness); - - return await this.readWitnessSignals(witness, signals); - } - - /** - * Override witness value to try and fake a proof. If the circuit has soundness problems (i.e. - * some signals are not constrained correctly), then you may be able to create a fake witness by - * overriding specific values, and pass the constraints check. - * - * The symbol names must be given in full form, not just as the signal is named in the circuit code. In - * general a symbol name looks something like: - * - * - `main.signal` - * - `main.component.signal` - * - `main.component.signal[n][m]` - * - * You will likely call `expectConstraintPass` on the resulting fake witness to see if it can indeed fool - * a verifier. - * @see {@link expectConstraintPass} - */ - async editWitness( - witness: Readonly, - symbolValues: {[symbolName: string]: bigint} - ): Promise { - await this.loadSymbols(); - - const fakeWitness = witness.slice(); - for (const symbolName in symbolValues) { - // get corresponding symbol - const symbolInfo = this.symbols![symbolName]; - if (symbolInfo === undefined) { - throw new Error('Invalid symbol name: ' + symbolName); - } - - // override with user value - fakeWitness[symbolInfo.varIdx] = symbolValues[symbolName]; - } - - return fakeWitness; - } - - /** Read symbol values from a witness. */ - async readWitness(witness: Readonly, symbols: string[]): Promise> { - await this.loadSpecificSymbols(symbols); - - const ans: Record = {}; - for (const symbolName of symbols) { - // get corresponding symbol - const symbolInfo = this.symbols![symbolName]; - if (symbolInfo === undefined) { - throw new Error('Invalid symbol name: ' + symbolName); - } - - // override with user value - ans[symbolName] = witness[symbolInfo.varIdx]; - } - - return ans; - } - - /** - * Read signals from a witness. - * - * This is not the same as {@link readWitness} in the sense that the entire value represented by a signal - * will be returned here. For example, instead of reading `main.out[0], main.out[1], main.out[2]` with `readWitness`, - * you can simply query `out` in this function and an object with `{out: [...]}` will be returned. - * - * To read signals within a component, simply refer to them as `component.signal`. In other words, omit the `main.` prefix - * and array dimensions. - */ - async readWitnessSignals(witness: Readonly, signals: string[] | OUT): Promise { - await this.loadSymbols(); - - // for each out signal, process the respective symbol - const entries: [OUT[number], SignalValueType][] = []; - - // returns the dot count in the symbol - // for example `main.inner.in` has 2 dots - function dotCount(s: string): number { - return s.split('.').length; - } - - for (const signal of signals) { - // if our symbol has N dots (0 for `main` signals), we must filter symbols that have different - // amount of dots. this shall speed-up the rest of the algorithm, as symbol count may be large - // non-main signals have an additional `.` in them after `main.symbol` - const signalDotCount = dotCount(signal) + 1; // +1 for the dot in `main.` - const signalLength = signal.length + 5; // +5 for prefix `main.` - const symbolNames = Object.keys(this.symbols!).filter( - s => s.startsWith(`main.${signal}`) && signalDotCount === dotCount(s) - ); - - // get the symbol values from symbol names, ignoring `main.` prefix - // the matched symbols must exactly equal the signal - const matchedSymbols = symbolNames.filter(s => { - const i = s.indexOf('['); - if (i === -1) { - // not an array signal - return s.length === signalLength; - } else { - // an array signal, we only care about the symbol name - return s.slice(0, i).length === signalLength; - } - }); - - if (matchedSymbols.length === 0) { - // no matches! - throw new Error('No symbols matched for signal: ' + signal); - } else if (matchedSymbols.length === 1) { - // easy case, just return the witness of this symbol - entries.push([signal, witness[this.symbols![matchedSymbols[0]].varIdx]]); - } else { - // since signal names are consequent, we only need to know the witness index of the first symbol - let idx = this.symbols![matchedSymbols[0]].varIdx; - - // we can assume that a symbol with this name appears only once in a component, and that the depth is same for - // all occurrences of this symbol, given the type system used in Circom. So, we can just count the number - // of `[`s in any symbol of this signal to find the number of dimensions of this signal. - // we particularly choose the last symbol in the array, as that holds the maximum index of each dimension of this array. - const splits = matchedSymbols.at(-1)!.split('['); - - // since we chose the last symbol, we have something like `main.signal[dim1][dim2]...[dimN]` which we can parse - const dims = splits.slice(1).map(dim => parseInt(dim.slice(0, -1)) + 1); // +1 is needed because the final value is 0-indexed - - // at this point, we have an array of signals like `main.signal[0..dim1][0..dim2]..[0..dimN]` - // and we must construct the necessary multi-dimensional array out of it. - // eslint-disable-next-line no-inner-declarations - function processDepth(d: number): SignalValueType { - const acc: SignalValueType = []; - if (d === dims.length - 1) { - // final depth, count witnesses - for (let i = 0; i < dims[d]; i++) { - acc.push(witness[idx++]); - } - } else { - // not final depth, recurse to next - for (let i = 0; i < dims[d]; i++) { - acc.push(processDepth(d + 1)); - } - } - return acc; - } - entries.push([signal, processDepth(0)]); - } - } - - return Object.fromEntries(entries) as CircuitSignals; - } - - /** - * Assert the output of a given witness. - * @param actualOut expected witness - * @param expectedOut computed output signals - */ - private assertOut(actualOut: WitnessType, expectedOut: CircuitSignals): Promise { - return this.circomTester.assertOut(actualOut, expectedOut); - } - - /** Loads the list of R1CS constraints to `this.constraints`. */ - private async loadConstraints(): Promise { - await this.circomTester.loadConstraints(); - this.constraints = this.circomTester.constraints; - } - - /** - * Loads the symbols in a dictionary at `this.symbols` - * Symbols are stored under the .sym file - * - * Each line has 4 comma-separated values: - * - * 1. symbol name - * 2. label index - * 3. variable index - * 4. component index - */ - private async loadSymbols(): Promise { - // no need to check if symbols are already defined - // that check happens within circomWasmTester - await this.circomTester.loadSymbols(); - this.symbols = this.circomTester.symbols; - } - - /** Faster alternative to this.circomTester.loadSymbols(), - * stops once all the requested symbols are found */ - private async loadSpecificSymbols(symbolsRequested: string[]): Promise { - if (!this.symbols) this.symbols = {}; // Init if missing - - // Identify which symbols are still needed - const symbolsToFind = new Set(symbolsRequested.filter(s => !this.symbols?.[s])); - if (symbolsToFind.size === 0) return; - - // Read the symbols file into memory - const symbolsFile = await fs.promises.readFile( - path.join(this.circomTester.dir, this.circomTester.baseName + '.sym'), - 'utf8' - ); - - // Start looking for the requested symbols - for (const line of symbolsFile.split('\n')) { - if (symbolsToFind.size === 0) return; // Stop when all found - - const [labelIdx, varIdx, componentIdx, symbolName] = line.split(','); - if (!symbolName || !symbolsToFind.has(symbolName)) continue; // Skip non-requested symbols - - // Add found symbols to the symbols map, like circomTester.loadSymbols() - this.symbols[symbolName] = { - labelIdx: Number(labelIdx), - varIdx: Number(varIdx), - componentIdx: Number(componentIdx), - }; - symbolsToFind.delete(symbolName); // Remove from list - } - } - - /** - * @deprecated this is buggy right now - * @param witness witness - */ - private getDecoratedOutput(witness: WitnessType): Promise { - return this.circomTester.getDecoratedOutput(witness); - } - - /** - * Cleanup directory, should probably be called upon test completion (?) - * @deprecated this is buggy right now - */ - private release(): Promise { - return this.circomTester.release(); - } -} diff --git a/src/types/index.ts b/src/types/index.ts deleted file mode 100644 index 5d64c8b..0000000 --- a/src/types/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** An integer value is a numerical string, a number, or a bigint. */ -export type IntegerValueType = `${number}` | number | bigint; - -/** A signal value is a number, or an array of numbers (recursively). */ -export type SignalValueType = IntegerValueType | SignalValueType[]; - -/** - * An object with string keys and array of numerical values. - * Each key represents a signal name as it appears in the circuit. - * - * By default, signal names are not typed, but you can pass an array of signal names - * to make them type-safe, e.g. `CircuitSignals<['sig1', 'sig2']>` - */ -export type CircuitSignals = T extends [] - ? {[signal: string]: SignalValueType} - : {[signal in T[number]]: SignalValueType}; - -/** A witness is an array of `bigint`s, corresponding to the values of each wire in the evaluation of the circuit. */ -export type WitnessType = bigint[]; - -/** - * Symbols are a mapping of each circuit `wire` to an object with three keys. Within them, - * the most important is `varIdx` which indicates the position of this signal in the witness array. - */ -export type SymbolsType = { - [symbol: string]: { - labelIdx: number; - varIdx: number; - componentIdx: number; - }; -}; - -/** A configuration object for circuit main components. */ -export type CircuitConfig = { - /** File to read the template from */ - file: string; - /** The template name to instantiate */ - template: string; - /** Directory to instantiate at */ - dir?: string; - /** Target version */ - version?: `${number}.${number}.${number}`; - /** An array of public input signal names, defaults to `[]` */ - pubs?: string[]; - /** An array of template parameters, defaults to `[]` */ - params?: (number | bigint)[]; - /** Include `pragma custom_templates;` in instantiation */ - usesCustomTemplates?: boolean; -}; - -/** - * A simple type-wrapper for `circom_tester` WASM tester class. - * Not all functions may exist here, some are omitted. - * @see https://github.com/iden3/circom_tester/blob/main/wasm/tester.js - */ -export type CircomTester = { - checkConstraints: (witness: WitnessType) => Promise; - release: () => Promise; - assertOut: (actualOut: WitnessType, expectedOut: CircuitSignals) => Promise; - calculateWitness: (input: CircuitSignals, sanityCheck: boolean) => Promise; - loadConstraints: () => Promise; - constraints: unknown[] | undefined; - loadSymbols: () => Promise; - symbols: SymbolsType | undefined; - getDecoratedOutput: (witness: WitnessType) => Promise; - dir: string; - baseName: string; -}; diff --git a/src/utils/index.ts b/src/utils/index.ts deleted file mode 100644 index bba27d8..0000000 --- a/src/utils/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type {CircomkitConfig} from '../configs'; - -/** A mapping from prime names to prime value as supported by Circom's `-p` option. */ -export const primes: Record = { - bn128: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), - bls12381: BigInt('52435875175126190479447740508185965837690552500527637822603658699938581184513'), - goldilocks: BigInt('18446744069414584321'), - grumpkin: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), - pallas: BigInt('28948022309329048855892746252171976963363056481941560715954676764349967630337'), - vesta: BigInt('28948022309329048855892746252171976963363056481941647379679742748393362948097'), - secq256r1: BigInt('115792089210356248762697446949407573530086143415290314195533631308867097853951'), -} as const; - -/** A mapping from prime (decimals or hexadecimal) to prime name as supported by Circom's `-p` option. */ -export const primeToName: Record<`${bigint}`, CircomkitConfig['prime']> = { - '21888242871839275222246405745257275088548364400416034343698204186575808495617': 'bn128', - '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001': 'bn128', - - '52435875175126190479447740508185965837690552500527637822603658699938581184513': 'bls12381', - '0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001': 'bls12381', - - '18446744069414584321': 'goldilocks', - '0xffffffff00000001': 'goldilocks', - - '21888242871839275222246405745257275088696311157297823662689037894645226208583': 'grumpkin', - '0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47': 'grumpkin', - - '28948022309329048855892746252171976963363056481941560715954676764349967630337': 'pallas', - '0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001': 'pallas', - - '28948022309329048855892746252171976963363056481941647379679742748393362948097': 'vesta', - '0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001': 'vesta', - - '115792089210356248762697446949407573530086143415290314195533631308867097853951': 'secq256r1', - '0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff': 'secq256r1', -} as const; - -/** JSON Stringify with a prettier format. */ -export function prettyStringify(obj: unknown): string { - return JSON.stringify(obj, undefined, 2); -} diff --git a/src/utils/ptau.ts b/src/utils/ptau.ts deleted file mode 100644 index 3cb4b64..0000000 --- a/src/utils/ptau.ts +++ /dev/null @@ -1,51 +0,0 @@ -import {createWriteStream} from 'fs'; -import {get} from 'https'; - -/** Base PTAU URL as seen in [SnarkJS docs](https://github.com/iden3/snarkjs#7-prepare-phase-2). */ -const PTAU_URL_BASE = 'https://storage.googleapis.com/zkevm/ptau'; - -/** - * Returns the name of PTAU file for a given number of constraints. - * @see https://github.com/iden3/snarkjs#7-prepare-phase-2 - * @param n number of constraints - * @returns name of the PTAU file - */ -export function getPtauName(n: number): string { - // smallest p such that 2^p >= n - const p = Math.ceil(Math.log2(n)); - - let id = ''; // default for large values - if (p < 8) { - id = '_08'; - } else if (p < 10) { - id = `_0${p}`; - } else if (p < 28) { - id = `_${p}`; - } else if (p === 28) { - id = ''; - } else { - throw new Error('No PTAU for that many constraints!'); - } - return `powersOfTau28_hez_final${id}.ptau`; -} - -/** - * Downloads phase-1 powers of tau from Polygon Hermez. - * @see https://github.com/iden3/snarkjs#7-prepare-phase-2 - * @param ptauName name of PTAU file - * @param ptauDir directory to download to - * @returns path to downloaded PTAU file - */ -export function downloadPtau(ptauName: string, ptauDir: string): Promise { - const ptauPath = `${ptauDir}/${ptauName}`; - const file = createWriteStream(ptauPath); - return new Promise(resolve => { - get(`${PTAU_URL_BASE}/${ptauName}`, response => { - response.pipe(file); - file.on('finish', () => { - file.close(); - resolve(ptauPath); - }); - }); - }); -} diff --git a/src/utils/teardown.ts b/src/utils/teardown.ts deleted file mode 100644 index 137ac42..0000000 --- a/src/utils/teardown.ts +++ /dev/null @@ -1,15 +0,0 @@ -declare global { - // eslint-disable-next-line no-var - var curve_bn128: {terminate: () => Promise} | undefined; -} - -/** - * Teardown function to be run for graceful exits. - * - * SnarkJS may attach curve_bn128 to global, but does not terminate it. - * We have to do it manually (see https://github.com/iden3/snarkjs/issues/152) - * For this, we use the [`terminate`](https://github.com/iden3/ffjavascript/blob/master/src/bn128.js#L48) function. - */ -export async function teardown() { - if (globalThis.curve_bn128) await globalThis.curve_bn128.terminate(); -} diff --git a/tests/circomkit.json b/tests/circomkit.json new file mode 100644 index 0000000..cd60311 --- /dev/null +++ b/tests/circomkit.json @@ -0,0 +1,46 @@ +{ + "$schema": "../schema.json", + "compiler": { + "srcDir": "./tests/circuits", + "outDir": "./tests/build", + "optimization": 0, + "verbose": false + }, + "prover": { + "protocol": "groth16", + "ptauDir": "./tests/ptau", + "inputDir": "./tests/inputs", + "verbose": false + }, + "logLevel": "silent", + "circuits": { + "multiplier_3": { + "file": "multiplier", + "template": "Multiplier", + "params": [3] + }, + "arrays_2_3": { + "file": "arrays", + "template": "Arrays", + "params": [2, 3], + "pubs": ["in1D", "in2D"] + }, + "errors": { + "file": "errors", + "template": "Errors" + }, + "custom_mul": { + "file": "custom", + "template": "CustomMultiplier", + "usesCustomTemplates": true + }, + "bounded_add_8": { + "file": "tags", + "template": "BoundedAdd_wrapper", + "params": [8], + "overrides": { + "version": "2.2.0" + } + } + } +} diff --git a/tests/circomkit.test.ts b/tests/circomkit.test.ts deleted file mode 100644 index b7a586f..0000000 --- a/tests/circomkit.test.ts +++ /dev/null @@ -1,196 +0,0 @@ -import hre from 'hardhat'; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import solc from 'solc'; -import {Circomkit} from '../src'; -import {existsSync, rmSync, readFileSync} from 'fs'; -import {PTAU_PATH, prepareMultiplier} from './common'; -import {PROTOCOLS} from '../src/configs'; - -describe('circomkit', () => { - // we are not testing all curves because PTAU is only available for bn128 - PROTOCOLS.map(protocol => - describe('protocol: ' + protocol, () => { - let circomkit: Circomkit; - const {circuit, signals, inputName} = prepareMultiplier(3); - - beforeAll(() => { - circomkit = new Circomkit({ - protocol, - verbose: false, - logLevel: 'silent', - circuits: './tests/circuits.json', - dirPtau: './tests/ptau', - dirCircuits: './tests/circuits', - dirInputs: './tests/inputs', - dirBuild: './tests/build', - }); - }); - - it('should instantiate circuit', () => { - const path = circomkit.instantiate(circuit.name, circuit.config); - expect(existsSync(path)).toBe(true); - rmSync(path); // remove it to see if compile command creates it too - }); - - it('should compile circuit', async () => { - const outPath = await circomkit.compile(circuit.name); - expect(existsSync(`${outPath}/${circuit.name}_js`)).toBe(true); // js is built by default - expect(existsSync(`${outPath}/${circuit.name}_cpp`)).toBe(false); // cpp is NOT built by default - }); - - it('should export circuit information', async () => { - await circomkit.info(circuit.name); - }); - - it('should setup circuit', async () => { - const {proverKeyPath, verifierKeyPath} = await circomkit.setup(circuit.name, PTAU_PATH); - expect(existsSync(proverKeyPath)).toBe(true); - expect(existsSync(verifierKeyPath)).toBe(true); - }); - - it('should export a verification key given a circuit name and a prover key path', async () => { - const {proverKeyPath} = await circomkit.setup(circuit.name, PTAU_PATH); - const vkeyPath = await circomkit.vkey(circuit.name, proverKeyPath); - expect(existsSync(vkeyPath)).toBe(true); - }); - - it('should export a verification key given a circuit name', async () => { - const vkeyPath = await circomkit.vkey(circuit.name); - expect(existsSync(vkeyPath)).toBe(true); - }); - - it('should throw when exporting a verification key given an invalid prover key path', async () => { - try { - await circomkit.vkey(circuit.name, 'non-existent-path'); - } catch (err) { - expect((err as Error).message).toBe( - 'There must be a prover key for this circuit to extract a verification key.' - ); - } - }); - - it('should create an input', async () => { - const path = circomkit.input(circuit.name, inputName, signals.input); - expect(existsSync(path)).toBe(true); - }); - - it('should create a witness', async () => { - const path = await circomkit.witness(circuit.name, inputName); - expect(existsSync(path)).toBe(true); - }); - - it('should create a proof', async () => { - const path = await circomkit.prove(circuit.name, inputName); - expect(existsSync(path)).toBe(true); - }); - - it('should verify the proof', async () => { - const isVerified = await circomkit.verify(circuit.name, inputName); - expect(isVerified).toBe(true); - }); - - it('should export verifier contract and valid calldata', async () => { - const path = await circomkit.contract(circuit.name); - expect(existsSync(path)).toBe(true); - const source = readFileSync(path, {encoding: 'utf-8'}) - // XXX: snarkjs plonk template has an erroneous hardhat import - // See https://github.com/iden3/snarkjs/pull/464 - // @todo Remove this fix when the PR is merged - .replace('import "hardhat/console.sol";\n', ''); - - // compile the contract - const input = { - language: 'Solidity', - sources: { - 'TestVerifier.sol': { - content: source, - }, - }, - settings: { - outputSelection: { - '*': { - '*': ['abi', 'evm.bytecode.object'], - }, - }, - }, - }; - - const output = JSON.parse(solc.compile(JSON.stringify(input))); - const contractName = Object.keys(output.contracts['TestVerifier.sol'])[0]; - const bytecode = output.contracts['TestVerifier.sol'][contractName].evm.bytecode.object; - const abi = output.contracts['TestVerifier.sol'][contractName].abi; - - // deploy the contract - const signer = (await hre.ethers.getSigners())[0]; - const ContractFactory = new hre.ethers.ContractFactory(abi, bytecode, signer); - const contract = await ContractFactory.deploy(); - await contract.waitForDeployment(); - - // interaction with the contract - const calldata = await circomkit.calldata(circuit.name, inputName); - const args = calldata - .split('\n') - .filter(x => !!x) - .map(x => JSON.parse(x)); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - expect(await contract.verifyProof(...args)).toBe(true); - }); - - it('should export JSON files', async () => { - await circomkit.json('r1cs', circuit.name); - await circomkit.json('wtns', circuit.name, inputName); - - try { - await circomkit.json('zkey', circuit.name); - - // only groth16 is allowed to export zkey - if (protocol !== 'groth16') { - throw new Error('Should have thrown an error before this.'); - } - } catch (err) { - expect((err as Error).message).toBe('Exporting zKey to JSON is only supported for Groth16 at the moment.'); - } - }); - }) - ); -}); - -describe('instantiate version fallback (#123)', () => { - const {circuit} = prepareMultiplier(3); - const baseConfig = { - verbose: false, - logLevel: 'silent' as const, - circuits: './tests/circuits.json', - dirPtau: './tests/ptau', - dirCircuits: './tests/circuits', - dirInputs: './tests/inputs', - dirBuild: './tests/build', - }; - - it('should use this.config.version when circuitConfig has no version field', () => { - const customVersion = '2.1.9'; - const circomkit = new Circomkit({...baseConfig, version: customVersion}); - - const path = circomkit.instantiate('multiplier_version_fallback', circuit.config); - const content = readFileSync(path, 'utf-8'); - expect(content).toContain(`pragma circom ${customVersion};`); - - rmSync(path); - }); - - it('should prefer circuitConfig.version over this.config.version', () => { - const circomkit = new Circomkit({...baseConfig, version: '2.1.9'}); - - const path = circomkit.instantiate('multiplier_version_override', { - ...circuit.config, - version: '2.2.0', - }); - const content = readFileSync(path, 'utf-8'); - expect(content).toContain('pragma circom 2.2.0;'); - - rmSync(path); - }); -}); diff --git a/tests/circuits.json b/tests/circuits.json deleted file mode 100644 index 6981a66..0000000 --- a/tests/circuits.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "multiplier_3": { - "file": "multiplier", - "template": "Multiplier", - "params": [3] - }, - "arrays_2_3": { - "file": "arrays", - "template": "Arrays", - "params": [2, 3], - "pubs": ["in1D", "in2D"] - }, - "uses_custom_templates": { - "file": "custom_templates", - "template": "MyTest" - } -} diff --git a/tests/circuits/custom.circom b/tests/circuits/custom.circom new file mode 100644 index 0000000..288a0d4 --- /dev/null +++ b/tests/circuits/custom.circom @@ -0,0 +1,20 @@ +pragma circom 2.1.0; +pragma custom_templates; + +/// A custom template (gate) that acts as a multiplier. +/// Custom templates define R1CS-level gates using signal assignments. +template custom CustomMul() { + signal input a; + signal input b; + signal output out; + + out <-- a * b; +} + +template CustomMultiplier() { + signal input in1; + signal input in2; + signal output out; + + out <== CustomMul()(in1, in2); +} diff --git a/tests/circuits/custom_templates.circom b/tests/circuits/custom_templates.circom deleted file mode 100644 index 24b4aa4..0000000 --- a/tests/circuits/custom_templates.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.0; -pragma custom_templates; - -template custom Example() { - // custom template's code -} - -template MyTest() { - signal input in; - signal output out; - - component example = Example(); // instantiation of the custom template - out <== in * 2; -} - diff --git a/tests/circuits/fibonacci/recursive.circom b/tests/circuits/fibonacci/recursive.circom deleted file mode 100644 index 718458a..0000000 --- a/tests/circuits/fibonacci/recursive.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.0.0; - -// Fibonacci with custom starting numbers, recursive & inefficient -template Fibonacci(n) { - signal input in[2]; - signal output out; - component f1, f2; - if (n <= 1) { - out <== in[n]; - } else { - f1 = Fibonacci(n-1); - f1.in <== in; - f2 = Fibonacci(n-2); - f2.in <== in; - out <== f1.out + f2.out; - } -} diff --git a/tests/circuits/fibonacci/test/fibo_vanilla.circom b/tests/circuits/fibonacci/test/fibo_vanilla.circom deleted file mode 100644 index 0582645..0000000 --- a/tests/circuits/fibonacci/test/fibo_vanilla.circom +++ /dev/null @@ -1,6 +0,0 @@ -// auto-generated by circomkit -pragma circom 2.0.0; - -include "../vanilla.circom"; - -component main = Fibonacci(7); diff --git a/tests/circuits/fibonacci/vanilla.circom b/tests/circuits/fibonacci/vanilla.circom deleted file mode 100644 index 2eacba3..0000000 --- a/tests/circuits/fibonacci/vanilla.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.0.0; - -// Fibonacci with custom starting numbers -template Fibonacci(n) { - assert(n >= 2); - signal input in[2]; - signal output out; - - signal fib[n+1]; - fib[0] <== in[0]; - fib[1] <== in[1]; - for (var i = 2; i <= n; i++) { - fib[i] <== fib[i-2] + fib[i-1]; - } - - out <== fib[n]; -} diff --git a/tests/circuits/main/multiplier_3.circom b/tests/circuits/main/multiplier_3.circom index 87c6dc4..0054997 100644 --- a/tests/circuits/main/multiplier_3.circom +++ b/tests/circuits/main/multiplier_3.circom @@ -1,6 +1,5 @@ // auto-generated by circomkit pragma circom 2.1.0; - include "../multiplier.circom"; component main = Multiplier(3); diff --git a/tests/circuits/main/someArrays_2_3.circom b/tests/circuits/main/someArrays_2_3.circom deleted file mode 100644 index ac61a22..0000000 --- a/tests/circuits/main/someArrays_2_3.circom +++ /dev/null @@ -1,6 +0,0 @@ -// auto-generated by circomkit -pragma circom 2.1.4; - -include "../someArrays.circom"; - -component main {public[in1D, in2D]} = SomeArrays(2, 3); diff --git a/tests/circuits/main/uses_custom_templates.circom b/tests/circuits/main/uses_custom_templates.circom deleted file mode 100644 index b4f090b..0000000 --- a/tests/circuits/main/uses_custom_templates.circom +++ /dev/null @@ -1,7 +0,0 @@ -// auto-generated by circomkit -pragma circom 2.1.0; -pragma custom_templates; - -include "../custom_templates.circom"; - -component main = MyTest(); diff --git a/tests/circuits/multiout.circom b/tests/circuits/multiout.circom deleted file mode 100644 index 8911b5c..0000000 --- a/tests/circuits/multiout.circom +++ /dev/null @@ -1,24 +0,0 @@ -pragma circom 2.0.0; - -template Multiout(N) { - signal input a[N]; - signal input b[N]; - var newSize = N + N - 1; - signal output cOut[N]; - signal output aOut[newSize]; - signal output bOut[newSize]; - - var a1[newSize]; - var b1[newSize]; - var c1[N]; - for(var i = 0; i> = { - /** Signals, you are most likely to prepare an `input` and `output` here. */ - signals: S; - /** Name for the input path to an existing input JSON file under `inputs` folder. */ - inputName: string; - /** Circuit information. */ - circuit: { - /** Circuit name. */ - name: string; - /** Circuit configuration. */ - config: CircuitConfig; - /** Circuit size, i.e. constraint count. */ - size?: number; // TODO: we should support bigint for this - /** - * If `exact`, the circuit size MUST exactly match the computed size. - * Otherwise, the circuit can be a bit larger (i.e. over-constrained). - */ - exact?: boolean; - }; -}; - -/** - * Prepares inputs & expected outputs for the - * [Multiplier](../../circuits/multiplier.circom) circuit. - * - * @param N number of integers to multiply. - * @param order order of the finite field, defaults to order for `bn128` prime option. - * This is important when you have many numbers, as the product will respect the modular arithmetic. - */ -export function prepareMultiplier(N: number, order: bigint = primes['bn128']) { - const name = `multiplier_${N}`; - const config: CircuitConfig = { - file: 'multiplier', - template: 'Multiplier', - params: [N], - }; - - // N-1 quadratic constraints for multiplications - // N quadratic constraints for inverting the numbers - // N linear constraints to check each number is non-zero - // TOTAL: 3*N - 1 - const size = 3 * N - 1; - - const numbers: bigint[] = Array.from({length: N}, () => BigInt(2) + BigInt('0x' + randomBytes(8).toString('hex'))); - const product: bigint = numbers.reduce((prev, acc) => acc * prev) % order; - const malicious: bigint[] = Array.from({length: N}, () => BigInt(1)); - malicious[0] = product; - - const signals = { - /** Just an array of random numbers. */ - input: {in: numbers}, - /** Product of the numbers in `input`, in modular arithmetic w.r.t prime. */ - output: {out: product}, - /** A malicious input, all 1s but one element that is the product. - * Instead of `n = a * b * c` it proves `n = n * 1 * 1`. */ - badInput: {in: malicious}, - }; - - return { - signals, - circuit: {name, config, size, exact: true}, - inputName: 'input.test', - } as PreparedTestCircuit; -} diff --git a/tests/common/index.ts b/tests/common/index.ts deleted file mode 100644 index 5460f12..0000000 --- a/tests/common/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './circuits'; - -/** Path to a PTAU file for circuits (with 2^8 constraints max). */ -export const PTAU_PATH = './ptau/powersOfTau28_hez_final_08.ptau'; diff --git a/tests/configs.test.ts b/tests/configs.test.ts deleted file mode 100644 index a08ed2c..0000000 --- a/tests/configs.test.ts +++ /dev/null @@ -1,161 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -import {Circomkit} from '../src'; -import {existsSync, rmSync} from 'fs'; - -describe('overriding configurations', () => { - it('should override default configs', () => { - const circomkit = new Circomkit({prime: 'goldilocks'}); - expect(circomkit.config.prime).toEqual('goldilocks'); - }); - - it('should NOT allow an invalid prime', () => { - // @ts-expect-error - expect(() => new Circomkit({prime: 'fhdskfhjdk'})).toThrow('Invalid prime in configuration.'); - }); - - it('should NOT allow an invalid protocol', () => { - // @ts-expect-error - expect(() => new Circomkit({protocol: 'fhdskfhjdk'})).toThrow('Invalid protocol in configuration.'); - }); -}); - -describe('circomkit with custom circuits dir', () => { - let circomkit: Circomkit; - const dirCircuits = './tests/circuits/fibonacci'; - const testcase = {file: 'vanilla', circuit: 'fibo_vanilla', input: 'vanilla'}; - - beforeAll(() => { - circomkit = new Circomkit({ - protocol: 'groth16', - verbose: false, - logLevel: 'silent', - circuits: './tests/circuits.json', - dirPtau: './tests/ptau', - dirInputs: './tests/inputs', - dirBuild: './tests/build', - dirCircuits, - }); - }); - - it('should instantiate under the custom circuits directory', async () => { - await circomkit.compile(testcase.circuit, { - file: testcase.file, - template: 'Fibonacci', - params: [7], - }); - - await circomkit.info(testcase.circuit); - expect(existsSync(dirCircuits + '/test/' + testcase.circuit + '.circom')).toBe(true); - }); -}); - -describe('configuring the C witness generator', () => { - const CONFIG = { - verbose: false, - logLevel: 'silent', - dirPtau: './tests/ptau', - dirInputs: './tests/inputs', - dirBuild: './tests/build', - dirCircuits: './tests/circuits', - circuits: './tests/circuits.json', - } as const; - const CIRCUIT_NAME = 'multiplier_3'; - - it('should not generate the C witness calculators by default', async () => { - const circomkit = new Circomkit({...CONFIG}); - expect(circomkit.config.cWitness).toBe(false); - - const outPath = await circomkit.compile(CIRCUIT_NAME); - expect(existsSync(`${outPath}/${CIRCUIT_NAME}_cpp`)).toBe(false); - }); - - it('should generate the C witness calculators if specified', async () => { - const circomKitCWitness = new Circomkit({...CONFIG, cWitness: true}); - const outPath = await circomKitCWitness.compile(CIRCUIT_NAME); - expect(existsSync(`${outPath}/${CIRCUIT_NAME}_cpp`)).toBe(true); - - rmSync(`${outPath}/${CIRCUIT_NAME}_cpp`, {recursive: true}); - }); -}); - -describe('compiling circuits with custom_templates', () => { - const CONFIG = { - verbose: false, - logLevel: 'silent', - dirPtau: './tests/ptau', - dirInputs: './tests/inputs', - dirBuild: './tests/build', - dirCircuits: './tests/circuits', - circuits: './tests/circuits.json', - } as const; - const CIRCUIT_NAME = 'uses_custom_templates'; - - it('should compile correctly', async () => { - const circomkit = new Circomkit({...CONFIG}); - - const outPath = await circomkit.compile(CIRCUIT_NAME); - expect(existsSync(`${outPath}/${CIRCUIT_NAME}_js`)).toBe(true); - rmSync(`${outPath}/${CIRCUIT_NAME}_js`, {recursive: true}); - }); -}); - -describe('compiling under different directories', () => { - // Fibonacci circuits have only addition constraints so - // optimization levels >= 2 result in zero constraints and an invalid r1cs - const optimizationLevels = [0, 1]; - - const cases = [ - { - file: 'fibonacci/vanilla', - circuit: 'fibo_vanilla', - input: 'vanilla', - }, - { - file: 'fibonacci/recursive', - circuit: 'fibo_recursive', - input: 'recursive', - }, - ] as const; - - optimizationLevels.map(optimization => - cases.map(testcase => - describe(`circomkit with explicit config (--O${optimization}) & input (${testcase.circuit})`, () => { - let circomkit: Circomkit; - - beforeAll(() => { - circomkit = new Circomkit({ - protocol: 'groth16', - optimization, - verbose: false, - logLevel: 'silent', - circuits: './tests/circuits.json', - dirPtau: './tests/ptau', - dirCircuits: './tests/circuits', - dirInputs: './tests/inputs', - dirBuild: `./tests/build/o${optimization}`, - }); - }); - - it('should compile with custom config', async () => { - await circomkit.compile(testcase.circuit, { - file: testcase.file, - template: 'Fibonacci', - params: [7], - }); - - await circomkit.info(testcase.circuit); - }); - - it('should prove with custom input data', async () => { - const path = await circomkit.prove(testcase.circuit, testcase.input, {in: [1, 1]}); - expect(existsSync(path)).toBe(true); - }); - - it('should verify the proof', async () => { - const isVerified = await circomkit.verify(testcase.circuit, testcase.input); - expect(isVerified).toBe(true); - }); - }) - ) - ); -}); diff --git a/tests/data/multiplier_30/groth16_pkey.zkey b/tests/data/multiplier_30/groth16_pkey.zkey new file mode 100644 index 0000000000000000000000000000000000000000..11d1ea591ae20bb75ddc686ecf91858d42f2f98e GIT binary patch literal 25165 zcmeI4RZtyKqor|ocXxMpcXxMp2pZfiI0T2_9$bS44-(wn-CZWhzJ=+BgV{k(t?L&O(5 z;%t>*6PTv26&TnguGB)E$GqvHV8#T{{Q0|!q}xr=1gBOnsRLH3|5L;Fzcv5iVIm;Y zv=)v5_t{oR3NgG)9G=PIY$C7mO&I7Qeg!#(Ac#hoTc?v{=J-yngDJAZ=LzCBTF&l| zoM_Igu%s*j@m1(id=iWx+a`}EEkp5FL8xbc>Uwhq1ILX1MDQgY7R@)E5`pHIvD`*< z2nm}jHRmA+a^}yro1uNWVQ1e_!8Rx@fn*A-X5f^-8q#~Hy{tSeOWp#(Zv6;cA#~iY zX|x0^hRyJ%SaEZY5v-|!hPrGp7x&17T)INxff?gRs5uhQj!S|a;>M7SIM2ghT*#i- z9tKec3YRuj^UI<>p|eRnlzGFGVU>Q0n0^szYJD8hC5_S6roS2ZRROx+OG81_0rI;s z_=^j$k2E{>@ya?*V45UF%QLT1YK<_LCbp2VT&b^XL(R_x5G|cmQKK-%Je3!vLugx{ zBc9-kH?+G$+lcI^Y-7*NoZGZ1|F<_^Tv8L9oOcM3oa$r0SE@4&tU(Q3XtQ=cUlx)_ z%@ubfcGgbzNA)1H*QC9?LU@(}h3XVC#06{n;=LhUBE+>}^Hr*ZKsom~m+38vR@8&I zpT=iohO|hN14tu5nGy2pFaAy;Bj}u-!#l&0sTeV6&~c7RX`B&l6(nAt2lqD!)Oqj8 zp%C*0!$iyFQDNWdcG$mCSr#?jq0vY{2gp-Yqq#9(*TgY+>tGkqS7PO9a{YF44x*&m ze5_kyX4(N?)ATIPR2s&OUAg#mN>45;D$pM;rbgH35}xkQma*_SBz^A5U*o0q$@q)M zh&?{&pK~eT&jgHCiy}I7SBt}Q1cq%cs%5{3^|TT@yTiV>Y(h3-&&*Qu+1r3 zdrz>w8wko~-@W&w8>gZT&6Ql+L!{(FWR8VI=otGPQu%QJ>qZT*i2e+~IsRV*uzYk9 z*Mt=isi~?l^ixx-*k|VF`{})UA?QMMw~c#zG(1!w`M=||27fG^4qasgV{ z4{`y%s6NOAXyHD{1^A-=AQzy8{~#COi{^t|fEM9{T!1gy4{`xo#1C=-zUV&41!$2z z$OZVK{~#BjMgAZc;EUmdT!0qkgIs_w#t(76 z7vPKKgIs_Xx!X=zAtSlUTCg6sFp}hRHbr5x;MM3sZv|nQ?rE2c z`5Fx|WU7rH7TpR1XwW2SY3IDEScNN1)loHM!hRbPRT(i?i*68M+EzXbjz@GpV?W&-v4hWB7zQjS?@v}O;@rSf1qH$>!dKSXO)a20T`l18n zg}sQYBWQh(b3nVF2oj@w!!QxBz}4XxGT!5&#`yy};ow+8p7U?IE`ZyUDmMemed#QV z%hz=S?8T2{cq+FvF+*FD^Jq1tP8cB;?bTPeaw%aWON5PSepJ@HUvs()>%=0*$Eu&_ z>ReZHQK|VTGE(r%6GgQgk$KUl4A(LT2~Ljs`T9vsCH!(7h(RBq=m#PbrDB&SUCvXV z5sdb6o|OKPWQq4?f+fk#2@49ZG)hK`lp!fiCr%@rgONnbIkyDmP+7;*^jV!e;B|}1 zwi#zeV>Ec}v2?}TWxlVw1l}3d&~DoSnw&W*^i9`oYKjQGRfI_@J=Qlgns&pM8PjH) zkh$w8FKiy%%Yq)zrN@s|L3sF3QAJ*oI7_awEQi zhIEV`@RR2xMjmibG6FsLJ8x09gqspcKe>p8;~%4c9+p4|3SrjET`}|D3s6t9nL|Z) z+j2-f^`YWB(0|ITL#|SGyp+M6>7q1kR^1Oi=rPLY7L1Q78fQaVH%&88G1N$d_n%YX zUgA~iOJrBtH!}1{qQtH~V#tPr4v5#MuxV10ObBbR&CL}@UcrBf5idZIt%NGK$tpm+h8{vUs2EPTCNGBP%a+os$yvpoXG*k4mzE4oY|v! zN)UP?O^r9;qO1ATsQDa=yj9WH%|^ly-BHm9KRk2+TgASDBH*WhSpTKvN<6o!;r zcj}pFv6Gnj4VWn|dRZ-fs_slSCJ<@I-g>ZHM>@Uwc;;wY^W){raC z)jI_k7JRl`XWV%J#a%LvUstQ1R-Nka>NMuX6a~YP1t)2hZnuiJCuJt=qa87*0dE2% z6&*%JaUUyDVmTKq;9B$=8>9MOK6o#QgGoL#oOM>zTpQBFvsLZK*-E^8s5P6uS9bv@ zL!B0ytk(b4R6r!}AyZdBYIKla82Nhv*o4$CBC%m|$?bEMJj1yO z^)pn%1=_ErHQ-yz{4L!J%2Be@Prn*F@bST*G~Q2*S3|L$8^iEy#rsV@v(@-N(NhUc zR2Zk;=c|%JFF<&dt4vM@upqL2a(gceL=yNMO;fga^LinR!m+nh;K$ehg7VIScC@C_ z!#{&JqB-dBjIKC{{xun`P%q9v$V0P-X*AeJFJzs;CGXN}q#^kroVLz(QdjyeA4eYh zM##B=8u5k0q@6Llv`A~p`OZgk0Fn@Qq9a8E;Vq^-at_Of<@aF2gCqvb#GvwaHo711 z16G38U}weoKEJbh|L5%PPe&4aK7L0tllxLb8GMVIYGU-k# zsHa5-r^`*go}Pf}anzCwv5i0iI-Zz0yy>10~H_s*99(pBi1U+@n&MckWew>u+6PR@lShQ)y!+Xg{pYa*l_9PxN%-)iDd6Ejb!C4%H&s-?{+zu17G8K^WhwU;zzs zrCT)ZOz3(~s9}=>Ta4oJ?<4W`}MA6D9 zoa}X_kasNd&&6R4ee+2`{96}D5oOj4@1-_9&S7ePDv5vBF4yeRwYu!xqu=Q2 zX9EZNTNm)N3zk#)=E<%QrPC z`FT2pSbysRUnrf8pzNcZ)6l__fV#%?kE*CWtTJI(o8(9Q&gKX9|^606UXxU2JdUDrQ@5!Rc~vH zBw{3|HG%%OE)W=GF!Yo8@-HqEB_qn067O$afcCwN34RTc z)Oh&hhucKgi%e&{$=z}jPwthk;=9%W?ccgU64<5}9<6&>F!{`wGgfhM;u|_ADam2` zShcX}yob<4WI5^;DNo?<8AQ&)&+Es7c)8W zAFB2#Hl{96~uE9`GRmK(r13{kLP-VA)dNA=Dc#$?SB+ON3y719d#w=UoV zZu^sMvMjDkcjW|BZlGqHilUb9%rxAbaW#_qi!Q|9x&n(}1ke+)Xet`WHOb$)00#rY5J!46T3cd)(CX?;r==U4GvR$EeloAYqC-a~;Bn-? z@h^dY3H(doUjqLU`2Q{e!24YPdEov3o%8>BhR-uta;4gqMFvITo#=eg_6!!7K@ z>{(?B_|1rMnL6M4CAhJ$aDcz~@NOcBYa&0Zi5hC%lykYF%b!rXL2<>CkI#ZsCwr#) ztJ;EnhY_o1$`k`*5D9+l9A`gIhMIsBYe26(;gl~yXfPq|TbL`DVVmkcD3#R5yq=yN zBf$I3)dBXsW~z;6iVe9nZ7;Jr}uN>5_lfd2=Wst_O#D(NY zD+}Gqd$1-gGJA@_HN;P2M5Cd9x_^R1_h2t^=PWF!DVT>{ZeY(wB4T230rL$`v2l@1xcq z$TM2WhzfJv3xaLY)?`)Mh1m#+?2(=mfJm5+hF^RSA8aIRR`+pQzr(T7XKEjCdyt#r zxk8LFI1;S)*7Zg=2)SjUWDj?6o5O4Tks&tk<2{kxE-73)$HC-t96< zSB+hUH!mo4%Mn&YhwX_XCk+`S486Gd1bCNJ9ghzCW(-a3R68i0H_opjnxA6Ayi8Uf z&Icpvx>;_DHtoX_nY#>J=pLaPPC-?#t@iqy>TQ>bq3@7|O|wJ&{oP^boy-)_ehrWt z-6>}cA}PsLyQ|C1BUf6c) z-4g7iyz}5KpOM1<%s|xO?oa;CJnmQ&>rNfhTV?WqTs5%1sw*X-Zg~m(CG#uG*({a! z#q-)O+cK*$;+7_vj6U zR%b7zv+ZqmMG~-C=LC#ke(D`X6Qd)6fy;GE6hgC)oiiKUiT{=!%(4ioGWk?(WfoyE z0a`Gtv6CO^zEYFWVNpH9@GH<0<8L(x-Wq}`e6Jj~-vx12;Ka+|@3w={wr=CNCYEfY zM>5J^cQY=G8fK_TWzM-SaH>mD_I7>|8FdOfu~XCYO@(E((+t^I9`yj_ zP60XCp#CL19exj=k2K9=0mowKSqlxk2vZVGfj|MLR^Xmi(RK?o1FIgBj z^yg45>upGaB`XkF@r{~Ke$f-<@MT!90$Os-KHOkW9_(d|S|8D@iOx&Z@}L{A@)LuigfZ@ax@tIZ<+9 ze0m+75PlHvY|0wfZ$ey%C`1~ZEJkkoL&DskOf-p2IZ%y(^i{wZ1WD*46aT_RI{rrE zw5#S&4QrNv@@v(qvZRUUv2K@M(#G%#8)L~tR4wYMaKfZhW#1)FuMyEOr($lwSOjv0l&}UidthcMLt1fWu8m%}d zWq^YfzQE@)zEP>kv{1YK_N6l%^y#`A0ahQ8-)*wn6edHUS&~R479xlarFUwM@F}OY z!_~U%ziKIeHI$SmuwEn~<{}h6!iAJ(NNzwAE0LedU*DUA3?*r`aDDo1gI77eYm4nU zrblgm2vnx2P}^F$HHA zbC==1(dj3Nqj)Tutj*3Xj))T8lWX7twF96(T}!Ok=b;Y_ADrrwaLLltHdmp3YSeyX znNT1Jx++C77jQ12apJFx*uhqe`s6lBiLa#>vt{sJn9_R>`bmJe+|t~d&$1{%=STXF z{lQ&Wn9ZI6s%MtGhX!?Y;rBqOh+NDtB6P*h4n{Su-}*o@3lTZ!XZy=BvalKO)18gb zDO?Glu1-RRu2-CR8kiSxUd!{-o+&|0M1sc}lDl3gU(TP4_WJ^E+ZL6kdZ6+vUh3@1 z4Bid!lVJ@#Z*)Szn-Y8kjEI6XQ&_!TgH;$(A=oP;?`pyKTX=D_Yvb>UTzGFunEE;J z6=LO|5oaV|6rNf%J16b;lV2Y>@B;kF%iNt5BWJyVsgK;rKfU0^lyu5wU_dPWd5&mU zGIV3e@M|aZ?NjEtoE*_)h$BvH1eZUK@Q~en&+uW}rU|!i)gq$4zl@&DdB-09Z zowK&Yl=&QNZN(yR&f@!V#$S>yAurMenGZi9vU+F6t~l?wiY6XqrKyzOK-z4LnAI;GQ2X_Yd4AuZ4us{@iI6#Bi>^)a}d9To;>}kU-d!%Zi71a zZobB66M9)y2EsB?R?xS@ywuc0RHKjV+QT)5@Wn-yHcSX^J0GY&p1!cHtrHyu&JpPZ z@nE#ND+Oz1U%DqX&I&WL>gF4j0i#&DJU?o=N98W<(^KP?!Uda8qtg_=6B0Q+r})^x zIoyfs%;Fk_8AXbU3D`^Vc(RW*lo-75bzRo%YJ zN@L>r^>+z#RZuwFBsetDyxcLI-6+T%jalRdL^Dil@|a4`S3kVSlF_FDPFl|nPcu~? z5KI+jcc?9CkPy5w@7=&L>G?cIHwlU771F5*>eBKyJOPlfUZpMP_VfHy(HXex!uWRL zYP%j48Bms#x}?cRkVlcQJ3hw1GQk$K!N@hvhEfx&09XHJTquXERhVe@$I_iS)0Cc4 zWT2nkBDVnvLC%{gt=ZuaqL{9EPB|?*#~5$DG`COYB|%&kvfqluuA~Fby)>C~yXj5> zm8s-yH;5|2`5$iB>t6diL*I}xVC!L^R^NfYxRX`yOjZ-CKvrhV$YPKoMi^|ct)6xz zF_XDelx5WkfTBmhUGn;PdWF`8JEAZ9ohONdh4H^eANTUTs$z3lY+|woSmQ3nMO@Wy z`{7VzfZpX*Ie%LIaTtfx&&I*z$%~bNWnnA$J&_u{@5hi+4i?me@C-DImyZm{b6fo zFpHZP_))Qfam(2es3T0cbDzFr_OPD|+dMDtNxl>kqlhYa=Dy=GuPMe}f$ktPx+s|> zg-4GGAUwJkaf{nl`_kXWd9G%(P#iwl7t|0srNXMMC(S8V9kRzAl7@rF8%-HCzAT3w z8e3Zt%)2sz-8u7vDaYgzg|X~ZM|{`Ujd`1QtRrL1bJ9C*D?cSx;W7ih+4!e8Yn;hDQe@7{W=aW342~`Q}`a>`HmD#3$x#B|?jD+VraxP8Aeb zRBDsQ{9A@0LR=`3DT){rN6^WaPw&i#(eE+UbES=>+3cYn-AFU8KC{6Tj$$h!k$aR4taOuSrIPojRqPt<(NDr!zue?n2kD<}?4uKL~M zZ^yoxo`32N^I7>T0hIkn+ffndw-zY}9F7c*1l8pp|1lYkIu(Qlb#EjMi3v6K@4y8; z$KfL)nfjv#5-iNz^K}YWVE8J81UWll}FCa1^eU{ zKLnLfp7wE~sfPL)d!OpSu!hBYhk&MlrybRCjXZ*lDUj{lE_SZQ32mv-o0bsVpdR$b zw4}>t=2q}!1rE(dC_t!8ez=M9Z(mD47#>qoqPc=ePl=5DLS^=$2q_*v|90i`c_(9K zhqvAcjv6y~02h^0aT_+d>yn-%Ap4bMSFxE#S^*j3aWfptsmPIRpH3E4da9Vx_*iYO zz!G)iUK5PIOeQWCcL~!;F370Jn<60bB_aopH7CxD%pjB)JHLa+h?#n^3;#h=VOW=k z4N@T=5{#8R!u1A4GpNBsShscUF6znupn0o5*vCGcmd1tQ?DeZla;eauQPjEDq-N}0^#5s(Wk0usLB+(wj|J2FXvT5k>J;_11qxbch1tGLNu)+!@~Na zbSj2DA+08J{sEY|Y{vOb^BC3D?dNXJO{lB(I2OM&u1|~!597(h4#jEOs;$@2Qzq+x zW9}#S!hpzGfCDm&rjV&8YBVPmf(!Ayn-h%zC$U#IHk)SXW*!B$6v#p?nI`Ofj zdAfnE^dj3fuE$fjr29EjN-5opq`rVKNa{&H7zfs*0j*D|utDSL;KvZSw&X2eB7mLX zVZdY*3>V}7(3Kg!#pAHT=7_yRhBr?mbTQh(*(O_&nHi*Av4<0>J8sCSSvbW&z6aI3 z7F{CF4d`0StopCl&j07#82|f3{}T9@z`q3kCGanSe+m3c;9mm&68M+EzXbjz@c%Rc zz#bd{fQ=Xa4AsM2X3qC)A=Q8anJmb9u{=8mUw7|IY`E*H!0zt>AUi%o9EV4ajIpE1 zgLp~d+zZ)1!kc)?GE*{#cdmc8!A-?z;8%=25NT=V)Harf0ZTgbE2#oMKwMpv@;-$m zkpZo5YI>JytON>9E@vf-W zJjcFN2HuNmcL*F2hfz;S;A7NBK&H?Z3ooDdb%+_M;5D;o1y*O!-EQxyQ{rxz|BB5Zf#Q2zr>1-$d6JWP;`4X~_-`-9cv&Pp8%Fl=QyAvNj;_6Rs&EFuW`6*uWTxRJyZLw+_PCP{!roub=T95Ks|i zEzAi^hjw$dwIc{T!=%tyl{EubAEe$?fpB&a-j% zPsgUFDXz(kYE}~;ORn&$Xr0*KVrodG{6k=0&)(7@|TXh`Qo-|n;sy#gPF z7@3(#WHU_v#BkywW-%rWAEWkkk0N`xJo<#Nn{Wg{qA3>#`XQnwaC1KF1rX z9vX%fTb-R%A{OMVe(2|@LUiCpEPT;U5hjhNu>CbYB9bK1 zJ5?v2>Peh*Wy>b@(Kby6f@o~x;UreS9BIvaN*Vl3ycb5G@Pd z&bSX3*{+zPaL9&!b8-b)t=KicqUT^n^S$Cx#8P({p2rll;H?UErpkzhilQmn8SGla zM|wGlve^?Zj#_bq%AT7l?piKOA35_>E{J1`O{x4labK-LZ}0U}tb8d9@R&R&@HY@; z4*Ut^ge!OIkK?@+u*aMpaJIHSlfE-UR$VepD>xBjdk@}_MIQFw%c2nE zl5=-7p*xxHDyS9LS%8+yfrIS6RMZ@(wr+XKD>EdJh7Hr5xp zneCV!hRibr?OcYNN;TwMpkS~cjEDWawkPgvdp5x)ocDKVaO$HK`fmQS#;m5=9O}&g zP3?Au9$u(4m*@V6O84I6>URQzuMuomp93ruXb{gW{LPIR#DKr~Rj_4UxlCgX$MukP zD_BxdM<@gkh5*sjt(s_q8xq{a47!HWy^2f*$QjRMIbX$tqG4T5uy|9^;VqaV zhBIl+{$vWAs37-xO)Or))k%^7^TpOlNz#&Z3UWo|oVD&oS5#lG5uKa7-Zd*NyXa9M zvmozcW99@in!?+k+19ZiTL)kFWaW;_pv}6`Sk&(!qm7VW zBxBAB*>uWQmZ8pyX^l;I{RPIwqj}ffjWoe-6$0lNwYlE~OwTdsFe>Q8;s;U?o^Pjh zi|U2Cw}mFglUh{Z`~H`j_3yc9V1uG$=daB$S| zo;;WX^8k8Lqmg`oJ3Ie0tn}}RuYPHdYKBj9(&0nzt(6fVa&=^;Y6#b~0}jT#zS#}L zUUF(&CX8cDvE$L87=q6EGjL?O)EyD#SUzDcEn$nlbRkD~C^by&3n#>8m z5Br<{0&c=lAR26UP;~Vo9ZYyzs8btX9)#f~o3+Nj9-V;uhZ)MhVzrc@R}YKoX1d z2s7nGRlPb@MMWi^snKDPzJY;e z0wY(3gt!V2kPfLL!j>(k8qg8FQpCU-ng-VRV;)?%%S{R3`WRP}84cRMEa4wk^3X4@ z|DyJsml?7AOrH>hJ%9}B)Sp{R9!Lzij5+Utx-=U~Wlnhey*~>=6PMsSQAF5Y&2%>b z0w^oP%1Z~mHZ0tF0fAnHV}f77bEHB9VwP1AKjvjAwlxS1pFF$6tbw_MSes4z7odl| zgp3C;ZN7YEq1!z%1mqW$UAKim4kirS?x7s24fx2X5f#trDK#kh^A0Xf@P))#!b8Kf zKi}rx6K(bdV9eTy#A9X&4L57!g!Mful4fhm;RgxfL^Q45I)M)vO+!}JvXExiIKnSQ z?EdXU6|AA5LNpVZaw@3~eh^YFF@#}dO-JKm5ru+Zl>40`)$f{dkZ z5T$EaSz=O?{ov@q%(E6@Kk_QJ6~9jP{-$gvHpIY5%~Sa?j|Y{kOpgREI-RNf1v2g1 zf&-#jr#red?eEpV-7=%R{Ys?xU$@w!?~U!CV4~48mLvA-g&{7jk7=JQL8)IeU*W28 zgfAIJ^N`OIAal)$q(c#cFv5n@&F91?O+})w5;nU*T#8^laKySYMtFrTugP4q6E#K? zq;od}Su(S$y`0Qp<5fwyZ36W zLZSt7&fYA4Z8DQ<0c(6+*F@e)&**zi%$&l?P>Lh?tbb`f?*YRIqoE9w z8lwo4lF(G2@3>J zglCGGQOe(BzF?2(zZv0;UewlYC)RwYJuo1uUqTERG9><0UpNya5plV)g|*j~kC}Gl!q|^ligoUC!W9em|m=hyk~#Xktw>dd8n}1d}>7f ze35GR;s!}e;5ysnRhaA(AU(MU(CXi}qN_qbZ?DS9>vDL#sXK=u8R|bxbH?1|qCv{6 zI9Qw0G9;RNQte+I2BOpaoPvxH->F2lWQxsFg8H#=8_kU?sz+Zh`gG(;dbNsyB3#AX zPwYL$BW%196|K*w1>ndPUvR>a<4er|u=w6LdO-0>UshNuNi07|qP_jKFpo2uv0 z1~M7#f<^n6-f67DYg|gIR=i&{=s=T3qsc1Eohgev-}Rf@fuqbS>)E-zHqH$f&3o+i z(I|$bKhG0^_eXXG0ZCgpYUHGE5l@V7pbxc|7bGc8Zy=o0_|&Kkx4HlkN}v`(#eu>AvUHPGCy=0Y;%>A;U+7yq1(p%|%wn z#w!j4Yp9YSfK$5j@(P&0b06l>@GG7_xe+;v$@l}#ueF?tq3nYv`G+v~?hfh-isab_vi)iZkj^_43x`Kxm(OmM49KX&(&@q;7s zzJICGQm#JqKx`kbY?`PuICFE!P{3yo)3M3sMPzmK9(E6?Wr*mQP<6Q*P2}#78`fk0 z8orA9pT4wqCT5lpGoZC^pE^`=>&2qkV+Qp0O7d3Ei@S`ct9D+cQ7AVc0sA)oXJgDi z2ciV7?x_0Aj)`vm()ps~IEy!jIiv79a!B$!(P&Kv0%Wq;_GXiwej{lIIEDEaN*TTJ zgu$_pr;y$&XihpSOaw*Z2yl(4k^4QdV+O~31sdQ7P4Mg{bYY1f?@OFM=)`TywlIpb z*4sL-nP{~zO0ccID8`~3gOZM&v%g!^81O{e#CTW=Q+iXy+prKPLAdz}Z*ZzH73b-r0m6EAX?W+hjl0$*e>26# zcY24Ph|bZB?!S%}B^YZgE0<>%D`zEAvL@!#N=Un-LZH9C)Ej}PUmq=9lCw@Uaz3jw zBSi1{=e3%^I>5vC@bsk(DbR19IgXQ##O=h`0* zOsa*i_$uE5f=4}H3?RzMn;oo~ej}R)H%o+=VZ{f9waQSTs#kESR5Zj5Dv`#CgwbNnvhMnj8AxFN}X95&$yrhNVLS z*HGLIvW>>C%_c03>tKY8bo?Fm7)ZGO6Df}l0^}XE$g??oAp)~0r&+Gr8U&8=HP`S) zp|#y9NlIhq*XCKv_*%z9huJI2c{|$#A1ZYKiY9$n%hA=~EPXh~2J9Jjm)O`)L{S@M zC(t3CzytOo{p*r7eMKp`4)txrk5y(Yv^^+9PcX;X$jSY1Up1_zBs@WGr-x&27*$9_ zO)o!@@kQbE_poLuB6%Y;Lt@o%k~?z-8j6eiG~TU)D+$=mz|ZP(`LYPAX&8d4MmrFGR$H7%_E%tm zW;1Dx8F25&Y{7hKq)ALXqaBU1j&lXKee>mL`~lSMB`as*fjjS=OF4aN}n*dU;F z9A}uZ{cgrEBqc!PY_VWih=m+dj6o_~_AVFHBH708Jv>}g5WcMl@=|3#L+xIb`E0aS zdn)eSZj8Z%+aS-_XBb~KpX5ymcxXU{HlY)?RYO=s)W@cIP<6YGMV=T!i!&#bFv>(2 zxFs_%Y<6-ym;!OA&TR}t^98<_{7Bv%dp)jE%;d2p7kx>qxsDck(!cJev#qiUE6&tW zKv4EiZY&73klH+N|^pB-JsWfnx3Y}9yy z44G&&!!-AQSd7c{jq8DCa$rMSi@D{2)PCrf3Eg{h9Ip+V@F&ssw>ieF@i``?&;6Vj5p6pp^ zC?cjv+k|z6=HsgNT#yakXv65BJ7lTutAAt-R2V(%iuL18;Z?hJttrK=``jZHR6-rZ z6wyNZ{@&?N?1#3pgwIdls)ZVg!l@$Y1A*#k_~f^JrjsCZlgfA{ z;E2PjNWD(udaN(3><&LAQa8!nX#)mCds1k=8 zX+z)f08?+NrufCM;hm#2_~?8t{uUcdzNg%XZ%~6EMQnzK@oV5Un8d^9JC^5Jg**>j zkMmYbaRD-pjuM)Sx94SZ-t$@psUffCA zkdiH@JZaPK{sV=>$M0EjnCnq;a^=FU6{+-t6!`<5lj}4R0Vp?`yH<8o8{G}rKx+}f zP}k8}a|fz$1)ga=1;UZSS#U_&%9te!FbT8>FH{{S5vn*Am$dU+PEtmDJQq7^jg0vx zdHLsASbZV9&rt*wCmzHumZ}Dtz!jj_zDE0nqPT^m88C5JYJym9?8P?&{0L(*Yl~%J z1f_R13+IZQMTGu~%^tyYzr{-5%IAl%iPhr1CGSvI;XfD)D{31%^1#M~`O5g~y82dH z1-ir)?fCixoQsf(con0bg)NX%>)Y|MvZf{K3jKt|rKT#*{Wjjt;)he*Grhm41d_!0rnY%+C7;yBTL#r zZHj25Y)=hB$&@@7cmdHG5{jc}{1|(7UBVlo>1c@_(hzT2_8#>V>a<9u{0q7qYm+t= zEvt)wAe5WK5-Nn0R3MIl`=Q_*p7tTxS9)^5UdyY1O)me8qhpIIsXPmay=<3^3GE~T zQ~r7AH;^DL-bD{%4`lh6;yz2mF)wIwX@{;;p!(8T4VyNOqE=o`I=D4sIN{I|0OtR8 z-+J7(xH;IRBf%E0dSUi8%1QbROOmZ!jCP;BLWHVI1IpA4+HJk)5xP#talWSEDHS*b z4{k~?_&#IV;N8}oJajE4=|5X(z`$v_f^rh=yEW4jaeX@*2HOdvypY2vT%-}3vo4NJ zzCnBJj(`wRZcjQOuhR?udD@y++?z0IZ-y@_Y0@_+g@c>Qh|i<#c+ZgbfPjr?MdUQ^ zX2f~AviyF6S1?q95c%cw%lNQt_WTN=`-yI`hNQPTzkBEf7tq(3?CmP zldl``x5!KEGqHOf%^WNLPx?NT4rCpV=JJE_2)7$@X|4crdmxwQ3L&=_a%rvza{C~c z=87S=A987~1ab!;m*z?#cMx)Et_*U+kV|vrkQ;$qn$r|V=8Yl9rMXJT9fn+*tAgAS z$fdbz$Q^}TnyZ1_G03I4TF4!TT$-zc+$iMITs`E*AeZJEAa??CX|54+Cn1;Snjm)y za%rv^a;G7e=2{?k26Abx6>?`Gm*(0acMfuCt{rmcA(!SlAa?RNQxq`$6$9BbL`H{ z0=p^_SOpR(DRQ}75hKTTg-}>3<_{?@sT4(yTr%Wbc4C*6lqzOLRs_b1uTU{7kyVte z82Np#kLjN7H@kpXaFq%R^z?i0d+&SS_xry0`d!l_Ox4SxAPD05&U4b0E5bREUE&pr z;Zwfi+yq1}gDPFQESyu2PT|X!#mg+~<#U2?PCyBVfq2>ELM3cgf>cu?wdG2qST1OV zm6^g~qgbsxI#ro16>37#CUq>V2zUG!1W6D>(I{>qDI$uZBuG*y zB+JNP{t2N_EEW%iL_2|%3<(_x{H3&1GM&nFs0b&M$%K|n;ZF&Piz3*_B82{jk`^vA zIV2%IS7cz)f&QcnOb3L)=Lqd z?_|KVq<&Z_R*DVbBdL0!@mOVXxiMLst4x)Ia~be##o9}bs)=QCQDre-={3T6w#~**D9AdIE#?K%@G!vjLn7eYA39cMwjjkMKf-8q9#xrS^{gIM)zV_!`wSNaK>as5E zlOPyAUdqY3q{|N>iZq4Nl$UgQLjR;gQHTP)@Xh`O16cPCCUI%23jZsOw>2k&qyAvUN*IwxQV~?RgZEnQ;AnC<(v#I9fLEt zR1MDH(l|JSOYz_gF8zZuxL^p*z|eU0P4$OqF>@Jun(7mHLOw+B3Hk74QeCkutk||! zU~o#ei?G~EK8oDPi*(Z;96DGk`G`*3+;mA-9)c5*`%t=vTQnbUsoSAPbgIZLmP0~C z(R_?mVkh#67O@<$BRa|8me?W1m<)j=$dJgZ!OA9rmDTboo<vwq1(MXZ5NY{jFhp7~L|u7}heJds$pdkSG06i-Dj(QnTVT8L>0n^Hf`QHEGd%Pn zIw=*1UW_RfNK*OcNb=2*ZflNgz9ZNi*F;xReD&Mq8zG>5Z({}Jp+vzhc>uhwN>0(S34*p!L zCHYoM^R3pww_2yqYOELD;%h%DANnL8`ZOQ<4nFjqKIj>U+kGG=`5>nGuHV52vC{`4 zgJYKujx-;R4n7>6J~)_S!#>42_=N)kbeikM_c1w6PwtSvIT;lqjNe z^@y_GIjB@S&|_Q`*YVlx`g#oHlRRY2p=pq?dX%rCIcg0m)lS9s_Q1fQjXfedSA{5h z@B|5?$G9rAlQYgW;5w$z+o}-dt6&bZ167FMmJ02m#z3JB)G@xCaW2&D@Km`ftb^zF zwsOY#a+)LjAUxa2*&Z|uC)$9fa)oJEV}gt4I>-#S6((_8!n9W(LlwUI?Q~3Xg;__( zgRUAeV8AlN18N*=R`@4sN%d>is+NH0Wf}xwNef|NpMWJTS_)~dXCVd2SkG!nrWGCm zi&-tnw5}syC95TwR&xX_W3?pH8jgT9td?Y2xe>5{)sj4*o|I@sUZ-)JypM#po_QoZ zjoNaOG%k|D0*aJH>8Ld^3fVGT!d;dX@-0O0#86- zj1VS7EV@o$&33I%rQ%FzMGrF$VI#sggo#6#IAHxLykJBw>=1+;9(8(j4Y#l!xnL+4 za&cBTHnE1k#jB_ExFMWef&j6J=qHgaZioxHIO7tdwPb~qh#yHx6JjoA2)Q_uFJ@em zG%SALrpGTp+eDup(&GzyOzU7seO?mPE5>yxC*uRU3pv%e0l)yt4M|gsHK2tLEdoly zxF$nO0XI;t%Yf;IoQoLO6-(Ht7KVT!JS3rnmcb{=Dq2!kAz%XQ$!i$hYH=%|#~}^a zCPOeOC@d=Gl2{9;e2A-k28%mo%`~S7v2vBAbh{`xQ&C_n11tsp5=Tpo< zdI;%JC>nuEG1H<NREhOUx77H1ff=mJ@4b^S3GeccFv)TuO zV60)zfJWM_{%VIPUuHw@R8C@Z6`F_Wl9`si3PD){Yptk+hziCkGRikssGC&9O|@2V zn^de0Hp^Pew@qroO-)d}7_U+ zy@`in;}LDe1Jg36vVW3&V zwed)_;$f~pn||xT!>6$a51+;!JbW5^@bGEu!NaGq2M?dd9z3=X9vJC47WUw=y@^M{ z#zSkx!`+TOc=$B-;NjEQgNILJ4<0^^J$U#u_Tb^u*n`J*!oysVW3@M-M9V;A9p@ounx3^(!Uvhm2a;(;l$ zQ`+MnK8-zi_%!z5;nUcIhfiY<9zKmdc=$B-;4w^im{iUy>(p3FY`y#&c?1}SU$*=h!9uQRKFw3wT!;w710qH9DJF6t-Q0i* zB9S(Kpq)o-`&i%fu(x+Tf&3<7MN?>0)M9Dw{D~bZgIE3EiHPrw!pYfW({=R6fIF*Jp|^UqT5piXap*68P{g`p54Ru>^{C{5Ai)a&-d(ZzK{0ueRPoTqdC5hZuR*n^EOP^TD+}? z?`?g2ZyVx!Tb}Q2y?nnJAe0e#1P#TpXiL+-_5Sd=D7ndqAG=0fT&7=J>YU z>a!)Y3MRrWRvF@3CC|4?j*stFAHEDJbD7AERGyF2R-evHdQ8Pl=@~~XEWFv=44{pL zz@3AuIdRaQdxx<~VeSlU122Qb=6L=v(D}!j(Ge-1MLu5*Q9!aok0w>jyt z%=|MOafA*xA|1Dih{jez0>z872Wb$g9U`~0tM3>gp|>jFkjw+ILDJ~v!b1?rS_d#! zP=YeJJPV8E_H)5J&Fjv;u4i@Sds?7(xW(DC-_6Y-nae^!q;?Q*#OY`~C5W${=0lv} zyJ~k^SH;vnyAfC2Ysn3@qgJ(C=Hgn?Ts8_+&sC#d%ZuMEyAAiP#MUY3&3@zcj#& zLkn0WMv;YFh@FEK4SkW+KBA1Laf+2B6>?$5A16_df`3?-cMHNH0W4%XKP&4vjJseR z#^qHGPQKdJ0UYIoENe+k#|Pc}0nu6#=UcPt7bH=_VP@l6632>VZL==r6efm3M}J`e zU7-`f&>zR0wO;73CO!%4(EUO#gmR2PdRz4Cf=RzF1k-hstOrvyld1(%qb4;POjS%O z4kQQ3C7Dzym})82qLXqYDYCQ2|4kHSz@&xAF|`nEHjtByYdBC$xB<F)EsyYZ z3a_QKJmH8$xRVx5!poAzwUpLth^8YUVp9+zie+f35PXg6DX>O=ae-OFGz#QFI+1#D zV3{n$+)0Kol$->6RD;5hB?}=abuFc38BYWT=|FP|D)hjBbjP7#9Mxrt;T0MP8`r|5 z3dF|;6HpyP2KHtS_LdI{u@{W6H1>iK7NQr7nECVrvaUWzfI(GVfEQuS&e&dp^D`~b z63D}mY`wHZF`^5Ui*7Q*do!xsEkxjCOF&!zK?@%t@u=|%$JA4(azc2TXgc@hBN&S4 z;>$U)T^`T`tw&YQ;7%1@7f>O+O2l0|oojz-zeI+PE|}8vBMXa+NrHyMQB4BElwU!9 z^iq4>eEnQkyj%xR;xVg)rMe@O#n)G&RS>G2GO6lTFDGp$6Vq5rYcU7PN7awvbv>7L zv8gW$G90WbNp-5l;fyZR#-WFS3=m$%%u<@z{3;Ji`XcN>6PyZ-`Z(C%mSFUl=SNP+sW)K=9@Z6rsf zF06WMJ6yW^GN{PWw2Rn2vl}@-C$Mtiy-vMuRt8Sdn!ZQIK#W`v=i+SHO!v7xF~Ln_ zys45VE+i|GS-rGfE0ekL5IcpZzhiFm)IZ1EGBdaOep;)0J!^H_h?sV7Z!K_Z`gyCh zx(VD3Tg$^L*jkLC%TqUOtybOv)*`hXYthSfZrfU)qIWyBG$-a=sDPZqtQ_HH|IqA8 z-FUH1l8R_iv}C-niM>qSi#IJ1XVL^Ye>M-JUMugGQJZP8bsi>g!0qRZ~Dr1|4;u2+?O#qgb;7%Ni_)`8F*F zRadUtLG}HYzyav-ru+<`KH!GldxVsnpn(DG#9nx&svZ)(1C2@~7S!zCZ%QYKxv&+xImtCDwn~XLWHcVpOf{TlBoyhi( z0rRz6=td!5^Qp)NKdsz}-R*Ru;M{x|1ao$Eq4X8i+wMXa;b2Y=%I`L*oi;UrR)m@L zl*a@Pe{5g}K&Z#G<1I!rG%cgvp$hF`M@F67poY+hrrYEV8fM(?UY7K6M%lK@XdeGm z)eMdEFa*&aq>(!ect|}?w;i_#oYzkc-IOS=c7oZ&b>VsXZY&Lwb@7#ev`?y8Pz>cU z>LCdK(gLP3X>~$S%OUX!eLBP-32f7VKTnUt4-iru;Yl}o1YX3YsSZE3Wo3XE|}i}RTo^fvAWEvFw?q?stk8k zS(Ss-2usk7}@I&}K*RZR34aQ6BPnbk3G0^cQl70V0W$pv#=>v0V;9>#O@h|8I& zO|l2o2AYfW7z^Yh8ADINJR50u?HQS)s4uj}Z6x5#k;{Li|qq(eb|@Kk`?5=lm$3?hQW-evYQ&uh!*9wYGlr ziI)BdagQG%?(rkU@3bGC{QL1Ef3L9pi+wkPx#+KJxX39+}TfuFi(#Tia z#-_&JX=%4$y!Bo5xeL?gnxfN~g{2L?^@ zb0Vp~kdtUA4a&oUp*1iN!?p+w?%3|g&6_gTKQE38#uZvG32F4Y8c`j`#+LE!9%Bf_ zj34dEiEQsdG~OAe%?FWx1lvH};jsT3bo#`_!GLPmno&FU>^9otAQ<)?KsiS@I^76zr0t#Q(;3nfpL2yeNqv!wch$ zA29daEntV2LNF58v;BiNBy9B>KlmP{zAM7I5@ohF>b`?yiJS&K80}`!t{^68${_*i zG#7&#(v59hA*d6Z*TN}dZULtMfGOPz$>DdKZlHX$=;BTm(1N| zlVA#o$z#PBUTBs?dkQV)X#YB1ab=fDdD2lfTp}=+1y-!FsPn8rZi;|D#TH?WIT2*|amXXYx0w{z#2_*7Caur@5BMv@ODsS#bc4ALcue8-lRBb1%9pH!_VcS6+7AVGh;GbdkdFO3G+r~NxBc?5A=+fZQOheT3Z$aG3 z*fkYL@^7R1gQn8kz}C+0LI;_M@vwyqtBEmf$_!xh^oBFs9Y~=RyZ}8DWClnq2-$Ep zpq%fbj?CyH8TBswzJUopho5blTj95k(mx1NnpN)rpzVRTmdHiSM^jTj=0B~OT{$fr z*4Mu$NdFB8;LajJMm%9m=Uo>eSB(}z>)6?9D`uNvIuBTQI9fJaiu&oDLwNEFYV_{} z>kr%Zcmmro-W>}?EZ4jL=x^RW{40yUwfg8^jBfwPvmg7|*N&X}`i^UR->#jU9Y*(! zcj5i*&6`gSjQ!&;?)bxVufKNjXZ!Czy1G(*qjG-F_anddtxIt{0Ing|o8{cUIPzy- z@Bh>1Uii~5ANsq=Ppo}o^1-W*edY^~oV@boZ}*^GUq`NS;dj3J_FJEQ@#|mv+ktQX z#-lrb_(!jQe)iu#@Tr#ye{kiA=iW=;;jp0^*TPswS?>?0DOj%ee*dTMe*V#~|H%Ve ze$@Nf`@eX7{JZ(>f712sUtRpbwvjC4LN4I7POcls^=CJ4zW$R`vj5><+4;sB^Z)v< zJ{A7nTNnS=TgU#*H~vO{I{Iyl!PX+G{_t~~AL@#I?$=-a_(NC!%O|?C^B-0|@#|7w z=ly^FNLVJBadbu1f8)Xby!LdxGV@<=9@*0PzxVyKx8$!3UEg`+nLq!@%#P3g^*NFY zxvqUNz4_B0|4)B-c;a>AFMl_l`0DO|@Vh6(Uy6OMp1;a$i~|K5(Gf$zukK}4BRdMN zWA^K5HEN-|hG%kGUDK`T-P>IR?jmp(fx8IYMc^(1cM-UYz+D9HBJc}TpF$pTp3)QxVmt4maTV;(7>|f$I@m$8bH4>jbV-xF&HugX=k5FW@?hYZ_Mp*F3HZxGK1oaA84e zMBPpS{H-zd&2aE1ZNfQACsY{Gb#7RZSGTdBiPno1y-_GHmZlm7{ls#qQCut)XQt@a zrH>)$>@YZe=ll3R20wS9b{5M#wD4@%3Sy22i`q=Jv>IP;q0f3Oj8EUZ`TZ|fKHc~1 zE1&uPBX9h8&&Mv_mwDkQjfckXJuCOVwkc2c!r%DZ&6~gc+Myqn@Bgj)#(#6yPv1K| z{FQ(5&eP$yv}0$AX9km9WLwHt!fCeE@QdG4-uaK$dcXGnzP07A4(49|%IB8eo_q3- zUi*R+CSRj`KgROg!TDX!P5#=q9=h*`@0DNp%>Q}!zaRbHAH4X@^w`zE2D?{sN@c2C z5dUdnQSkjTx9I;tZYkh*xaExh=eHI0XzeV1%=_$2b#XOhM?PApRl`Y(Qmj9ZXe4e$ ztCd1DW`zq&F*`Wdh}${l8U@u3PtDFI>~MW~I%$W?%cYcEL49c%zX+bzET(4k$grCGr6XjAso90) zdSjwkIbEou4?9Xwnt6{o!P=u#CyGC2-fNFjb;vb6Rhcb4K@wBwxW#+AS}UEPoCut> zbFLuqNtP3#Q+8^l+9*B6QV}{$ff5)^QsGjy_92!4%G30-^iQ5YProStIQlv;_ak(*BoU6e7GhPn#JNMHn z(oRoZI#oj>nb8nAS}c@iPcD~_7b>G8vx#Prj}{8_yZ2{`jY^?jr^4q67b`y3L*3x$ zNU<_Gk1lEU^qCWda<#TP-%aU9Ya`y|BC$FFK2vjr!zi$jnO-iIW+#@I+~PL#!}MiSXx@yr%9{(I;55T8EJKYr?hgQOIkgUN->r- z3H)U6Q^GUDXRD>zP8>g`}C8uvB<9A{CyCN_AjSUx`bFna-4jPTAztP?SpHQX?eR!qU=G zL|UpvDWMjV>z5Ye;))uo!zmkyDBUP$k|nHk$##vk?q(1>g@kTxQ%DdSxJyc9adZUo zDq=Z%uTug@nCLRHiNWe{R4Nb0q@`hCuvZ1v38}m{DJ|_y0rNC4*QD}DhqN@30ZyI3 zzDp{Pc1ug6J-}=eY><`8W4+SSSRe4~hb;!A^1eZ7Y2OgA+zgxOQh9$)TH2onuJ^z; zTcq-VtUP#jiN%|ql03;cN6hn}r&w{Ssx(`_QK@rjoS&_}m!}W*|uCwQ)7&Gta1eilF zDq<-l7Q;9`!W_iPCN;CcJ@R2enVzZ_M4Os$n9Mci$$!LRNSwY0Hmr~h#j-3G6>(t; zB&lqrmQ+K_Te&xEha|Bgi*-eu4Tb8Zsd{4@YmGSDAT6F2#fv*AdU_}OypMhEqEBNt z`SfY9GD!Al6(gJTrRt^o8F3H$91b~Iq{Rsm&B?ZxPa2_`4KSVsuRUVeQ(H07zvvRBN4Iq$Ss#R!c1|rDJz-VWr<@=QN_xm%?QwY%oBT@ zV$3e+drm*$p&j?oPIzc1J+vo1v{SZ)Pe0|rdfJm?(i8iTlj~`GPh$on2T?9o>(9ft z7e5Si7vZokC_=b0z1k?$#b~iotkdINilXzIuH$Jct7Z1YWRZ`c??Xpdl)@Mt*Q&J_ z;nVXKu&fj%u_((^%PVI^L9Q1U&&32~zFeOcmHASAT9Oy5by=#^6{)-!B6?WCM>(Qg z#8f3}ahrmO%`)dr@n+^o)_M9U;$vnZEQn=MEJ;$KEKAd6aGVLri+hJJpbIFANR^N( zBef(83F^kDN>w&^62s=*7QWmgSSez7#?)Fh^CMDg$YG3XXUdC8+`QA^JrpihiRf~i%UWdw2g=WGr1;ODseePB1b0iU&sV-LdL98rV z6g^ytxOQmf$e~oNE}AuGTq&jsogK|Q7K1Je#O^qTX&8@??JDaaQ2m8RKzUW_6x6dY z>)9ekfukd0)Q(6AJ5)ouoVH_#P=bpls7HhjPD;qo=CH%{bSJ%Z)VVARwc;1 zf2@Wp?yYtIm>N0TID4^LoJ~-GD>|B@?=sQ>@~ literal 0 HcmV?d00001 diff --git a/tests/data/multiplier_30/witness.wtns b/tests/data/multiplier_30/witness.wtns new file mode 100644 index 0000000000000000000000000000000000000000..a1917a04fb8a4c3ffbb26c41e5778e3b28f9c31d GIT binary patch literal 1996 zcmXRf$tz}JU|;}YMj+MzVh~UOVj%y+6i^mt*c5gXCixXm?ShvovqheduV z1~x!7Abkz&KmrIr`UwCBeDWZ(@PScze4zu03w$a@!w+BRjD{bj>4OD-@G@`^kQX2z huRuWFfq;Ai0eON27@+_f4FCcmJemRs1Q1180010j6xjd( literal 0 HcmV?d00001 diff --git a/tests/errors.test.ts b/tests/errors.test.ts deleted file mode 100644 index a10d79f..0000000 --- a/tests/errors.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import {Circomkit, WitnessTester} from '../src'; - -describe('errors', () => { - let circuit: WitnessTester<['in', 'inin'], ['out']>; - - beforeAll(async () => { - const circomkit = new Circomkit({ - verbose: false, - logLevel: 'silent', - circuits: './tests/circuits.json', - dirPtau: './tests/ptau', - dirCircuits: './tests/circuits', - dirInputs: './tests/inputs', - dirBuild: './tests/build', - }); - circuit = await circomkit.WitnessTester('error_rt', {file: 'errors', template: 'Errors'}); - }); - - it('should fail for fewer inputs than expected', async () => { - await circuit.expectFail({in: 0, inin: [1]}); - // Not enough values for input signal inin - }); - - it('should fail for more inputs than expected', async () => { - await circuit.expectFail({in: 0, inin: [1, 2, 3]}); - // Too many values for input signal inin - }); - - it('should fail due to false-assert', async () => { - await circuit.expectFail({in: 1, inin: [1, 2]}); - // Error: Assert Failed. - }); - - it('should fail due to missing signal', async () => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - await circuit.expectFail({inin: [1, 2]}); - // Not all inputs have been set. Only 2 out of 3. - }); - - it('should fail due to extra signal', async () => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - await circuit.expectFail({inin: [1, 2, 3], idontexist: 1}); - // Too many values for input signal inin - }); -}); diff --git a/tests/hooks/teardown.js b/tests/hooks/teardown.js deleted file mode 100644 index 320d383..0000000 --- a/tests/hooks/teardown.js +++ /dev/null @@ -1,6 +0,0 @@ -// This is a Jest environment teardown script, runs only once after all tests. -module.exports = async () => { - // SnarkJS may attach curve_bn128 to global, but does not terminate it. - // We have to do it manually (see https://github.com/iden3/snarkjs/issues/152) - if (globalThis.curve_bn128) await globalThis.curve_bn128.terminate(); -}; diff --git a/tests/inputs/arrays_2_3/default.json b/tests/inputs/arrays_2_3/default.json index e9318f5..0470808 100644 --- a/tests/inputs/arrays_2_3/default.json +++ b/tests/inputs/arrays_2_3/default.json @@ -2,8 +2,7 @@ "in": 1, "in1D": [2, 3], "in2D": [ - [4, 5], - [6, 7], - [8, 9] + [4, 5, 6], + [7, 8, 9] ] } diff --git a/tests/inputs/errors/default.json b/tests/inputs/errors/default.json new file mode 100644 index 0000000..f56aabf --- /dev/null +++ b/tests/inputs/errors/default.json @@ -0,0 +1,4 @@ +{ + "in": 0, + "inin": [3, 5] +} diff --git a/tests/proofTester.test.ts b/tests/proofTester.test.ts deleted file mode 100644 index b11c7c2..0000000 --- a/tests/proofTester.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import {Circomkit, ProofTester} from '../src'; -import {PTAU_PATH, prepareMultiplier} from './common'; - -describe('proof tester', () => { - const protocol = 'groth16'; - let circuit: ProofTester<['in'], typeof protocol>; - const { - circuit: {name, config}, - signals: {input}, - } = prepareMultiplier(3); - - beforeAll(async () => { - const circomkit = new Circomkit({ - verbose: false, - logLevel: 'silent', - protocol, - circuits: './tests/circuits.json', - dirPtau: './tests/ptau', - dirCircuits: './tests/circuits', - dirInputs: './tests/inputs', - dirBuild: './tests/build', - }); - circomkit.instantiate(name, config); - await circomkit.setup(name, PTAU_PATH); - circuit = await circomkit.ProofTester(name, protocol); - }); - - it('should verify a proof correctly', async () => { - const {proof, publicSignals} = await circuit.prove(input); - await circuit.expectPass(proof, publicSignals); - expect(await circuit.verify(proof, publicSignals)).toBe(true); - }); - - it('should NOT verify a proof with invalid public signals', async () => { - const {proof} = await circuit.prove(input); - await circuit.expectFail(proof, ['1']); - }); -}); diff --git a/tests/witnessTester.test.ts b/tests/witnessTester.test.ts deleted file mode 100644 index dce8957..0000000 --- a/tests/witnessTester.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -import {Circomkit, WitnessTester} from '../src'; -import {prepareMultiplier} from './common'; - -// TODO: add C tester - -describe('witness tester', () => { - let circomkit: Circomkit; - let circuit: WitnessTester<['in'], ['out']>; - const { - circuit: {name, config, size, exact}, - signals, - } = prepareMultiplier(4); - - beforeAll(async () => { - circomkit = new Circomkit({ - verbose: false, - logLevel: 'silent', - circuits: './tests/circuits.json', - dirPtau: './tests/ptau', - dirCircuits: './tests/circuits', - dirInputs: './tests/inputs', - dirBuild: './tests/build', - optimization: 2, - }); - circuit = await circomkit.WitnessTester(name, {...config, recompile: true}); - }); - - it('should have correct number of constraints', async () => { - await circuit.expectConstraintCount(size!, exact); - - // should also work for non-exact too, where we expect at least some amount - await circuit.expectConstraintCount(size!); - await circuit.expectConstraintCount(size! - 1); - }); - - it('should assert correctly', async () => { - await circuit.expectPass(signals.input, signals.output); - }); - - it('should fail for bad witness', async () => { - await circuit.expectFail(signals.badInput); - }); - - it('should compute correctly', async () => { - const output = await circuit.compute(signals.input, ['out']); - expect(output).toHaveProperty('out'); - expect(output.out).toEqual(BigInt(signals.output.out)); - }); - - it('should compute correctly with multiple output signals', async () => { - const N = 167; - const newSize = N + N - 1; - const a = 2; - const b = 3; - const aOut = Array(newSize) - .fill(0) - .map((_, i) => BigInt(i < N ? a * i : 0)); - const bOut = Array(newSize) - .fill(0) - .map((_, i) => BigInt(i < N ? b * i : 0)); - const cOut = Array(N).fill(BigInt(a * b)); - - const circuit2 = await circomkit.WitnessTester('multiout', { - file: 'multiout', - template: 'Multiout', - params: [N], - }); - - const input = { - a: Array(N).fill(a), - b: Array(N).fill(b), - }; - const output = await circuit2.compute(input, ['aOut', 'bOut', 'cOut']); - - expect(output).toHaveProperty('aOut'); - expect(output).toHaveProperty('bOut'); - expect(output).toHaveProperty('cOut'); - expect(output.aOut).toHaveLength(newSize); - expect(output.bOut).toHaveLength(newSize); - expect(output.cOut).toHaveLength(N); - expect(output.aOut).toEqual(aOut); - expect(output.bOut).toEqual(bOut); - expect(output.cOut).toEqual(cOut); - - await circuit2.expectPass(input, output); - }); - - it('should read witness correctly', async () => { - const witness = await circuit.calculateWitness(signals.input); - const symbol = 'main.out'; - const symbolValues = await circuit.readWitness(witness, [symbol]); - expect(symbol in symbolValues).toBe(true); - expect(symbolValues[symbol]).toEqual(BigInt(signals.output.out)); - }); - - it('should assert for correct witness', async () => { - const witness = await circuit.calculateWitness(signals.input); - await circuit.expectConstraintPass(witness); - }); - - it('should NOT assert for maliciously edited witness', async () => { - // create a valid witness - const witness = await circuit.calculateWitness(signals.input); - // change the values so that it still computes correctly but is not sound - const badWitness = await circuit.editWitness(witness, { - 'main.in[0]': BigInt(1), - 'main.in[1]': BigInt(1), - 'main.in[2]': BigInt(signals.output.out), - }); - await circuit.expectConstraintFail(badWitness); - }); -}); diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 5af41da..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "declaration": true, - "noEmitOnError": true, - "noFallthroughCasesInSwitch": true, - "noImplicitReturns": true, - "noImplicitOverride": true, - "esModuleInterop": true, - "pretty": true, - "strict": true, - "skipLibCheck": true, - "types": ["jest", "node"], - // to be used with bundler: pkgroll - "moduleResolution": "Bundler", - "module": "Preserve", - "target": "ES6" - }, - "files": ["./hardhat.config.ts"], - "include": ["src/**/*.*", "tests/**/*.*"], - "exclude": ["node_modules"] -} diff --git a/tsconfig.test.json b/tsconfig.test.json deleted file mode 100644 index 3ddde89..0000000 --- a/tsconfig.test.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "ES2020", - "moduleResolution": "Node", - "module": "CommonJS", - "lib": ["ES2020"] - } -} From 08f66800c7deb026605aebe9fbc2f9ec69c08025 Mon Sep 17 00:00:00 2001 From: erhant Date: Tue, 30 Jun 2026 22:37:04 +0300 Subject: [PATCH 02/21] feat: CLI `--backend` override and prime-aware witness writing, add `Justfile` (#126) * feat: CLI `--backend` override and prime-aware witness writing, add `Justfile` * fix: copilot comments --- Cargo.lock | 1 + Justfile | 35 ++++++++++++ crates/circomkit-cli/src/main.rs | 12 +++- crates/circomkit-core/Cargo.toml | 3 + crates/circomkit-core/src/enums.rs | 56 +++++++++++++++++++ crates/circomkit-core/src/utils/mod.rs | 2 +- crates/circomkit-core/src/utils/primes.rs | 26 +++++++++ crates/circomkit-core/src/utils/witness.rs | 53 ++++++++++++++---- .../src/lambdaworks/convert.rs | 8 +-- crates/circomkit/src/circomkit/compile.rs | 16 +++--- crates/circomkit/src/circomkit/prove.rs | 16 ++++-- crates/circomkit/src/lib.rs | 2 +- crates/circomkit/tests/e2e/prove.rs | 43 ++++++++++++-- 13 files changed, 236 insertions(+), 37 deletions(-) create mode 100644 Justfile diff --git a/Cargo.lock b/Cargo.lock index 3029d5d..4849e88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -661,6 +661,7 @@ dependencies = [ "schemars 0.8.22", "serde", "serde_json", + "tempfile", "thiserror 2.0.18", "ureq", ] diff --git a/Justfile b/Justfile new file mode 100644 index 0000000..57deed3 --- /dev/null +++ b/Justfile @@ -0,0 +1,35 @@ +## Run `just` to see recipes. + +# List available recipes +default: + @just --list + +# Format all crates +fmt: + cargo fmt --all + +# Check formatting without modifying files (CI-friendly) +fmt-check: + cargo fmt --all --check + +# Lint with clippy across the workspace +lint: + cargo clippy --workspace --all-targets + +# Lint including the native proving backends +lint-all: + cargo clippy --workspace --all-targets --features "prove-arkworks,prove-lambdaworks" + +# Run the test suite (e2e needs `circom` + `snarkjs` on PATH) +test: + cargo test --workspace + +# Run tests including the native proving backends +test-all: + cargo test --workspace --features "prove-arkworks,prove-lambdaworks" + +# Format, lint, and test — the pre-commit gate +check: fmt lint test + +# Same as `check` but with native backends enabled +check-all: fmt lint-all test-all diff --git a/crates/circomkit-cli/src/main.rs b/crates/circomkit-cli/src/main.rs index 8b52a1c..43e3006 100644 --- a/crates/circomkit-cli/src/main.rs +++ b/crates/circomkit-cli/src/main.rs @@ -4,6 +4,7 @@ use anyhow::{Context, Result}; use clap::{Parser, Subcommand}; use circomkit::Circomkit; +use circomkit::ProvingBackendKind; #[derive(Parser)] #[command( @@ -94,6 +95,9 @@ enum Commands { circuit: String, /// Input name input: String, + /// Override the proving backend (snarkjs, arkworks, lambdaworks) + #[arg(long)] + backend: Option, }, /// Verify a proof @@ -243,8 +247,12 @@ fn main() -> Result<()> { println!("witness: {}", path.display()); } - Commands::Prove { circuit, input } => { - let path = ck.prove(&circuit, &input, None)?; + Commands::Prove { + circuit, + input, + backend, + } => { + let path = ck.prove(&circuit, &input, None, backend)?; println!("proof: {}", path.display()); } diff --git a/crates/circomkit-core/Cargo.toml b/crates/circomkit-core/Cargo.toml index 0383532..a891f86 100644 --- a/crates/circomkit-core/Cargo.toml +++ b/crates/circomkit-core/Cargo.toml @@ -22,3 +22,6 @@ download = ["dep:ureq"] [dependencies.ureq] workspace = true optional = true + +[dev-dependencies] +tempfile.workspace = true diff --git a/crates/circomkit-core/src/enums.rs b/crates/circomkit-core/src/enums.rs index b530b00..61fdf91 100644 --- a/crates/circomkit-core/src/enums.rs +++ b/crates/circomkit-core/src/enums.rs @@ -69,6 +69,31 @@ pub enum ProvingBackendKind { Lambdaworks, } +impl fmt::Display for ProvingBackendKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Snarkjs => write!(f, "snarkjs"), + Self::Arkworks => write!(f, "arkworks"), + Self::Lambdaworks => write!(f, "lambdaworks"), + } + } +} + +impl std::str::FromStr for ProvingBackendKind { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + match s.to_ascii_lowercase().as_str() { + "snarkjs" => Ok(Self::Snarkjs), + "arkworks" => Ok(Self::Arkworks), + "lambdaworks" => Ok(Self::Lambdaworks), + other => Err(format!( + "unknown proving backend '{other}' (expected: snarkjs, arkworks, lambdaworks)" + )), + } + } +} + /// Log level for circomkit operations. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "lowercase")] @@ -95,3 +120,34 @@ impl LogLevel { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn proving_backend_kind_from_str_roundtrips() { + for kind in [ + ProvingBackendKind::Snarkjs, + ProvingBackendKind::Arkworks, + ProvingBackendKind::Lambdaworks, + ] { + let parsed: ProvingBackendKind = kind.to_string().parse().unwrap(); + assert_eq!(parsed, kind); + } + // Case-insensitive parsing. + assert_eq!( + "ARKWORKS".parse::().unwrap(), + ProvingBackendKind::Arkworks + ); + } + + #[test] + fn proving_backend_kind_from_str_rejects_unknown() { + let err = "plonky2".parse::().unwrap_err(); + assert!( + err.contains("plonky2"), + "error should name the bad input: {err}" + ); + } +} diff --git a/crates/circomkit-core/src/utils/mod.rs b/crates/circomkit-core/src/utils/mod.rs index c1bcad7..d9b7089 100644 --- a/crates/circomkit-core/src/utils/mod.rs +++ b/crates/circomkit-core/src/utils/mod.rs @@ -3,7 +3,7 @@ mod ptau; mod r1cs; mod witness; -pub use primes::{prime_from_value, prime_value}; +pub use primes::{prime_field_n8, prime_from_value, prime_value}; pub use ptau::{download_ptau, ptau_name_for_constraints, ptau_path_if_exists}; pub use r1cs::{parse_r1cs_bytes, parse_r1cs_info, read_r1cs_file, read_r1cs_info}; pub use witness::{ diff --git a/crates/circomkit-core/src/utils/primes.rs b/crates/circomkit-core/src/utils/primes.rs index fae66aa..9c30e16 100644 --- a/crates/circomkit-core/src/utils/primes.rs +++ b/crates/circomkit-core/src/utils/primes.rs @@ -41,6 +41,19 @@ pub fn prime_value(prime: Prime) -> BigUint { } } +/// Returns the number of bytes used to encode a field element of the given prime +/// in Circom's binary `.wtns`/`.r1cs` formats (the `n8` field). +/// +/// Matches snarkjs/ffjavascript: the modulus bit-length rounded up to a whole +/// number of 64-bit words, times 8. e.g. bn128 (254 bits) → 32, goldilocks +/// (64 bits) → 8. +/// +/// TODO: add link here +pub fn prime_field_n8(prime: Prime) -> u32 { + let bits = prime_value(prime).bits(); + (((bits - 1) / 64 + 1) * 8) as u32 +} + /// Attempts to identify a `Prime` variant from its field value. pub fn prime_from_value(value: &BigUint) -> Option { let primes = [ @@ -81,4 +94,17 @@ mod tests { let unknown = BigUint::from(42u32); assert_eq!(prime_from_value(&unknown), None); } + + #[test] + fn field_n8_matches_snarkjs_word_alignment() { + // 254/255-bit curves pack into 32 bytes (4 64-bit words). + assert_eq!(prime_field_n8(Prime::Bn128), 32); + assert_eq!(prime_field_n8(Prime::Bls12381), 32); + assert_eq!(prime_field_n8(Prime::Grumpkin), 32); + assert_eq!(prime_field_n8(Prime::Pallas), 32); + assert_eq!(prime_field_n8(Prime::Vesta), 32); + assert_eq!(prime_field_n8(Prime::Secq256r1), 32); + // Goldilocks is a 64-bit field — a single word. + assert_eq!(prime_field_n8(Prime::Goldilocks), 8); + } } diff --git a/crates/circomkit-core/src/utils/witness.rs b/crates/circomkit-core/src/utils/witness.rs index 17ff0b3..0690919 100644 --- a/crates/circomkit-core/src/utils/witness.rs +++ b/crates/circomkit-core/src/utils/witness.rs @@ -4,7 +4,7 @@ use std::path::Path; use num_bigint::BigInt; use num_traits::Signed; -use super::primes::prime_value; +use super::primes::{prime_field_n8, prime_value}; use crate::error::{CoreError, Result}; use crate::types::Witness; @@ -98,15 +98,14 @@ pub fn parse_witness_to_elems( )) } -/// Write a witness to a binary `.wtns` file (version 2, BN128 prime). -/// -/// Uses 32 bytes per field element (n8 = 32), which is standard for BN128/BLS12-381. -/// -/// TODO: take prime as argument -pub fn write_witness_file(path: &Path, witness: &Witness) -> Result<()> { - let n8: u32 = 32; - let prime = prime_value(crate::enums::Prime::Bn128); - let prime_bytes = prime.to_bytes_le(); +/// Write a witness to a binary `.wtns` file (version 2) for the given prime. +pub fn write_witness_file( + path: &Path, + witness: &Witness, + prime: crate::enums::Prime, +) -> Result<()> { + let n8 = prime_field_n8(prime); + let prime_bytes = prime_value(prime).to_bytes_le(); let witness_count = witness.len() as u32; @@ -155,3 +154,37 @@ pub fn write_witness_file(path: &Path, witness: &Witness) -> Result<()> { std::fs::write(path, buf)?; Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::enums::Prime; + + /// Extract the `n8` field from section 1 of a written witness file. + /// Layout: header (12 bytes) + section id (4) + section length (8) → n8 at offset 24. + fn n8_from_bytes(buf: &[u8]) -> u32 { + u32::from_le_bytes(buf[24..28].try_into().unwrap()) + } + + #[test] + fn writes_n8_per_prime_and_roundtrips() { + let dir = tempfile::tempdir().unwrap(); + + // create a fake witness + let witness = vec![BigInt::from(1), BigInt::from(42), BigInt::from(255)]; + + // bn128 packs elements into 32 bytes + let bn = dir.path().join("bn128.wtns"); + write_witness_file(&bn, &witness, Prime::Bn128).unwrap(); + let bytes = std::fs::read(&bn).unwrap(); + assert_eq!(n8_from_bytes(&bytes), 32); + assert_eq!(parse_witness_bytes(&bytes).unwrap(), witness); + + // goldilocks packs elements into 8 bytes + let gl = dir.path().join("goldilocks.wtns"); + write_witness_file(&gl, &witness, Prime::Goldilocks).unwrap(); + let bytes = std::fs::read(&gl).unwrap(); + assert_eq!(n8_from_bytes(&bytes), 8); + assert_eq!(parse_witness_bytes(&bytes).unwrap(), witness); + } +} diff --git a/crates/circomkit-prove/src/lambdaworks/convert.rs b/crates/circomkit-prove/src/lambdaworks/convert.rs index 3787a54..b6bc1c0 100644 --- a/crates/circomkit-prove/src/lambdaworks/convert.rs +++ b/crates/circomkit-prove/src/lambdaworks/convert.rs @@ -24,8 +24,8 @@ fn field_to_dec(elem: &FieldElement) -> String { pub fn proof_to_snarkjs_json(proof: &Proof) -> serde_json::Value { serde_json::json!({ "pi_a": [ - field_to_dec(&proof.pi1.x()), - field_to_dec(&proof.pi1.y()), + field_to_dec(proof.pi1.x()), + field_to_dec(proof.pi1.y()), "1" ], "pi_b": [ @@ -40,8 +40,8 @@ pub fn proof_to_snarkjs_json(proof: &Proof) -> serde_json::Value { ["1", "0"] ], "pi_c": [ - field_to_dec(&proof.pi3.x()), - field_to_dec(&proof.pi3.y()), + field_to_dec(proof.pi3.x()), + field_to_dec(proof.pi3.y()), "1" ], "protocol": "groth16", diff --git a/crates/circomkit/src/circomkit/compile.rs b/crates/circomkit/src/circomkit/compile.rs index 65801c9..c0a6a35 100644 --- a/crates/circomkit/src/circomkit/compile.rs +++ b/crates/circomkit/src/circomkit/compile.rs @@ -32,17 +32,17 @@ impl Circomkit { }; // Check source .circom file mtime - if let Ok(source_mtime) = source_path.metadata().and_then(|m| m.modified()) { - if source_mtime > r1cs_mtime { - return false; - } + if let Ok(source_mtime) = source_path.metadata().and_then(|m| m.modified()) + && source_mtime > r1cs_mtime + { + return false; } // Check generated main file mtime - if let Ok(main_mtime) = main_path.metadata().and_then(|m| m.modified()) { - if main_mtime > r1cs_mtime { - return false; - } + if let Ok(main_mtime) = main_path.metadata().and_then(|m| m.modified()) + && main_mtime > r1cs_mtime + { + return false; } true diff --git a/crates/circomkit/src/circomkit/prove.rs b/crates/circomkit/src/circomkit/prove.rs index e0be8ce..e59d676 100644 --- a/crates/circomkit/src/circomkit/prove.rs +++ b/crates/circomkit/src/circomkit/prove.rs @@ -97,6 +97,8 @@ impl Circomkit { input: &str, data: Option<&CircuitSignals>, ) -> Result { + let prime = self.resolve(circuit)?.compiler.prime; + let input_data = match data { Some(d) => d.clone(), None => self.load_input(circuit, input)?, @@ -114,7 +116,7 @@ impl Circomkit { if let Some(parent) = wtns_path.parent() { std::fs::create_dir_all(parent)?; } - circomkit_core::utils::write_witness_file(&wtns_path, &witness)?; + circomkit_core::utils::write_witness_file(&wtns_path, &witness, prime)?; log::info!("witness computed for {circuit}/{input}"); Ok(wtns_path) @@ -122,19 +124,21 @@ impl Circomkit { /// Generate a proof for a circuit with the given input. /// - /// The proving backend is selected from the resolved circuit config - /// (`prover.backend`), capability-checked against the protocol and curve. - /// snarkjs uses its one-shot `full_prove`; native backends (arkworks, - /// lambdaworks) compute a witness first, then prove from it. + /// The proving backend is taken from `backend` when provided (e.g. the CLI + /// `--backend` flag), otherwise from the resolved circuit config + /// (`prover.backend`). Either way it is capability-checked against the + /// protocol and curve. snarkjs uses its one-shot `full_prove`; native + /// backends (arkworks, lambdaworks) compute a witness first, then prove from it. pub fn prove( &self, circuit: &str, input: &str, data: Option<&CircuitSignals>, + backend: Option, ) -> Result { let resolved = self.resolve(circuit)?; let protocol = resolved.prover.protocol; - let kind = resolved.prover.backend; + let kind = backend.unwrap_or(resolved.prover.backend); let prime = resolved.compiler.prime; let pkey_path = self.paths.pkey(circuit, protocol); diff --git a/crates/circomkit/src/lib.rs b/crates/circomkit/src/lib.rs index 758517b..9016f19 100644 --- a/crates/circomkit/src/lib.rs +++ b/crates/circomkit/src/lib.rs @@ -9,7 +9,7 @@ pub use circomkit::Circomkit; // Re-export key types for convenience pub use circomkit_core::config::{CircomkitConfig, CircuitConfig}; -pub use circomkit_core::enums::{Prime, Protocol}; +pub use circomkit_core::enums::{Prime, Protocol, ProvingBackendKind}; pub use circomkit_core::error::CoreError; pub use circomkit_core::pathing::CircomkitPaths; pub use circomkit_core::types::R1CSInfo; diff --git a/crates/circomkit/tests/e2e/prove.rs b/crates/circomkit/tests/e2e/prove.rs index 7bada7d..d26cd08 100644 --- a/crates/circomkit/tests/e2e/prove.rs +++ b/crates/circomkit/tests/e2e/prove.rs @@ -16,7 +16,7 @@ fn full_prove_and_verify() { let input = signals! { "in" => vec![2_i64, 4, 10] }; let proof_path = ck - .prove("multiplier_3", "prove_test", Some(&input)) + .prove("multiplier_3", "prove_test", Some(&input), None) .unwrap(); assert!(proof_path.exists()); @@ -30,7 +30,7 @@ fn verify_rejects_tampered_signals() { setup_multiplier(&ck); let input = signals! { "in" => vec![2_i64, 4, 10] }; - ck.prove("multiplier_3", "tamper_test", Some(&input)) + ck.prove("multiplier_3", "tamper_test", Some(&input), None) .unwrap(); // Tamper with the public signals file @@ -52,7 +52,7 @@ fn prove_rejects_unsupported_backend_curve() { let input = signals! { "in" => vec![2_i64, 4, 10] }; let err = ck - .prove("multiplier_3", "cap_test", Some(&input)) + .prove("multiplier_3", "cap_test", Some(&input), None) .expect_err("lambdaworks on bn128 must be rejected"); let msg = err.to_string().to_lowercase(); @@ -80,7 +80,9 @@ fn arkworks_backend_through_orchestrator() { ck.config.prover.backend = ProvingBackendKind::Arkworks; let input = signals! { "in" => vec![2_i64, 4, 10] }; - let proof_path = ck.prove("multiplier_3", "ark_e2e", Some(&input)).unwrap(); + let proof_path = ck + .prove("multiplier_3", "ark_e2e", Some(&input), None) + .unwrap(); assert!(proof_path.exists()); // Same proving key snarkjs set up + snarkjs-format proof => snarkjs verifies it. @@ -88,6 +90,37 @@ fn arkworks_backend_through_orchestrator() { assert!(ok, "snarkjs should verify the arkworks-generated proof"); } +/// An explicit backend override (as the CLI `--backend` flag passes) wins over +/// the resolved `prover.backend`. The config defaults to snarkjs (bn128), but +/// overriding to lambdaworks (bls12381-only) surfaces the curve capability error +/// before any proving work — proving the override, not the config, was used. +#[test] +fn prove_backend_override_beats_config() { + use circomkit::core::enums::ProvingBackendKind; + + let (ck, _guard) = test_circomkit(); + + let input = signals! { "in" => vec![2_i64, 4, 10] }; + let err = ck + .prove( + "multiplier_3", + "override_test", + Some(&input), + Some(ProvingBackendKind::Lambdaworks), + ) + .expect_err("override to lambdaworks on bn128 must be rejected"); + + let msg = err.to_string().to_lowercase(); + assert!( + msg.contains("lambdaworks"), + "error should name the overridden backend: {msg}" + ); + assert!( + msg.contains("curve"), + "error should mention the curve: {msg}" + ); +} + #[test] fn witness_then_prove() { let (ck, _guard) = test_circomkit(); @@ -102,7 +135,7 @@ fn witness_then_prove() { // Then prove (will recompute witness via snarkjs, but the file exists) let proof_path = ck - .prove("multiplier_3", "witness_test", Some(&input)) + .prove("multiplier_3", "witness_test", Some(&input), None) .unwrap(); assert!(proof_path.exists()); From 655a6f91173dee6b02bd1242d6ff64b7b2a1a648 Mon Sep 17 00:00:00 2001 From: erhant Date: Wed, 1 Jul 2026 14:06:33 +0300 Subject: [PATCH 03/21] example: multiplier with e2e test script --- README.md | 367 ++++++++++++++++++ crates/circomkit-core/src/config/circomkit.rs | 3 +- crates/circomkit/src/circomkit/mod.rs | 2 +- examples/multiplier/.gitignore | 6 + examples/multiplier/circomkit.json | 19 + .../multiplier/circuits/multiplier.circom | 36 ++ examples/multiplier/e2e.sh | 73 ++++ .../inputs/multiplier_3/default.json | 3 + 8 files changed, 507 insertions(+), 2 deletions(-) create mode 100644 README.md create mode 100644 examples/multiplier/.gitignore create mode 100644 examples/multiplier/circomkit.json create mode 100644 examples/multiplier/circuits/multiplier.circom create mode 100755 examples/multiplier/e2e.sh create mode 100644 examples/multiplier/inputs/multiplier_3/default.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..cbcaf8c --- /dev/null +++ b/README.md @@ -0,0 +1,367 @@ +

+

+ Circomkit +

+

A simple-to-use & opinionated circuit development & testing toolkit — in Rust.

+

+ +

+ + + + + Rust + +

+ +This is a Rust rewrite of [Circomkit](https://github.com/erhant/circomkit) (originally TypeScript), delivered as a modular workspace: a **CLI tool**, a **library**, and **testing utilities**. It keeps the opinionated, path-abstracting design of the original while adding native Rust proving backends and multi-curve support. + +- [x] Simple CLI, abstracting away all paths behind a single config. +- [x] Testing utilities to check circuit computations & soundness errors, with minimal boilerplate. +- [x] Supports all protocols: `groth16`, `plonk`, and `fflonk` (via snarkjs). +- [x] Native Rust proving backends: **Arkworks** (Groth16 / BN254) and **Lambdaworks** (Groth16 / BLS12-381). +- [x] Automatically downloads phase-1 PTAU when using `bn128`. +- [x] Exports a Solidity verifier contract and its calldata, or JSON exports for R1CS. + +> [!NOTE] +> +> This is a work-in-progress rewrite. Node.js (napi-rs) and Python (pyo3) bindings are planned; the `Circomkit` struct is intentionally FFI-friendly (no generics, owned return types). + +## Requirements + +Circomkit shells out to external tools for compilation and (by default) proving: + +- [`circom`](https://docs.circom.io/getting-started/installation/) (v2.2.x) — circuit compiler. +- [`snarkjs`](https://github.com/iden3/snarkjs) (v0.7.x, installed globally via npm) — used for the default proving/setup/verify pipeline (Groth16, PLONK, FFLONK across all 7 primes). + +The native Arkworks / Lambdaworks backends do their own proving in-process and don't require snarkjs to *prove*, but setup / vkey / contract / verify still route through snarkjs. + +## Installation + +Build from source with Cargo (edition 2024): + +```sh +cargo build --release # binary at target/release/circomkit +cargo run -p circomkit-cli # run the CLI directly +``` + +To use Circomkit as a library, add the umbrella crate as a dependency: + +```toml +[dependencies] +circomkit = { git = "https://github.com/erhant/circomkit" } +``` + +## Usage + +You can see available commands with: + +```sh +circomkit --help +``` + +By default the CLI reads `./circomkit.json`; override it with the global `--config` flag. + +### Command Line Interface + +Actions that require a circuit name can be called as follows: + +```sh +# Compile circuit(s) — the argument is a regex, so "multiplier.*" matches many +circomkit compile + +# Create the main component file +circomkit instantiate + +# Print circuit info (wires, constraints, public/private I/O, prime, ...) +circomkit info + +# Create a Solidity verifier contract +circomkit contract + +# Remove build artifacts for a circuit +circomkit clear + +# Circuit-specific trusted setup (auto-downloads PTAU if --ptau is omitted) +circomkit setup [--ptau ] + +# Export the verification key +circomkit vkey + +# Automatically download PTAU (for BN128) +circomkit ptau +``` + +> [!NOTE] +> +> `setup` optionally takes a PTAU path. If omitted, Circomkit decides which PTAU to use based on the constraint count and downloads it for you. This only works for the `bn128` prime and has an upper-limit of $2^{28}$ constraints. + +Actions that generate a witness, a proof, or verify a proof need JSON inputs for the signal values. Input files live under the `inputs` folder, in a directory named after the circuit. For example, an input named `foo` for a circuit named `bar` is at `inputs/bar/foo.json`. + +```sh +# Compute a witness +circomkit witness + +# Generate a proof (optionally overriding the configured backend) +circomkit prove [--backend ] + +# Verify a proof +circomkit verify + +# Export Solidity calldata to the console +circomkit calldata [--pretty] + +# Export R1CS metadata as JSON +circomkit json r1cs +``` + +You can also inspect configured circuits and the effective configuration: + +```sh +# List configured circuits +circomkit list + +# Print the effective (resolved) configuration +circomkit config +``` + +### Circomkit Configuration + +Everything is driven by a single `circomkit.json`, following the v0.4 unified-config style with nested sections. You can print the active configuration with `circomkit config`, and a JSON schema is available (`schema.json`) for editor autocompletion. + +```json +{ + "$schema": "./schema.json", + "prover": { + "protocol": "groth16", + "backend": "snarkjs", + "ptauDir": "./ptau", + "inputDir": "./inputs" + }, + "compiler": { + "prime": "bn128", + "srcDir": "./circuits", + "outDir": "./build", + "optimization": 1 + }, + "witness": { "calculator": "wasm" }, + "logLevel": "info", + "circuits": { + "multiplier_3": { + "file": "multiplier", + "template": "Multiplier", + "params": [3] + } + } +} +``` + +You can change the `protocol` (`groth16`, `plonk`, `fflonk`), the proving `backend` (`snarkjs`, `arkworks`, `lambdaworks`), and the underlying `prime` (`bn128`, `bls12381`, `goldilocks`, `grumpkin`, `pallas`, `vesta`, `secq256r1`). + +> [!NOTE] +> +> Using a prime other than `bn128` makes circuit-specific setup harder, as you must supply the PTAU files yourself; with `bn128` we can use the [Perpetual Powers of Tau](https://github.com/privacy-scaling-explorations/perpetualpowersoftau). + +### Circuit Configuration + +Each entry under `circuits` uses the circuit name as the key. The value describes the source filename, the template name, its public signals, and its template parameters: + +```json +"sudoku_9x9": { + "file": "sudoku", + "template": "Sudoku", + "pubs": ["puzzle"], + "params": [3] +} +``` + +> [!TIP] +> +> `pubs` and `params` can be omitted, in which case they default to `[]`. Per-circuit `overrides` merge on top of the global settings (e.g. `"overrides": { "version": "2.2.0" }`). + +### Using Circomkit in Code + +The `Circomkit` orchestrator exposes the same operations as the CLI. You can load config from a file, or provide circuit configuration and inputs directly. + +```rust +use circomkit::{Circomkit, signals}; + +// Load configuration from circomkit.json (accepts any AsRef: &str, PathBuf, ...) +let ck = Circomkit::from_file("circomkit.json")?; + +// Artifacts output under build/multiplier_3 +ck.compile("multiplier_3")?; + +// Compute a witness from inline signals +let input = signals! { "in" => vec![3_i64, 5, 7] }; +let wtns = ck.witness("multiplier_3", "my_input", Some(&input))?; + +// Generate a proof; pass None to fall back to the configured backend +let proof = ck.prove("multiplier_3", "my_input", Some(&input), None)?; + +// Verify it +assert!(ck.verify("multiplier_3", "my_input")?); +``` + +## Writing Tests + +Circomkit provides two tester utilities that reduce boilerplate so you can focus on inputs and outputs. Signals are built with the `signals!` macro. + +### Witness Tester + +`WitnessTester` computes witnesses via the WASM calculator (wasmtime) and offers assertion helpers: + +- `expect_pass(input, None)` — constraints & assertions pass for the input. +- `expect_pass(input, Some(output))` — additionally checks that outputs match. +- `expect_fail(input)` — witness computation fails (returns the error message). + +```rust +use circomkit::{Circomkit, signals}; + +let ck = Circomkit::from_file("circomkit.json")?; +let config = ck.config.circuits["multiplier_3"].clone(); +let tester = ck.witness_tester("multiplier_3", config)?; + +// Passes on correct input & output +let input = signals! { "in" => vec![2_i64, 4, 10] }; +let output = signals! { "out" => 80_i64 }; +tester.expect_pass(&input, Some(&output))?; + +// Fails on bad input +let bad = signals! { "in" => vec![1_i64, 4, 10] }; +tester.expect_fail(&bad)?; +``` + +Check the constraint count with `expect_constraint_count(n, exact)` — `exact = true` asserts equality, otherwise it asserts `actual >= n`: + +```rust +tester.expect_constraint_count(15, true)?; // exactly 15 constraints +``` + +For finer control over outputs, `compute(input, &["out"])` extracts named output signals from the witness: + +```rust +let out = tester.compute(&signals! { "in" => vec![2_i64, 3, 5] }, &["out"])?; +assert_eq!(out["out"], circomkit::SignalValue::Single(30.into())); +``` + +To test for **soundness errors**, compute a witness with `calculate_witness`, tamper with it via `edit_witness` (a map of symbol names to new values), then check that constraints now fail: + +```rust +use std::collections::HashMap; + +let witness = tester.calculate_witness(&input)?; +let mut overrides = HashMap::new(); +overrides.insert("main.out".to_string(), 1234.into()); +let bad_witness = tester.edit_witness(&witness, &overrides)?; +// assert that bad_witness no longer satisfies the constraints +``` + +### Proof Tester + +`ProofTester` generates and verifies a proof end-to-end using the WASM file, proving key, and verification key. Create the setup artifacts before constructing the tester: + +```rust +use circomkit::Protocol; + +let ck = Circomkit::from_file("circomkit.json")?; +ck.instantiate("multiplier_3")?; +ck.setup("multiplier_3", None)?; // auto-downloads PTAU for bn128 +let tester = ck.proof_tester("multiplier_3", Protocol::Groth16)?; +``` + +## Native Proving Backends + +Beyond snarkjs, Circomkit ships two native Rust Groth16 backends, gated behind Cargo features on the umbrella / CLI crates: + +| Backend | Feature flag | Curve | Notes | +|---|---|---|---| +| snarkjs | *(default)* | all 7 primes | full protocol support (Groth16 / PLONK / FFLONK) | +| Arkworks | `prove-arkworks` | BN254 | loads a snarkjs `.zkey`, produces a snarkjs-format proof | +| Lambdaworks | `prove-lambdaworks` | BLS12-381 | trusted setup on-the-fly, reads binary or JSON R1CS | + +```sh +cargo build --features "prove-arkworks,prove-lambdaworks" +circomkit prove my_circuit my_input --backend arkworks +``` + +The `circomkit-prove::capabilities` matrix is the single source of truth for which `(backend, protocol, curve)` combinations are valid; unsupported combinations error early (`UnsupportedProtocol` / `UnsupportedCurve` / `BackendNotEnabled`). The `--backend` flag (and the `backend` argument to `Circomkit::prove`) overrides the configured `prover.backend`. + +## Workspace Structure + +The project is a Cargo workspace of focused crates: + +```ml +crates +├── circomkit-core - "config, types, pathing, R1CS/witness/sym parsers, compile, PTAU, calldata" +├── circomkit-witness - "WitnessCalculator trait + WASM backend (wasmtime)" +├── circomkit-prove - "ProvingBackend trait + snarkjs / arkworks / lambdaworks backends" +├── circomkit-test - "WitnessTester, ProofTester" +├── circomkit - "umbrella: Circomkit orchestrator + re-exports" +└── circomkit-cli - "the `circomkit` binary (clap)" +``` + +## File Structure + +Circomkit follows an _opinionated file structure_, abstracting away pathing behind the scenes. All directories can be customized in `circomkit.json`. An example for a Sudoku circuit with a 9x9 main component: + +```ml +circomkit +├── circomkit.json - "circomkit configuration" +│ +├── circuits - "circuit source code" +│ ├── main - "auto-generated main components" +│ │ └── sudoku_9x9.circom +│ └── sudoku.circom - "circuit template" +│ +├── inputs - "circuit inputs" +│ └── sudoku_9x9 - "folder name is the circuit instance name" +│ └── my_solution.json - "file name is the input name" +│ +├── ptau - "PTAU files" +│ └── powersOfTau28_hez_final_08.ptau +│ +└── build - "build artifacts" + └── sudoku_9x9 - "folder name is the circuit instance name" + ├── sudoku_9x9_js - "WASM outputs" + │ └── sudoku_9x9.wasm + │ + ├── my_solution - "folder name is the input name" + │ ├── groth16_proof.json - "proof, per protocol" + │ ├── public.json + │ └── witness.wtns + │ + ├── sudoku_9x9.r1cs + ├── sudoku_9x9.sym - "symbol file, used by tests" + │ + ├── groth16_pkey.zkey - "proving key, per protocol" + ├── groth16_vkey.json - "verification key, per protocol" + └── groth16_verifier.sol - "verifier contract" +``` + +## Development + +Common tasks are wrapped in a [`Justfile`](./Justfile): + +```sh +just # list recipes +just fmt # cargo fmt --all +just lint # cargo clippy --workspace --all-targets +just test # cargo test --workspace +just check # fmt + lint + test + +# variants that enable the native proving backends +just lint-all +just test-all +just check-all +``` + +Integration tests require `circom` and `snarkjs` on your `PATH`. Test circuits live under `tests/circuits/` and are configured via `tests/circomkit.json`; end-to-end tests are in `crates/circomkit/tests/e2e/`. + +## Acknowledgements + +We wholeheartedly thank [BuidlGuild](https://buidlguidl.com/) & [Austin Griffith](https://twitter.com/austingriffith) for providing Circomkit with an [Ecosystem Impact Grant](https://grants.buidlguidl.com/)! + +## License + +Licensed under [MIT](./LICENSE). diff --git a/crates/circomkit-core/src/config/circomkit.rs b/crates/circomkit-core/src/config/circomkit.rs index 4097ecd..a2fa63f 100644 --- a/crates/circomkit-core/src/config/circomkit.rs +++ b/crates/circomkit-core/src/config/circomkit.rs @@ -56,7 +56,8 @@ impl CircomkitConfig { /// /// Automatically detects the legacy Circomkit v0.3 flat config format /// and converts it to the new nested format. - pub fn from_file(path: &Path) -> Result { + pub fn from_file(path: impl AsRef) -> Result { + let path = path.as_ref(); if !path.exists() { return Ok(Self::default()); } diff --git a/crates/circomkit/src/circomkit/mod.rs b/crates/circomkit/src/circomkit/mod.rs index 6c194ca..ba487c6 100644 --- a/crates/circomkit/src/circomkit/mod.rs +++ b/crates/circomkit/src/circomkit/mod.rs @@ -28,7 +28,7 @@ impl Circomkit { } /// Load Circomkit from a `circomkit.json` file. - pub fn from_file(path: &Path) -> Result { + pub fn from_file(path: impl AsRef) -> Result { let config = CircomkitConfig::from_file(path)?; Self::new(config) } diff --git a/examples/multiplier/.gitignore b/examples/multiplier/.gitignore new file mode 100644 index 0000000..ce02b00 --- /dev/null +++ b/examples/multiplier/.gitignore @@ -0,0 +1,6 @@ +# Circomkit build artifacts and downloaded PTAU +/build +/ptau + +# Auto-generated main components (created by `circomkit compile`/`instantiate`) +/circuits/main diff --git a/examples/multiplier/circomkit.json b/examples/multiplier/circomkit.json new file mode 100644 index 0000000..b29f41e --- /dev/null +++ b/examples/multiplier/circomkit.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../schema.json", + "prover": { + "protocol": "groth16", + "backend": "snarkjs" + }, + "compiler": { + "prime": "bn128", + "srcDir": "./circuits", + "outDir": "./build" + }, + "circuits": { + "multiplier_3": { + "file": "multiplier", + "template": "Multiplier", + "params": [3] + } + } +} diff --git a/examples/multiplier/circuits/multiplier.circom b/examples/multiplier/circuits/multiplier.circom new file mode 100644 index 0000000..0fd190c --- /dev/null +++ b/examples/multiplier/circuits/multiplier.circom @@ -0,0 +1,36 @@ +pragma circom 2.0.0; + +template IsZero() { + signal input in; + signal output out; + + signal inv; + inv <-- in != 0 ? (1 / in) : 0; + + out <== (-in * inv) + 1; + in * out === 0; +} + +// Multiplies `n` numbers together, asserting none of them equals 1. +template Multiplier(n) { + assert(n > 1); + signal input in[n]; + signal output out; + + // assert that all numbers are != 1 + component isZero[n]; + for (var i = 0; i < n; i++) { + isZero[i] = IsZero(); + isZero[i].in <== in[i] - 1; + isZero[i].out === 0; + } + + // multiply + signal inner[n-1]; + inner[0] <== in[0] * in[1]; + for (var i = 2; i < n; i++) { + inner[i-1] <== inner[i-2] * in[i]; + } + + out <== inner[n-2]; +} diff --git a/examples/multiplier/e2e.sh b/examples/multiplier/e2e.sh new file mode 100755 index 0000000..f2e564f --- /dev/null +++ b/examples/multiplier/e2e.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# +# End-to-end walkthrough of the Circomkit CLI against the multiplier example. +# Compiles a circuit, runs a trusted setup, computes a witness, proves, and verifies. +# +# Requires `circom` and `snarkjs` on your PATH. +# Run from anywhere: ./examples/multiplier/e2e.sh +# +set -euo pipefail + +# Resolve paths so the script works from any working directory. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +CIRCUIT="multiplier_3" +INPUT="default" + +# --- helpers --------------------------------------------------------------- + +step() { + echo + echo "==================================================================" + echo ">> $1" + echo "==================================================================" +} + +# --- build the CLI --------------------------------------------------------- + +step "Building the circomkit CLI" +cargo build -p circomkit-cli --manifest-path "$REPO_ROOT/Cargo.toml" +BIN="$REPO_ROOT/target/debug/circomkit" + +# Run every command with the example dir as the working directory so the +# relative paths in circomkit.json (./circuits, ./build, ...) resolve here. +cd "$SCRIPT_DIR" + +# --- the walkthrough ------------------------------------------------------- + +step "Effective configuration" +"$BIN" config + +step "Configured circuits" +"$BIN" list + +step "Compiling '$CIRCUIT'" +"$BIN" compile "$CIRCUIT" + +step "Circuit info (wires, constraints, I/O, prime)" +"$BIN" info "$CIRCUIT" + +step "Trusted setup (auto-downloads PTAU for bn128)" +"$BIN" setup "$CIRCUIT" + +step "Exporting the verification key" +"$BIN" vkey "$CIRCUIT" + +step "Computing the witness for input '$INPUT'" +"$BIN" witness "$CIRCUIT" "$INPUT" + +step "Generating a proof for input '$INPUT'" +"$BIN" prove "$CIRCUIT" "$INPUT" + +step "Verifying the proof" +"$BIN" verify "$CIRCUIT" "$INPUT" + +step "Exporting a Solidity verifier contract" +"$BIN" contract "$CIRCUIT" + +step "Exporting Solidity calldata" +"$BIN" calldata "$CIRCUIT" "$INPUT" --pretty + +echo +echo "Done! Artifacts are under $SCRIPT_DIR/build/$CIRCUIT" diff --git a/examples/multiplier/inputs/multiplier_3/default.json b/examples/multiplier/inputs/multiplier_3/default.json new file mode 100644 index 0000000..0e62de2 --- /dev/null +++ b/examples/multiplier/inputs/multiplier_3/default.json @@ -0,0 +1,3 @@ +{ + "in": [2, 4, 10] +} From f7f6a293c563453afb5dec9441574e40fe1297de Mon Sep 17 00:00:00 2001 From: erhant Date: Wed, 1 Jul 2026 14:53:22 +0300 Subject: [PATCH 04/21] fix(core): floor PTAU selection at power 8 to match snarkjs domain sizing --- crates/circomkit-core/src/utils/ptau.rs | 67 +++++++++++++++++++------ 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/crates/circomkit-core/src/utils/ptau.rs b/crates/circomkit-core/src/utils/ptau.rs index 338695c..ae54842 100644 --- a/crates/circomkit-core/src/utils/ptau.rs +++ b/crates/circomkit-core/src/utils/ptau.rs @@ -7,18 +7,37 @@ const PTAU_BASE_URL: &str = "https://storage.googleapis.com/zkevm/ptau"; /// Determine the PTAU file name for a given constraint count. /// -/// Finds the smallest power of 2 such that `2^p >= constraints`, -/// then returns the corresponding PTAU filename. +/// Ports the reference Circomkit `getPtauName`: takes `p = ceil(log2(n))`, the +/// smallest power such that `2^p >= n`, then floors at power 8. The floor keeps +/// small circuits off the tiny (fragile) PTAU files and gives snarkjs the extra +/// domain headroom it needs — its own requirement is +/// `floor(log2(nConstraints + nPubInputs + nOutputs)) + 1`, which for small +/// circuits always fits comfortably within `2^8`. +/// +/// The Hermez ceremony tops out at `2^28`; larger circuits fall back to the +/// `_{p}` name, which won't be downloadable and surfaces as a download error. +/// +/// See . pub fn ptau_name_for_constraints(constraints: u32) -> String { - let mut power = 1u32; - let mut exp = 0u32; - while power < constraints { - power = power.saturating_mul(2); - exp += 1; - } - // Minimum PTAU is 2^1 - exp = exp.max(1); - format!("powersOfTau28_hez_final_{exp:02}.ptau") + // ceil(log2(n)): the number of bits needed to represent `n - 1`. + let p = if constraints <= 1 { + 0 + } else { + u32::BITS - (constraints - 1).leading_zeros() + }; + + let id = if p < 8 { + "_08".to_string() + } else if p < 10 { + format!("_0{p}") + } else if p < 28 { + format!("_{p}") + } else if p == 28 { + String::new() + } else { + format!("_{p}") + }; + format!("powersOfTau28_hez_final{id}.ptau") } /// Download a PTAU file if it doesn't already exist. @@ -64,18 +83,29 @@ mod tests { #[test] fn ptau_naming() { + // Small circuits floor at power 8, matching reference Circomkit. + assert_eq!( + ptau_name_for_constraints(0), + "powersOfTau28_hez_final_08.ptau" + ); assert_eq!( ptau_name_for_constraints(1), - "powersOfTau28_hez_final_01.ptau" + "powersOfTau28_hez_final_08.ptau" + ); + assert_eq!( + ptau_name_for_constraints(8), + "powersOfTau28_hez_final_08.ptau" ); assert_eq!( - ptau_name_for_constraints(2), - "powersOfTau28_hez_final_01.ptau" + ptau_name_for_constraints(256), + "powersOfTau28_hez_final_08.ptau" ); + // ceil(log2(257)) = 9 → single-digit tier keeps the leading zero. assert_eq!( - ptau_name_for_constraints(3), - "powersOfTau28_hez_final_02.ptau" + ptau_name_for_constraints(257), + "powersOfTau28_hez_final_09.ptau" ); + // ceil(log2(1024)) = 10 → two-digit tier. assert_eq!( ptau_name_for_constraints(1024), "powersOfTau28_hez_final_10.ptau" @@ -84,5 +114,10 @@ mod tests { ptau_name_for_constraints(1025), "powersOfTau28_hez_final_11.ptau" ); + // The largest ceremony (2^28) uses the base file name. + assert_eq!( + ptau_name_for_constraints(1 << 28), + "powersOfTau28_hez_final.ptau" + ); } } From 1683797c3636addfb8a28df0f04dab7ec899d655 Mon Sep 17 00:00:00 2001 From: erhant Date: Wed, 1 Jul 2026 14:53:34 +0300 Subject: [PATCH 05/21] feat(core): fall back to flat inputs/{circuit}.json input layout --- README.md | 4 ++++ crates/circomkit-core/src/pathing.rs | 13 +++++++++++++ crates/circomkit/src/circomkit/mod.rs | 17 ++++++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cbcaf8c..1b1ed0d 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,10 @@ circomkit ptau Actions that generate a witness, a proof, or verify a proof need JSON inputs for the signal values. Input files live under the `inputs` folder, in a directory named after the circuit. For example, an input named `foo` for a circuit named `bar` is at `inputs/bar/foo.json`. +> [!TIP] +> +> For circuits with a single input, you can skip the subdirectory and use the flat `inputs/{circuit}.json` layout instead. When `inputs/{circuit}/{input}.json` is missing, Circomkit falls back to `inputs/{circuit}.json`. + ```sh # Compute a witness circomkit witness diff --git a/crates/circomkit-core/src/pathing.rs b/crates/circomkit-core/src/pathing.rs index 49b54c5..1bf1480 100644 --- a/crates/circomkit-core/src/pathing.rs +++ b/crates/circomkit-core/src/pathing.rs @@ -113,6 +113,15 @@ impl CircomkitPaths { self.input_dir.join(circuit).join(format!("{input}.json")) } + /// Flat input JSON fallback: `{input_dir}/{circuit}.json` + /// + /// A convenience layout for circuits with a single input, avoiding the + /// per-circuit subdirectory. Used as a fallback when the per-input file + /// under [`input_json`](Self::input_json) does not exist. + pub fn input_json_flat(&self, circuit: &str) -> PathBuf { + self.input_dir.join(format!("{circuit}.json")) + } + /// PTAU file: `{ptau_dir}/{ptau_name}` pub fn ptau(&self, ptau_name: &str) -> PathBuf { self.ptau_dir.join(ptau_name) @@ -185,6 +194,10 @@ mod tests { paths.input_json("mul", "test"), PathBuf::from("./inputs/mul/test.json") ); + assert_eq!( + paths.input_json_flat("mul"), + PathBuf::from("./inputs/mul.json") + ); } #[test] diff --git a/crates/circomkit/src/circomkit/mod.rs b/crates/circomkit/src/circomkit/mod.rs index ba487c6..23e1615 100644 --- a/crates/circomkit/src/circomkit/mod.rs +++ b/crates/circomkit/src/circomkit/mod.rs @@ -44,11 +44,22 @@ impl Circomkit { } /// Load circuit input signals from the inputs directory. + /// + /// Looks for `inputs/{circuit}/{input}.json` first, falling back to the flat + /// `inputs/{circuit}.json` layout for single-input circuits. pub fn load_input(&self, circuit: &str, input: &str) -> Result { let path = self.paths.input_json(circuit, input); - if !path.exists() { - return Err(CoreError::FileNotFound(path)); - } + let path = if path.exists() { + path + } else { + let flat = self.paths.input_json_flat(circuit); + if flat.exists() { + flat + } else { + // Report the primary path — it's the canonical location. + return Err(CoreError::FileNotFound(path)); + } + }; let content = std::fs::read_to_string(&path)?; let signals: CircuitSignals = serde_json::from_str(&content)?; Ok(signals) From 23c2301dc56817a2cd1d7b5ea845fd3118b4a89d Mon Sep 17 00:00:00 2001 From: erhant Date: Mon, 13 Jul 2026 17:40:12 +0300 Subject: [PATCH 06/21] feat: add a ligthweight custom circom parser, along with a circom codegen crate --- Cargo.lock | 68 +++ Cargo.toml | 8 + crates/circomkit-codegen/Cargo.toml | 12 + crates/circomkit-codegen/src/eval.rs | 268 ++++++++++++ crates/circomkit-codegen/src/input.rs | 160 +++++++ crates/circomkit-codegen/src/lib.rs | 73 ++++ .../circomkit-codegen/src/main_component.rs | 134 ++++++ crates/circomkit-codegen/src/wrapper.rs | 248 +++++++++++ .../src/functions/instantiate.rs | 114 ----- crates/circomkit-core/src/functions/mod.rs | 2 - crates/circomkit-parser/Cargo.toml | 18 + crates/circomkit-parser/src/ast.rs | 127 ++++++ crates/circomkit-parser/src/circom.pest | 89 ++++ crates/circomkit-parser/src/lib.rs | 394 ++++++++++++++++++ crates/circomkit/Cargo.toml | 1 + crates/circomkit/src/circomkit/compile.rs | 13 +- 16 files changed, 1611 insertions(+), 118 deletions(-) create mode 100644 crates/circomkit-codegen/Cargo.toml create mode 100644 crates/circomkit-codegen/src/eval.rs create mode 100644 crates/circomkit-codegen/src/input.rs create mode 100644 crates/circomkit-codegen/src/lib.rs create mode 100644 crates/circomkit-codegen/src/main_component.rs create mode 100644 crates/circomkit-codegen/src/wrapper.rs delete mode 100644 crates/circomkit-core/src/functions/instantiate.rs create mode 100644 crates/circomkit-parser/Cargo.toml create mode 100644 crates/circomkit-parser/src/ast.rs create mode 100644 crates/circomkit-parser/src/circom.pest create mode 100644 crates/circomkit-parser/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 4849e88..e390e1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -628,6 +628,7 @@ dependencies = [ name = "circomkit" version = "0.1.0" dependencies = [ + "circomkit-codegen", "circomkit-core", "circomkit-prove", "circomkit-test", @@ -651,6 +652,15 @@ dependencies = [ "serde_json", ] +[[package]] +name = "circomkit-codegen" +version = "0.1.0" +dependencies = [ + "circomkit-parser", + "serde_json", + "thiserror 2.0.18", +] + [[package]] name = "circomkit-core" version = "0.1.0" @@ -666,6 +676,16 @@ dependencies = [ "ureq", ] +[[package]] +name = "circomkit-parser" +version = "0.1.0" +dependencies = [ + "pest", + "pest_derive", + "serde", + "thiserror 2.0.18", +] + [[package]] name = "circomkit-prove" version = "0.1.0" @@ -2378,6 +2398,48 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pest_meta" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" +dependencies = [ + "pest", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -3472,6 +3534,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "unicode-ident" version = "1.0.24" diff --git a/Cargo.toml b/Cargo.toml index 0c168bc..5c1dc25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,8 @@ resolver = "3" members = [ "crates/circomkit-core", + "crates/circomkit-parser", + "crates/circomkit-codegen", "crates/circomkit-witness", "crates/circomkit-prove", "crates/circomkit-test", @@ -19,6 +21,8 @@ authors = ["Erhan Tezcan"] [workspace.dependencies] # Internal crates circomkit-core = { path = "crates/circomkit-core" } +circomkit-parser = { path = "crates/circomkit-parser" } +circomkit-codegen = { path = "crates/circomkit-codegen" } circomkit-witness = { path = "crates/circomkit-witness" } circomkit-prove = { path = "crates/circomkit-prove" } circomkit-test = { path = "crates/circomkit-test" } @@ -53,6 +57,10 @@ tempfile = "3" # Regex regex = "1" +# Circom source parsing (circomkit-parser) +pest = "2" +pest_derive = "2" + # WASM runtime (witness calculation) wasmtime = "31" diff --git a/crates/circomkit-codegen/Cargo.toml b/crates/circomkit-codegen/Cargo.toml new file mode 100644 index 0000000..37bd498 --- /dev/null +++ b/crates/circomkit-codegen/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "circomkit-codegen" +description = "Code generation (tag wrappers, input scaffolding) for Circom circuits, built on circomkit-parser" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +circomkit-parser.workspace = true +serde_json.workspace = true +thiserror.workspace = true diff --git a/crates/circomkit-codegen/src/eval.rs b/crates/circomkit-codegen/src/eval.rs new file mode 100644 index 0000000..bf5a140 --- /dev/null +++ b/crates/circomkit-codegen/src/eval.rs @@ -0,0 +1,268 @@ +//! A tiny integer-expression evaluator for Circom array dimensions and template +//! arguments (e.g. `N`, `n-1`, `N*M`, `2**k`). +//! +//! Circom array sizes and instantiation arguments must be compile-time integer +//! constants, so evaluating them given the template's parameter bindings yields +//! the concrete shape/value we need for codegen. + +use std::collections::HashMap; + +/// Evaluate an integer expression using the provided identifier bindings. +/// +/// Supports `+ - * / % **`, unary `+`/`-`, parentheses, decimal integer +/// literals, and identifiers looked up in `vars`. Division/modulo are integer +/// operations and error on a zero divisor. +pub fn eval_expr(expr: &str, vars: &HashMap) -> Result { + let tokens = tokenize(expr)?; + let mut parser = Eval { + tokens: &tokens, + pos: 0, + vars, + }; + let value = parser.expr()?; + if parser.pos != parser.tokens.len() { + return Err(format!("unexpected trailing tokens in `{expr}`")); + } + Ok(value) +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Tok { + Num(i64), + Ident(String), + Plus, + Minus, + Star, + Slash, + Percent, + Pow, + LParen, + RParen, +} + +fn tokenize(s: &str) -> Result, String> { + let mut toks = Vec::new(); + let chars: Vec = s.chars().collect(); + let mut i = 0; + while i < chars.len() { + let c = chars[i]; + if c.is_whitespace() { + i += 1; + continue; + } + match c { + '+' => { + toks.push(Tok::Plus); + i += 1; + } + '-' => { + toks.push(Tok::Minus); + i += 1; + } + '*' => { + if i + 1 < chars.len() && chars[i + 1] == '*' { + toks.push(Tok::Pow); + i += 2; + } else { + toks.push(Tok::Star); + i += 1; + } + } + '/' => { + toks.push(Tok::Slash); + i += 1; + } + '%' => { + toks.push(Tok::Percent); + i += 1; + } + '(' => { + toks.push(Tok::LParen); + i += 1; + } + ')' => { + toks.push(Tok::RParen); + i += 1; + } + _ if c.is_ascii_digit() => { + let start = i; + while i < chars.len() && chars[i].is_ascii_digit() { + i += 1; + } + let num: String = chars[start..i].iter().collect(); + let val = num + .parse::() + .map_err(|e| format!("invalid number `{num}`: {e}"))?; + toks.push(Tok::Num(val)); + } + _ if c.is_ascii_alphabetic() || c == '_' => { + let start = i; + while i < chars.len() && (chars[i].is_ascii_alphanumeric() || chars[i] == '_') { + i += 1; + } + toks.push(Tok::Ident(chars[start..i].iter().collect())); + } + other => return Err(format!("unexpected character `{other}` in expression")), + } + } + Ok(toks) +} + +struct Eval<'a> { + tokens: &'a [Tok], + pos: usize, + vars: &'a HashMap, +} + +impl Eval<'_> { + fn peek(&self) -> Option<&Tok> { + self.tokens.get(self.pos) + } + + // expr := term (('+' | '-') term)* + fn expr(&mut self) -> Result { + let mut acc = self.term()?; + while let Some(tok) = self.peek() { + match tok { + Tok::Plus => { + self.pos += 1; + acc = acc.checked_add(self.term()?).ok_or("integer overflow")?; + } + Tok::Minus => { + self.pos += 1; + acc = acc.checked_sub(self.term()?).ok_or("integer overflow")?; + } + _ => break, + } + } + Ok(acc) + } + + // term := power (('*' | '/' | '%') power)* + fn term(&mut self) -> Result { + let mut acc = self.power()?; + while let Some(tok) = self.peek() { + match tok { + Tok::Star => { + self.pos += 1; + acc = acc.checked_mul(self.power()?).ok_or("integer overflow")?; + } + Tok::Slash => { + self.pos += 1; + let d = self.power()?; + if d == 0 { + return Err("division by zero".into()); + } + acc /= d; + } + Tok::Percent => { + self.pos += 1; + let d = self.power()?; + if d == 0 { + return Err("modulo by zero".into()); + } + acc %= d; + } + _ => break, + } + } + Ok(acc) + } + + // power := unary ('**' power)? (right-associative) + fn power(&mut self) -> Result { + let base = self.unary()?; + if let Some(Tok::Pow) = self.peek() { + self.pos += 1; + let exp = self.power()?; + if exp < 0 { + return Err("negative exponent".into()); + } + let mut result: i64 = 1; + for _ in 0..exp { + result = result.checked_mul(base).ok_or("integer overflow")?; + } + Ok(result) + } else { + Ok(base) + } + } + + // unary := ('+' | '-') unary | primary + fn unary(&mut self) -> Result { + match self.peek() { + Some(Tok::Minus) => { + self.pos += 1; + Ok(-self.unary()?) + } + Some(Tok::Plus) => { + self.pos += 1; + self.unary() + } + _ => self.primary(), + } + } + + // primary := number | ident | '(' expr ')' + fn primary(&mut self) -> Result { + let tok = self.tokens.get(self.pos).cloned(); + self.pos += 1; + match tok { + Some(Tok::Num(n)) => Ok(n), + Some(Tok::Ident(id)) => self + .vars + .get(&id) + .copied() + .ok_or_else(|| format!("unknown identifier `{id}`")), + Some(Tok::LParen) => { + let v = self.expr()?; + match self.tokens.get(self.pos) { + Some(Tok::RParen) => { + self.pos += 1; + Ok(v) + } + _ => Err("expected `)`".into()), + } + } + other => Err(format!("unexpected token {other:?}")), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn vars() -> HashMap { + HashMap::from([("N".to_string(), 4), ("M".to_string(), 3)]) + } + + #[test] + fn basic_arithmetic() { + let v = vars(); + assert_eq!(eval_expr("N", &v).unwrap(), 4); + assert_eq!(eval_expr("N-1", &v).unwrap(), 3); + assert_eq!(eval_expr("N * M", &v).unwrap(), 12); + assert_eq!(eval_expr("(N + 1) * 2", &v).unwrap(), 10); + assert_eq!(eval_expr("2**3", &v).unwrap(), 8); + assert_eq!(eval_expr("N % M", &v).unwrap(), 1); + assert_eq!(eval_expr("-N + 5", &v).unwrap(), 1); + } + + #[test] + fn precedence_and_assoc() { + let v = vars(); + assert_eq!(eval_expr("1 + 2 * 3", &v).unwrap(), 7); + assert_eq!(eval_expr("2 ** 3 ** 2", &v).unwrap(), 512); // right-assoc + } + + #[test] + fn errors() { + let v = vars(); + assert!(eval_expr("N / 0", &v).is_err()); + assert!(eval_expr("N % 0", &v).is_err()); + assert!(eval_expr("X", &v).is_err()); + assert!(eval_expr("1 +", &v).is_err()); + assert!(eval_expr("(1 + 2", &v).is_err()); + } +} diff --git a/crates/circomkit-codegen/src/input.rs b/crates/circomkit-codegen/src/input.rs new file mode 100644 index 0000000..fc76c02 --- /dev/null +++ b/crates/circomkit-codegen/src/input.rs @@ -0,0 +1,160 @@ +//! Input-JSON scaffolding. +//! +//! Given a template and concrete parameter bindings, emit a placeholder input +//! object mapping each input signal to a zero-filled value of the correct array +//! shape — a starting point users fill in with real values. + +use std::collections::HashMap; + +use circomkit_parser::{MainComponent, Template}; +use serde_json::{Map, Value}; + +use crate::CodegenError; +use crate::eval::eval_expr; + +/// Bind a template's parameters to the arguments of a `main` component. +/// +/// Arguments are evaluated as integer expressions (they are compile-time +/// constants in circom). Earlier bindings are visible to later arguments. +pub fn bind_params( + template: &Template, + main: &MainComponent, +) -> Result, CodegenError> { + if template.params.len() != main.args.len() { + return Err(CodegenError::ParamArity { + template: template.name.clone(), + expected: template.params.len(), + got: main.args.len(), + }); + } + + let mut bindings = HashMap::new(); + for (name, arg) in template.params.iter().zip(&main.args) { + let value = eval_expr(arg, &bindings).map_err(|reason| CodegenError::DimEval { + expr: arg.clone(), + reason, + })?; + bindings.insert(name.clone(), value); + } + Ok(bindings) +} + +/// Build a placeholder input object for a template's input signals. +/// +/// Each input's array dimensions are evaluated against `params`; scalars map to +/// `0` and arrays to nested arrays of `0`. +pub fn scaffold_input( + template: &Template, + params: &HashMap, +) -> Result { + let mut obj = Map::new(); + for sig in template.inputs() { + let mut dims = Vec::with_capacity(sig.dimensions.len()); + for d in &sig.dimensions { + let n = eval_expr(d, params).map_err(|reason| CodegenError::DimEval { + expr: d.clone(), + reason, + })?; + if n < 0 { + return Err(CodegenError::DimEval { + expr: d.clone(), + reason: "negative dimension".to_string(), + }); + } + dims.push(n as usize); + } + obj.insert(sig.name.clone(), zeros(&dims)); + } + Ok(Value::Object(obj)) +} + +/// Pretty-printed JSON string version of [`scaffold_input`]. +pub fn scaffold_input_string( + template: &Template, + params: &HashMap, +) -> Result { + let value = scaffold_input(template, params)?; + // serialization of a plain object never fails + Ok(serde_json::to_string_pretty(&value).expect("json serialization")) +} + +/// A nested array of zeros with the given dimensions (scalar `0` if empty). +fn zeros(dims: &[usize]) -> Value { + match dims.split_first() { + None => Value::from(0), + Some((&head, rest)) => Value::Array((0..head).map(|_| zeros(rest)).collect()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + const ARRAYS: &str = r#" + template Arrays(N, M) { + signal input in; + signal input in1D[N]; + signal input in2D[N][M]; + signal output out; + } + component main = Arrays(2, 3); + "#; + + #[test] + fn scaffolds_nested_shapes() { + let program = circomkit_parser::parse(ARRAYS).unwrap(); + let t = program.template("Arrays").unwrap(); + let params = HashMap::from([("N".to_string(), 2), ("M".to_string(), 3)]); + + let v = scaffold_input(t, ¶ms).unwrap(); + assert_eq!(v["in"], json!(0)); + assert_eq!(v["in1D"], json!([0, 0])); + assert_eq!(v["in2D"], json!([[0, 0, 0], [0, 0, 0]])); + // output signals are not part of the input scaffold + assert!(v.get("out").is_none()); + } + + #[test] + fn binds_params_from_main() { + let program = circomkit_parser::parse(ARRAYS).unwrap(); + let t = program.template("Arrays").unwrap(); + let main = program.main.as_ref().unwrap(); + + let params = bind_params(t, main).unwrap(); + assert_eq!(params["N"], 2); + assert_eq!(params["M"], 3); + + // end-to-end: bindings drive the scaffold + let v = scaffold_input(t, ¶ms).unwrap(); + assert_eq!(v["in2D"], json!([[0, 0, 0], [0, 0, 0]])); + } + + #[test] + fn arity_mismatch_errors() { + let program = circomkit_parser::parse( + r#" + template T(A, B) { signal input x[A]; } + component main = T(2); + "#, + ) + .unwrap(); + let t = program.template("T").unwrap(); + let main = program.main.as_ref().unwrap(); + assert!(matches!( + bind_params(t, main), + Err(CodegenError::ParamArity { .. }) + )); + } + + #[test] + fn pretty_string_is_valid_json() { + let program = circomkit_parser::parse(ARRAYS).unwrap(); + let t = program.template("Arrays").unwrap(); + let params = HashMap::from([("N".to_string(), 2), ("M".to_string(), 3)]); + + let s = scaffold_input_string(t, ¶ms).unwrap(); + let reparsed: Value = serde_json::from_str(&s).unwrap(); + assert_eq!(reparsed["in1D"], json!([0, 0])); + } +} diff --git a/crates/circomkit-codegen/src/lib.rs b/crates/circomkit-codegen/src/lib.rs new file mode 100644 index 0000000..997465c --- /dev/null +++ b/crates/circomkit-codegen/src/lib.rs @@ -0,0 +1,73 @@ +//! Code generation for Circom circuits. +//! +//! Consumers of the parsed interface AST (from [`circomkit_parser`]): +//! +//! - [`generate_tag_wrapper`] — emit a wrapper template with untagged inputs for +//! a template whose inputs carry `{tag}` metadata (issue #116). +//! - [`scaffold_input`] / [`scaffold_input_string`] — emit a placeholder input +//! JSON object with correctly-shaped, zero-filled arrays. +//! +//! Plus config-independent main-component generation: +//! +//! - [`make_circuit_source`] / [`instantiate_circuit`] — generate the +//! `component main` file from a [`MainComponentSpec`]. +//! +//! ``` +//! let src = r#" +//! template BoundedAdd() { +//! signal input {maxbits} a; +//! signal input {maxbits} b; +//! signal output out; +//! } +//! "#; +//! let program = circomkit_parser::parse(src).unwrap(); +//! let template = program.template("BoundedAdd").unwrap(); +//! let wrapper = circomkit_codegen::generate_tag_wrapper(template).unwrap(); +//! assert!(wrapper.contains("template BoundedAdd_wrapper(maxbits)")); +//! ``` + +mod eval; +mod input; +mod main_component; +mod wrapper; + +pub use eval::eval_expr; +pub use input::{bind_params, scaffold_input, scaffold_input_string}; +pub use main_component::{MainComponentSpec, instantiate_circuit, make_circuit_source}; +pub use wrapper::{generate_tag_wrapper, generate_tag_wrapper_with_suffix, generate_tag_wrappers}; + +// Re-export the AST types these functions operate on, so downstream crates +// don't need a direct dependency on circomkit-parser just to name them. +pub use circomkit_parser::{CircomProgram, MainComponent, Signal, SignalDirection, Template}; + +/// Errors produced during code generation. +#[derive(Debug, thiserror::Error)] +pub enum CodegenError { + /// A tag wrapper was requested for a template with no tagged inputs. + #[error("template `{0}` has no tagged inputs; no wrapper needed")] + NoTaggedInputs(String), + + /// A dimension or argument expression could not be evaluated to an integer. + #[error("cannot evaluate expression `{expr}`: {reason}")] + DimEval { + /// The offending expression. + expr: String, + /// Why evaluation failed. + reason: String, + }, + + /// A `main` component's argument count did not match the template's parameters. + #[error("template `{template}` expects {expected} parameter(s) but got {got}")] + ParamArity { + /// Template name. + template: String, + /// Number of declared parameters. + expected: usize, + /// Number of supplied arguments. + got: usize, + }, + + /// The source could not be parsed. + #[error(transparent)] + Parse(#[from] circomkit_parser::ParseError), +} diff --git a/crates/circomkit-codegen/src/main_component.rs b/crates/circomkit-codegen/src/main_component.rs new file mode 100644 index 0000000..9c39fbb --- /dev/null +++ b/crates/circomkit-codegen/src/main_component.rs @@ -0,0 +1,134 @@ +//! Main-component (`component main`) source generation. +//! +//! Generates the small auto-generated `.circom` file that instantiates a +//! circuit's template as its `main` component, including the pragma(s), an +//! `include` of the template file, and the `component main` declaration. +//! +//! This is intentionally decoupled from any config type: callers pass the +//! relevant fields via [`MainComponentSpec`], so this crate depends only on +//! `circomkit-parser` (and `serde_json` for rendering parameters). + +use std::path::Path; + +use serde_json::Value; + +/// The inputs needed to generate a circuit's `main` component file. +pub struct MainComponentSpec<'a> { + /// Template source filename (relative to `src_dir`, without extension), + /// e.g. `"multiplier"`. Included as `../.circom`. + pub file: &'a str, + /// Name of the circom template to instantiate. + pub template: &'a str, + /// Template instantiation parameters, rendered as circom literals. + pub params: &'a [Value], + /// Public input signal names (emitted as `{public[...]}` when non-empty). + pub pubs: &'a [String], + /// Whether the circuit uses `pragma custom_templates`. + pub uses_custom_templates: bool, +} + +/// Generate the circom source code for a main component. +/// +/// The generated file includes the pragma, an include directive (relative from +/// `main/` up to the circuit file), and the `component main` declaration. +pub fn make_circuit_source(spec: &MainComponentSpec<'_>, version: &str) -> String { + let mut source = String::new(); + + source.push_str("// auto-generated by circomkit\n"); + source.push_str(&format!("pragma circom {version};\n")); + + if spec.uses_custom_templates { + source.push_str("pragma custom_templates;\n"); + } + + source.push_str(&format!("include \"../{}.circom\";\n\n", spec.file)); + + // component main declaration + source.push_str("component main"); + + if !spec.pubs.is_empty() { + source.push_str(&format!(" {{public[{}]}}", spec.pubs.join(", "))); + } + + source.push_str(&format!( + " = {}({});\n", + spec.template, + spec.params + .iter() + .map(|p| p.to_string()) + .collect::>() + .join(", ") + )); + + source +} + +/// Write the main component circom file to disk. +/// +/// Creates the target directory if it doesn't exist. +pub fn instantiate_circuit( + spec: &MainComponentSpec<'_>, + target_path: &Path, + version: &str, +) -> std::io::Result<()> { + let source = make_circuit_source(spec, version); + + if let Some(parent) = target_path.parent() { + std::fs::create_dir_all(parent)?; + } + + std::fs::write(target_path, source)?; + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + #[test] + fn basic_circuit_source() { + let spec = MainComponentSpec { + file: "multiplier", + template: "Multiplier", + params: &[json!(3)], + pubs: &[], + uses_custom_templates: false, + }; + + let source = make_circuit_source(&spec, "2.1.0"); + assert!(source.contains("pragma circom 2.1.0;")); + assert!(source.contains("include \"../multiplier.circom\";")); + assert!(source.contains("component main = Multiplier(3);")); + assert!(!source.contains("custom_templates")); + } + + #[test] + fn circuit_with_public_signals() { + let spec = MainComponentSpec { + file: "arrays", + template: "Arrays", + params: &[json!(2), json!(3)], + pubs: &["in1D".to_string(), "in2D".to_string()], + uses_custom_templates: false, + }; + + let source = make_circuit_source(&spec, "2.1.0"); + assert!(source.contains("{public[in1D, in2D]}")); + assert!(source.contains("= Arrays(2, 3);")); + } + + #[test] + fn circuit_with_custom_templates() { + let spec = MainComponentSpec { + file: "custom", + template: "Custom", + params: &[], + pubs: &[], + uses_custom_templates: true, + }; + + let source = make_circuit_source(&spec, "2.1.0"); + assert!(source.contains("pragma custom_templates;")); + } +} diff --git a/crates/circomkit-codegen/src/wrapper.rs b/crates/circomkit-codegen/src/wrapper.rs new file mode 100644 index 0000000..35cef5b --- /dev/null +++ b/crates/circomkit-codegen/src/wrapper.rs @@ -0,0 +1,248 @@ +//! Tag-wrapper generation (issue #116). +//! +//! `component main` cannot have tagged inputs, so a template whose inputs carry +//! `{tag}` metadata can't be used directly as a circuit's main component. This +//! module generates a wrapper template with plain (untagged) inputs that +//! internally creates tagged intermediate signals, sets their tag values, and +//! forwards everything to the original template. +//! +//! Tag values are supplied via wrapper parameters — one parameter per distinct +//! tag name, applied to every input that carries it. Because the interface-only +//! parser cannot tell whether a tag is *valued*, every tag is treated as valued; +//! for non-valued tags the emitted `sig.tag = ...;` line can simply be removed. + +use circomkit_parser::{CircomProgram, Signal, Template}; + +use crate::CodegenError; + +/// Generate a `_wrapper` template for a template with tagged inputs. +/// +/// Returns [`CodegenError::NoTaggedInputs`] if the template has no tagged +/// inputs (in which case no wrapper is needed). +pub fn generate_tag_wrapper(template: &Template) -> Result { + generate_tag_wrapper_with_suffix(template, "_wrapper") +} + +/// Like [`generate_tag_wrapper`], but with a custom name suffix. +pub fn generate_tag_wrapper_with_suffix( + template: &Template, + suffix: &str, +) -> Result { + let inputs: Vec<&Signal> = template.inputs().collect(); + if !inputs.iter().any(|s| !s.tags.is_empty()) { + return Err(CodegenError::NoTaggedInputs(template.name.clone())); + } + + // Distinct tag names, in first-seen order — each becomes a wrapper parameter. + let mut tag_params: Vec = Vec::new(); + for s in &inputs { + for tag in &s.tags { + if !tag_params.contains(tag) { + tag_params.push(tag.clone()); + } + } + } + + // Wrapper parameters: the original template's parameters, then tag params. + let mut params = template.params.clone(); + for tag in &tag_params { + if !params.contains(tag) { + params.push(tag.clone()); + } + } + + let inner_params = template.params.join(", "); + let mut out = String::new(); + + out.push_str(&format!( + "template {}{}({}) {{\n", + template.name, + suffix, + params.join(", ") + )); + + // Plain (untagged) inputs mirroring the original template's inputs. + for s in &inputs { + out.push_str(&format!( + " signal input {}{};\n", + s.name, + dims_suffix(&s.dimensions) + )); + } + out.push('\n'); + + // Tagged intermediate signals, with tag values set and inputs connected. + for s in &inputs { + if s.tags.is_empty() { + continue; + } + out.push_str(&format!( + " signal {{{}}} {}_tagged{};\n", + s.tags.join(", "), + s.name, + dims_suffix(&s.dimensions) + )); + for tag in &s.tags { + out.push_str(&format!(" {}_tagged.{} = {};\n", s.name, tag, tag)); + } + out.push_str(&format!(" {}_tagged <== {};\n\n", s.name, s.name)); + } + + // Positional connection list in the inner template's input order. + let args: Vec = inputs.iter().copied().map(connected_name).collect(); + + let outputs: Vec<&Signal> = template.outputs().collect(); + match outputs.as_slice() { + [] => { + // No outputs: use an explicit named component and wire inputs. + out.push_str(&format!( + " component _inner = {}({});\n", + template.name, inner_params + )); + for s in inputs.iter().copied() { + out.push_str(&format!( + " _inner.{} <== {};\n", + s.name, + connected_name(s) + )); + } + } + [single] => { + out.push_str(&format!( + " signal output {}{};\n", + single.name, + dims_suffix(&single.dimensions) + )); + out.push_str(&format!( + " {} <== {}({})({});\n", + single.name, + template.name, + inner_params, + args.join(", ") + )); + } + many => { + for o in many { + out.push_str(&format!( + " signal output {}{};\n", + o.name, + dims_suffix(&o.dimensions) + )); + } + let names: Vec<&str> = many.iter().map(|o| o.name.as_str()).collect(); + out.push_str(&format!( + " ({}) <== {}({})({});\n", + names.join(", "), + template.name, + inner_params, + args.join(", ") + )); + } + } + + out.push_str("}\n"); + Ok(out) +} + +/// Generate wrappers for every template in a program that has tagged inputs. +pub fn generate_tag_wrappers(program: &CircomProgram) -> Vec { + program + .templates + .iter() + .filter_map(|t| generate_tag_wrapper(t).ok()) + .collect() +} + +/// The signal name used when connecting an input to the inner template: +/// the tagged intermediate if the input is tagged, otherwise the input itself. +fn connected_name(s: &Signal) -> String { + if s.tags.is_empty() { + s.name.clone() + } else { + format!("{}_tagged", s.name) + } +} + +/// Render array dimensions as circom bracket suffixes, e.g. `["N", "M"]` -> `[N][M]`. +fn dims_suffix(dims: &[String]) -> String { + dims.iter().map(|d| format!("[{d}]")).collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + fn template(src: &str, name: &str) -> Template { + circomkit_parser::parse(src) + .unwrap() + .template(name) + .unwrap() + .clone() + } + + #[test] + fn wraps_bounded_add() { + let src = r#" + template BoundedAdd() { + signal input {maxbits} a; + signal input {maxbits} b; + signal output out; + } + "#; + let w = generate_tag_wrapper(&template(src, "BoundedAdd")).unwrap(); + + assert!(w.contains("template BoundedAdd_wrapper(maxbits) {")); + assert!(w.contains("signal input a;")); + assert!(w.contains("signal input b;")); + assert!(w.contains("signal {maxbits} a_tagged;")); + assert!(w.contains("a_tagged.maxbits = maxbits;")); + assert!(w.contains("a_tagged <== a;")); + assert!(w.contains("signal output out;")); + assert!(w.contains("out <== BoundedAdd()(a_tagged, b_tagged);")); + } + + #[test] + fn keeps_original_params_and_array_dims() { + let src = r#" + template Foo(n) { + signal input {binary} in[n]; + signal input plain; + signal output out; + } + "#; + let w = generate_tag_wrapper(&template(src, "Foo")).unwrap(); + + // original param `n` precedes the tag param `binary` + assert!(w.contains("template Foo_wrapper(n, binary) {")); + assert!(w.contains("signal input in[n];")); + assert!(w.contains("signal {binary} in_tagged[n];")); + // untagged input is forwarded directly + assert!(w.contains("signal input plain;")); + assert!(w.contains("out <== Foo(n)(in_tagged, plain);")); + } + + #[test] + fn multiple_outputs_use_tuple_assignment() { + let src = r#" + template Split() { + signal input {maxbits} x; + signal output lo; + signal output hi; + } + "#; + let w = generate_tag_wrapper(&template(src, "Split")).unwrap(); + assert!(w.contains("(lo, hi) <== Split()(x_tagged);")); + } + + #[test] + fn errors_without_tagged_inputs() { + let src = r#" + template Plain() { + signal input a; + signal output b; + } + "#; + let err = generate_tag_wrapper(&template(src, "Plain")).unwrap_err(); + assert!(matches!(err, CodegenError::NoTaggedInputs(_))); + } +} diff --git a/crates/circomkit-core/src/functions/instantiate.rs b/crates/circomkit-core/src/functions/instantiate.rs deleted file mode 100644 index dff757e..0000000 --- a/crates/circomkit-core/src/functions/instantiate.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::path::Path; - -use crate::config::CircuitConfig; -use crate::error::Result; - -/// Generate the circom source code for a main component. -/// -/// The generated file includes the pragma, an include directive -/// (relative from `main/` up to the circuit file), and the -/// `component main` declaration. -pub fn make_circuit_source(config: &CircuitConfig, version: &str) -> String { - let mut source = String::new(); - - source.push_str("// auto-generated by circomkit\n"); - source.push_str(&format!("pragma circom {version};\n")); - - if config.uses_custom_templates { - source.push_str("pragma custom_templates;\n"); - } - - source.push_str(&format!("include \"../{}.circom\";\n\n", config.file)); - - // component main declaration - source.push_str("component main"); - - if !config.pubs.is_empty() { - source.push_str(&format!(" {{public[{}]}}", config.pubs.join(", "))); - } - - source.push_str(&format!( - " = {}({});\n", - config.template, - config - .params - .iter() - .map(|p| p.to_string()) - .collect::>() - .join(", ") - )); - - source -} - -/// Write the main component circom file to disk. -/// -/// Creates the target directory if it doesn't exist. -pub fn instantiate_circuit( - config: &CircuitConfig, - target_path: &Path, - version: &str, -) -> Result<()> { - let source = make_circuit_source(config, version); - - if let Some(parent) = target_path.parent() { - std::fs::create_dir_all(parent)?; - } - - std::fs::write(target_path, source)?; - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn basic_circuit_source() { - let config = CircuitConfig { - file: "multiplier".to_string(), - template: "Multiplier".to_string(), - pubs: vec![], - params: vec![serde_json::json!(3)], - uses_custom_templates: false, - overrides: None, - }; - - let source = make_circuit_source(&config, "2.1.0"); - assert!(source.contains("pragma circom 2.1.0;")); - assert!(source.contains("include \"../multiplier.circom\";")); - assert!(source.contains("component main = Multiplier(3);")); - assert!(!source.contains("custom_templates")); - } - - #[test] - fn circuit_with_public_signals() { - let config = CircuitConfig { - file: "arrays".to_string(), - template: "Arrays".to_string(), - pubs: vec!["in1D".to_string(), "in2D".to_string()], - params: vec![serde_json::json!(2), serde_json::json!(3)], - uses_custom_templates: false, - overrides: None, - }; - - let source = make_circuit_source(&config, "2.1.0"); - assert!(source.contains("{public[in1D, in2D]}")); - assert!(source.contains("= Arrays(2, 3);")); - } - - #[test] - fn circuit_with_custom_templates() { - let config = CircuitConfig { - file: "custom".to_string(), - template: "Custom".to_string(), - pubs: vec![], - params: vec![], - uses_custom_templates: true, - overrides: None, - }; - - let source = make_circuit_source(&config, "2.1.0"); - assert!(source.contains("pragma custom_templates;")); - } -} diff --git a/crates/circomkit-core/src/functions/mod.rs b/crates/circomkit-core/src/functions/mod.rs index a8020cc..d926124 100644 --- a/crates/circomkit-core/src/functions/mod.rs +++ b/crates/circomkit-core/src/functions/mod.rs @@ -1,11 +1,9 @@ mod calldata; mod compile; -mod instantiate; mod symbols; pub use calldata::get_calldata; pub use compile::{CompileOutput, compile_circuit}; -pub use instantiate::{instantiate_circuit, make_circuit_source}; pub use symbols::{ edit_witness, parse_symbols, parse_symbols_str, read_witness_raw, read_witness_signals, }; diff --git a/crates/circomkit-parser/Cargo.toml b/crates/circomkit-parser/Cargo.toml new file mode 100644 index 0000000..79dc1c9 --- /dev/null +++ b/crates/circomkit-parser/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "circomkit-parser" +description = "Lightweight parser for Circom source interfaces (templates, signals, tags) used for codegen" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +pest.workspace = true +pest_derive.workspace = true +thiserror.workspace = true +serde = { workspace = true, optional = true } + +[features] +default = [] +# Derive serde on the AST types (useful for codegen / bindings that emit JSON). +serde = ["dep:serde"] diff --git a/crates/circomkit-parser/src/ast.rs b/crates/circomkit-parser/src/ast.rs new file mode 100644 index 0000000..bc3c42b --- /dev/null +++ b/crates/circomkit-parser/src/ast.rs @@ -0,0 +1,127 @@ +//! Abstract syntax tree for the Circom *interface* subset. +//! +//! These types capture only what codegen needs: template names/params, signal +//! directions/tags/dimensions, pragmas, includes, and the `main` component. + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// A parsed Circom source file, reduced to its interface. +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct CircomProgram { + /// `pragma` directives, in source order. + pub pragmas: Vec, + /// `include "..."` paths, in source order. + pub includes: Vec, + /// Template definitions, in source order. + pub templates: Vec