├── .dockerignore ├── .editorconfig ├── .gitignore ├── Dockerfile ├── README.md ├── attestation.template.md ├── docker-compose.yml ├── package-lock.json ├── package.json ├── scripts └── git-snapshot.sh ├── ts ├── attest.ts ├── contribute.ts ├── download.ts ├── index.ts ├── init.ts ├── upload.ts ├── utils.ts └── verify.ts ├── tsconfig.json └── zkeys ├── Hasher_2.test.0.zkey └── Hasher_3.prod.0.zkey /.dockerignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | **/node_modules 3 | **/build 4 | .git/ 5 | scripts/git-snapshot.sh 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # All files 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_size = 4 11 | indent_style = space 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | [*.{json,yml,md}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | contribution/* 2 | 3 | docs/book/* 4 | 5 | input.*.json 6 | *.wtns 7 | proof.json 8 | benchmarks/ 9 | **/build/ 10 | node_modules 11 | 12 | .DS_Store 13 | 14 | .vscode/ 15 | 16 | _build/ 17 | 18 | # Logs 19 | logs 20 | *.log 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | lerna-debug.log* 25 | 26 | # Diagnostic reports (https://nodejs.org/api/report.html) 27 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 28 | 29 | # Runtime data 30 | pids 31 | *.pid 32 | *.seed 33 | *.pid.lock 34 | 35 | # Directory for instrumented libs generated by jscoverage/JSCover 36 | lib-cov 37 | 38 | # Coverage directory used by tools like istanbul 39 | coverage 40 | *.lcov 41 | 42 | # nyc test coverage 43 | .nyc_output 44 | 45 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 46 | .grunt 47 | 48 | # Bower dependency directory (https://bower.io/) 49 | bower_components 50 | 51 | # node-waf configuration 52 | .lock-wscript 53 | 54 | # Compiled binary addons (https://nodejs.org/api/addons.html) 55 | build/Release 56 | 57 | # Dependency directories 58 | jspm_packages/ 59 | 60 | # TypeScript v1 declaration files 61 | typings/ 62 | 63 | # TypeScript cache 64 | *.tsbuildinfo 65 | 66 | # Optional npm cache directory 67 | .npm 68 | 69 | # Optional eslint cache 70 | .eslintcache 71 | 72 | # Optional REPL history 73 | .node_repl_history 74 | 75 | # Output of 'npm pack' 76 | *.tgz 77 | 78 | # Yarn Integrity file 79 | .yarn-integrity 80 | 81 | # dotenv environment variables file 82 | .env 83 | .env.test 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | 88 | # next.js build output 89 | .next 90 | 91 | # nuxt.js build output 92 | .nuxt 93 | 94 | # vuepress build output 95 | .vuepress/dist 96 | 97 | # Serverless directories 98 | .serverless/ 99 | 100 | # FuseBox cache 101 | .fusebox/ 102 | 103 | # DynamoDB Local files 104 | .dynamodb/ 105 | 106 | # Snapshot of git state to embed within Docker image 107 | .gitsnapshot/ 108 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:15.8.0-buster 2 | 3 | RUN rm /bin/sh && ln -s /bin/bash /bin/sh 4 | 5 | RUN wget -q https://dist.ipfs.io/go-ipfs/v0.8.0/go-ipfs_v0.8.0_linux-amd64.tar.gz && \ 6 | tar -xvzf go-ipfs_v0.8.0_linux-amd64.tar.gz && \ 7 | cd go-ipfs && \ 8 | bash install.sh 9 | 10 | WORKDIR /multisetups 11 | COPY . /multisetups/ 12 | RUN npm i 13 | 14 | CMD rm -rf /root/.ipfs2 && \ 15 | mkdir -p /root/.ipfs && \ 16 | mv /root/.ipfs /root/.ipfs2 && \ 17 | ipfs init -e && \ 18 | mv /root/.ipfs2 /root/.ipfs && \ 19 | ipfs daemon 20 | 21 | ENV CEREMONY ${CEREMONY} 22 | ENV GIT_HEAD ${GIT_HEAD} 23 | ENV GIT_HEAD_NAME ${GIT_HEAD_NAME} 24 | ENV GIT_UPSTREAM ${GIT_UPSTREAM} 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # multisetups 2 | 3 | For production use, Groth16 zk-SNARK circuits require a multi-party trusted 4 | setup to generate the proving and verifying key fo reach circuit, while 5 | reducing the probability that the toxic waste associated with the keys has been 6 | retained. While there already exist ([1](https://github.com/briangu33/Setup), 7 | [2](https://github.com/glamperd/setup-mpc-ui), 8 | [3](https://github.com/celo-org/snark-setup/)) which help teams to automate 9 | this process, so far none exist that support this combination of requirements: 10 | 11 | 1. Multiple circuits per ceremony (e.g. [MACI](https://github.com/appliedzkp/maci)) 12 | 2. Large circuits (more than 1 million constraints) that cannot be set up in a 13 | browser 14 | 15 | The `multisetups` utility seeks to meet them with the following goals in mind: 16 | 17 | 1. Simplicity: 18 | 19 | - Rather than automate away the role of a central coordinator, a 20 | coordinator is needed to verify contributions and pass the baton on to 21 | the next participant. Moreover, doing so reduces the time and cost of 22 | development. 23 | 24 | 2. Ease of use for contributors: 25 | 26 | - Contributors should only have to run a few commands to participate in 27 | the ceremony. Moreover, the software will be Dockerised for maximum 28 | ease-of-use. 29 | 30 | 3. Low infrastructure overhead: 31 | 32 | - Contribution files should be transferred via IPFS, so it is not necessary 33 | to provision cloud machines for the ceremony. As long as the coordinator 34 | has high bandwidth and storage, they can run the ceremony from their own 35 | machine. 36 | 37 | ## Requirements 38 | 39 | You need IPFS installed in your `$PATH` and you should run `ipfs daemon` in a 40 | separate terminal. This allows the coordinator and participants to easily share 41 | `.zkey` files. 42 | 43 | ## Quick start with Docker 44 | 45 | ```bash 46 | git clone git@github.com:weijiekoh/multisetups.git && 47 | cd multisetups && 48 | source scripts/git-snapshot.sh && 49 | docker-compose build && 50 | docker-compose up 51 | ``` 52 | 53 | To create a new ceremony with the sample `.zkey` files: 54 | 55 | ``` 56 | docker-compose exec multisetups node build/index.js init -d /multisetups/zkeys 57 | Ceremony initialised. Please give this multihash to the first participant and keep your IPFS node running and connected to the IPFS network. 58 | Qmeg59hpYk82DYmdupTgYTuZNedLeTKBJNQ2r38EpUqgYn 59 | ``` 60 | 61 | To download the ceremony files as a contributor: 62 | 63 | ``` 64 | docker-compose exec multisetups node build/index.js download -m Qmeg59hpYk82DYmdupTgYTuZNedLeTKBJNQ2r38EpUqgYn -d /ceremony/old 65 | 66 | Saving file(s) to /ceremony/old 67 | 247.36 KiB / 247.36 KiB [========================================] 100.00% 0s 68 | ``` 69 | To contribute: 70 | 71 | ``` 72 | docker-compose exec multisetups node build/index.js contribute -d /ceremony/old -n /ceremony/new 73 | 74 | Contribution generated, and transcript written to /ceremony/new/transcript.1.txt. 75 | Please run the 'attest' command next. 76 | ``` 77 | 78 | To generate an attestation file: 79 | 80 | ``` 81 | docker-compose exec multisetups node build/index.js attest -d /ceremony/new -t attestation.template.md 82 | 83 | Wrote prepopulated attestation to /ceremony/new/attestation.1.md. 84 | Please edit this file, sign it, and run the 'upload' subcommand. 85 | ``` 86 | 87 | To upload the contribution: 88 | 89 | ``` 90 | docker-compose exec multisetups node build/index.js upload -d /ceremony/new 91 | 92 | Contribution uploaded. Please send this multihash to the coordinator and keep your IPFS node running and connected to the IPFS network. 93 | QmYDsgWYRuHNYBeJABGZ6Csdj256jvj4E4WYX2dJ6w6iCj 94 | ``` 95 | 96 | ## Installation 97 | 98 | ```bash 99 | git clone git@github.com:weijiekoh/multisetups.git && 100 | cd multisetups && 101 | npm i 102 | ``` 103 | 104 | ## Creating a new ceremony 105 | 106 | First, create a `zkeys` directory and store all your `.zkey` files in it. You 107 | can use [`zkey-manager`](https://github.com/appliedzkp/zkey-manager) to create 108 | them. 109 | 110 | Next, run: 111 | 112 | ``` 113 | node build/index.js init -d zkeys 114 | ``` 115 | 116 | You should see something like this: 117 | 118 | ``` 119 | Ceremony initialised. Please give this multihash to the first participant and keep your IPFS node running and connected to the IPFS network. 120 | Qmeg59hpYk82DYmdupTgYTuZNedLeTKBJNQ2r38EpUqgYn 121 | ``` 122 | 123 | ## Contributing to a ceremony 124 | 125 | First, download the `.zkey` files: 126 | 127 | ``` 128 | node build/index.js download -d ./old -m . 129 | ``` 130 | 131 | Next, perform the contribution. This may take a long time. It should ideally be 132 | done on an airgapped computer. 133 | 134 | ``` 135 | node build/index.js contribute -m -d ./old -n ./new 136 | ``` 137 | 138 | Generate an attestation file: 139 | 140 | ``` 141 | node build/index.js attest -d ./new -t attestation.template.md 142 | ``` 143 | 144 | Edit this attestation file to fill out the missing info, and sign it. 145 | 146 | Finally, upload the files: 147 | 148 | ``` 149 | node build/index.js upload -n ./new 150 | ``` 151 | -------------------------------------------------------------------------------- /attestation.template.md: -------------------------------------------------------------------------------- 1 | # Attestation of contribution to trusted setup ceremony 2 | 3 | {{#if ceremony}}Ceremony: {{ceremony}} 4 | 5 | {{/if}} 14 | 15 | ## Context 16 | 17 | Contributor name: **INSERT NAME HERE** 18 | Date: {{date}} {{time}} 19 | Geographic location: **INSERT LOCATION HERE** 20 | Time taken: **e.g. "~30 minutes"** 21 | 22 | ## Hardware used 23 | 24 | Device(s): **SPECIFY MACHINE USED, E.G. HARDWARE** 25 | CPU architecture: {{os.arch}} 26 | CPU model: {{cpu.model}} 27 | CPU logical cores: {{cpu.cores}} 28 | CPU bugs: {{cpu.bugs}} 29 | Memory: {{mem.total}}MB 30 | 31 | ## Software used 32 | 33 | OS type: {{os.type}} 34 | OS platform: {{os.platform}} 35 | OS version: {{os.version}} 36 | Uptime: {{uptime}} 37 | Repository upstream: {{repo.upstream}} 38 | Repository commit: {{repo.head}} ({{repo.head_name}}) 39 | 40 | ## Transcript 41 | 42 | ``` 43 | {{transcript}} 44 | ``` 45 | 46 | ## Entropy sources 47 | 48 | - [ ] mashed keyboard to generate random string 49 | - [ ] bytes from /dev/urandom from machine ... 50 | - [ ] webcam 51 | - [ ] audio input 52 | - [ ] Geiger counter 53 | - [ ] random words from random books 54 | - [ ] asked people for random numbers / words 55 | 56 | ## Side channel defenses 57 | 58 | - [ ] Left other processes running 59 | - [ ] Didn't use swap space 60 | - [ ] Ran the software on secure hardware 61 | - [ ] Didn't tell anyone except coordinator about participation in advance 62 | 63 | ## Other defenses 64 | 65 | - [ ] Disconnected network during generation of contribution 66 | - [ ] Rebooted with airgap before generation of contribution 67 | - [ ] Full disk encryption 68 | - [ ] Put the machine in a Faraday cage 69 | - [ ] Used multiple machines and randomly picked the result of one of them 70 | - [ ] Ensured no one could see the screen 71 | 72 | ## Post processing 73 | 74 | - [ ] Filled up memory with memtester 75 | - [ ] Rebooted the machine 76 | - [ ] Power-cycled the machine 77 | - [ ] Wiped the storage drive 78 | - [ ] Destroyed the machine after (!) 79 | 80 | ## Sharing of results 81 | 82 | I intend to share the files: 83 | 84 | - [ ] via IPFS using multisetups 85 | - [ ] via GitHub PR 86 | - [ ] via `magic-wormhole` 87 | - [ ] via **INSERT CLOUD STORAGE HERE** 88 | 89 | ## Any other comments (optional) 90 | 91 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | multisetups: 4 | build: 5 | context: ./ 6 | volumes: 7 | - type: bind 8 | target: /ceremony 9 | source: ${CEREMONY_DIR:-./ceremony} 10 | ports: 11 | - "4001:4001" 12 | - "5001:5001" 13 | - "8080:8080" 14 | 15 | volumes: 16 | ceremony: 17 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multisetups", 3 | "version": "0.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "multisetups", 9 | "version": "0.0.1", 10 | "license": "MIT", 11 | "dependencies": { 12 | "argparse": "2.0.1", 13 | "handlebars": "^4.7.7", 14 | "js-yaml": "4.0.0", 15 | "shelljs": "0.8.4", 16 | "snarkjs": "0.3.59" 17 | }, 18 | "bin": { 19 | "multisetups": "build/index.js" 20 | }, 21 | "devDependencies": { 22 | "@types/jest": "26.0.19", 23 | "typescript": "4.1.3" 24 | } 25 | }, 26 | "node_modules/@iden3/bigarray": { 27 | "version": "0.0.2", 28 | "resolved": "https://registry.npmjs.org/@iden3/bigarray/-/bigarray-0.0.2.tgz", 29 | "integrity": "sha512-Xzdyxqm1bOFF6pdIsiHLLl3HkSLjbhqJHVyqaTxXt3RqXBEnmsUmEW47H7VOi/ak7TdkRpNkxjyK5Zbkm+y52g==" 30 | }, 31 | "node_modules/@iden3/binfileutils": { 32 | "version": "0.0.8", 33 | "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.8.tgz", 34 | "integrity": "sha512-/GqTsujUssGuQY+sd/XaLrA+OiCwzm+6yH28C57QQDWCHET2Logry9fGxU10n6XKdhCQBjZ7T/YMQkLwwkpRTQ==", 35 | "dependencies": { 36 | "fastfile": "0.0.19", 37 | "ffjavascript": "^0.2.30" 38 | } 39 | }, 40 | "node_modules/@jest/types": { 41 | "version": "26.6.2", 42 | "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", 43 | "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", 44 | "dev": true, 45 | "dependencies": { 46 | "@types/istanbul-lib-coverage": "^2.0.0", 47 | "@types/istanbul-reports": "^3.0.0", 48 | "@types/node": "*", 49 | "@types/yargs": "^15.0.0", 50 | "chalk": "^4.0.0" 51 | }, 52 | "engines": { 53 | "node": ">= 10.14.2" 54 | } 55 | }, 56 | "node_modules/@types/istanbul-lib-coverage": { 57 | "version": "2.0.3", 58 | "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", 59 | "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", 60 | "dev": true 61 | }, 62 | "node_modules/@types/istanbul-lib-report": { 63 | "version": "3.0.0", 64 | "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", 65 | "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", 66 | "dev": true, 67 | "dependencies": { 68 | "@types/istanbul-lib-coverage": "*" 69 | } 70 | }, 71 | "node_modules/@types/istanbul-reports": { 72 | "version": "3.0.0", 73 | "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", 74 | "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", 75 | "dev": true, 76 | "dependencies": { 77 | "@types/istanbul-lib-report": "*" 78 | } 79 | }, 80 | "node_modules/@types/jest": { 81 | "version": "26.0.19", 82 | "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.19.tgz", 83 | "integrity": "sha512-jqHoirTG61fee6v6rwbnEuKhpSKih0tuhqeFbCmMmErhtu3BYlOZaXWjffgOstMM4S/3iQD31lI5bGLTrs97yQ==", 84 | "dev": true, 85 | "dependencies": { 86 | "jest-diff": "^26.0.0", 87 | "pretty-format": "^26.0.0" 88 | } 89 | }, 90 | "node_modules/@types/node": { 91 | "version": "14.14.31", 92 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", 93 | "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", 94 | "dev": true 95 | }, 96 | "node_modules/@types/yargs": { 97 | "version": "15.0.13", 98 | "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", 99 | "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==", 100 | "dev": true, 101 | "dependencies": { 102 | "@types/yargs-parser": "*" 103 | } 104 | }, 105 | "node_modules/@types/yargs-parser": { 106 | "version": "20.2.0", 107 | "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", 108 | "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", 109 | "dev": true 110 | }, 111 | "node_modules/ansi-regex": { 112 | "version": "5.0.0", 113 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 114 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 115 | "dev": true, 116 | "engines": { 117 | "node": ">=8" 118 | } 119 | }, 120 | "node_modules/ansi-styles": { 121 | "version": "4.3.0", 122 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 123 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 124 | "dev": true, 125 | "dependencies": { 126 | "color-convert": "^2.0.1" 127 | }, 128 | "engines": { 129 | "node": ">=8" 130 | }, 131 | "funding": { 132 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 133 | } 134 | }, 135 | "node_modules/argparse": { 136 | "version": "2.0.1", 137 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 138 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" 139 | }, 140 | "node_modules/balanced-match": { 141 | "version": "1.0.0", 142 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 143 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 144 | }, 145 | "node_modules/big-integer": { 146 | "version": "1.6.48", 147 | "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", 148 | "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", 149 | "engines": { 150 | "node": ">=0.6" 151 | } 152 | }, 153 | "node_modules/blake2b-wasm": { 154 | "version": "2.1.0", 155 | "resolved": "git+ssh://git@github.com/jbaylina/blake2b-wasm.git#0d5f024b212429c7f50a7f533aa3a2406b5b42b3", 156 | "license": "MIT", 157 | "dependencies": { 158 | "nanoassert": "^1.0.0" 159 | } 160 | }, 161 | "node_modules/blakejs": { 162 | "version": "1.1.0", 163 | "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", 164 | "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" 165 | }, 166 | "node_modules/brace-expansion": { 167 | "version": "1.1.11", 168 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 169 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 170 | "dependencies": { 171 | "balanced-match": "^1.0.0", 172 | "concat-map": "0.0.1" 173 | } 174 | }, 175 | "node_modules/chalk": { 176 | "version": "4.1.0", 177 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 178 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 179 | "dev": true, 180 | "dependencies": { 181 | "ansi-styles": "^4.1.0", 182 | "supports-color": "^7.1.0" 183 | }, 184 | "engines": { 185 | "node": ">=10" 186 | }, 187 | "funding": { 188 | "url": "https://github.com/chalk/chalk?sponsor=1" 189 | } 190 | }, 191 | "node_modules/circom_runtime": { 192 | "version": "0.1.13", 193 | "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.13.tgz", 194 | "integrity": "sha512-vmv19/0p5OTe5uCI7PWqPtB5vPoYWjczqKYnabaC5HOxX99R4K1MuNqEXsNEAoEfZrmfAQd7vXLcATN9NVnsPA==", 195 | "dependencies": { 196 | "ffjavascript": "0.2.35", 197 | "fnv-plus": "^1.3.1" 198 | }, 199 | "bin": { 200 | "calcwit": "calcwit.js" 201 | } 202 | }, 203 | "node_modules/color-convert": { 204 | "version": "2.0.1", 205 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 206 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 207 | "dev": true, 208 | "dependencies": { 209 | "color-name": "~1.1.4" 210 | }, 211 | "engines": { 212 | "node": ">=7.0.0" 213 | } 214 | }, 215 | "node_modules/color-name": { 216 | "version": "1.1.4", 217 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 218 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 219 | "dev": true 220 | }, 221 | "node_modules/concat-map": { 222 | "version": "0.0.1", 223 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 224 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 225 | }, 226 | "node_modules/diff-sequences": { 227 | "version": "26.6.2", 228 | "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", 229 | "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", 230 | "dev": true, 231 | "engines": { 232 | "node": ">= 10.14.2" 233 | } 234 | }, 235 | "node_modules/fastfile": { 236 | "version": "0.0.19", 237 | "resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.19.tgz", 238 | "integrity": "sha512-tz9nWR5KYb6eR2odFQ7oxqEkx8F3YQZ6NBJoJR92YEG3DqYOqyxMck8PKvTVNKx3uwvOqGnLXNScnqpdHRdHGQ==" 239 | }, 240 | "node_modules/ffjavascript": { 241 | "version": "0.2.35", 242 | "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.35.tgz", 243 | "integrity": "sha512-xnC51tWbi0ah4SH+02jEfJyO+P+NiZWnxQrLDLtBYY1Dv3QM5ydxzd+gxnLEfWdT8i1bMM5pIh5P25l6fNCaVQ==", 244 | "dependencies": { 245 | "big-integer": "^1.6.48", 246 | "wasmcurves": "0.0.14", 247 | "web-worker": "^1.0.0" 248 | } 249 | }, 250 | "node_modules/fnv-plus": { 251 | "version": "1.3.1", 252 | "resolved": "https://registry.npmjs.org/fnv-plus/-/fnv-plus-1.3.1.tgz", 253 | "integrity": "sha512-Gz1EvfOneuFfk4yG458dJ3TLJ7gV19q3OM/vVvvHf7eT02Hm1DleB4edsia6ahbKgAYxO9gvyQ1ioWZR+a00Yw==" 254 | }, 255 | "node_modules/fs.realpath": { 256 | "version": "1.0.0", 257 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 258 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 259 | }, 260 | "node_modules/function-bind": { 261 | "version": "1.1.1", 262 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 263 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 264 | }, 265 | "node_modules/glob": { 266 | "version": "7.1.6", 267 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 268 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 269 | "dependencies": { 270 | "fs.realpath": "^1.0.0", 271 | "inflight": "^1.0.4", 272 | "inherits": "2", 273 | "minimatch": "^3.0.4", 274 | "once": "^1.3.0", 275 | "path-is-absolute": "^1.0.0" 276 | }, 277 | "engines": { 278 | "node": "*" 279 | }, 280 | "funding": { 281 | "url": "https://github.com/sponsors/isaacs" 282 | } 283 | }, 284 | "node_modules/handlebars": { 285 | "version": "4.7.7", 286 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", 287 | "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", 288 | "dependencies": { 289 | "minimist": "^1.2.5", 290 | "neo-async": "^2.6.0", 291 | "source-map": "^0.6.1", 292 | "wordwrap": "^1.0.0" 293 | }, 294 | "bin": { 295 | "handlebars": "bin/handlebars" 296 | }, 297 | "engines": { 298 | "node": ">=0.4.7" 299 | }, 300 | "optionalDependencies": { 301 | "uglify-js": "^3.1.4" 302 | } 303 | }, 304 | "node_modules/has": { 305 | "version": "1.0.3", 306 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 307 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 308 | "dependencies": { 309 | "function-bind": "^1.1.1" 310 | }, 311 | "engines": { 312 | "node": ">= 0.4.0" 313 | } 314 | }, 315 | "node_modules/has-flag": { 316 | "version": "4.0.0", 317 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 318 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 319 | "dev": true, 320 | "engines": { 321 | "node": ">=8" 322 | } 323 | }, 324 | "node_modules/inflight": { 325 | "version": "1.0.6", 326 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 327 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 328 | "dependencies": { 329 | "once": "^1.3.0", 330 | "wrappy": "1" 331 | } 332 | }, 333 | "node_modules/inherits": { 334 | "version": "2.0.4", 335 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 336 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 337 | }, 338 | "node_modules/interpret": { 339 | "version": "1.4.0", 340 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", 341 | "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", 342 | "engines": { 343 | "node": ">= 0.10" 344 | } 345 | }, 346 | "node_modules/is-core-module": { 347 | "version": "2.2.0", 348 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", 349 | "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", 350 | "dependencies": { 351 | "has": "^1.0.3" 352 | }, 353 | "funding": { 354 | "url": "https://github.com/sponsors/ljharb" 355 | } 356 | }, 357 | "node_modules/jest-diff": { 358 | "version": "26.6.2", 359 | "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", 360 | "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", 361 | "dev": true, 362 | "dependencies": { 363 | "chalk": "^4.0.0", 364 | "diff-sequences": "^26.6.2", 365 | "jest-get-type": "^26.3.0", 366 | "pretty-format": "^26.6.2" 367 | }, 368 | "engines": { 369 | "node": ">= 10.14.2" 370 | } 371 | }, 372 | "node_modules/jest-get-type": { 373 | "version": "26.3.0", 374 | "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", 375 | "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", 376 | "dev": true, 377 | "engines": { 378 | "node": ">= 10.14.2" 379 | } 380 | }, 381 | "node_modules/js-yaml": { 382 | "version": "4.0.0", 383 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", 384 | "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", 385 | "dependencies": { 386 | "argparse": "^2.0.1" 387 | }, 388 | "bin": { 389 | "js-yaml": "bin/js-yaml.js" 390 | } 391 | }, 392 | "node_modules/logplease": { 393 | "version": "1.2.15", 394 | "resolved": "https://registry.npmjs.org/logplease/-/logplease-1.2.15.tgz", 395 | "integrity": "sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==" 396 | }, 397 | "node_modules/minimatch": { 398 | "version": "3.0.4", 399 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 400 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 401 | "dependencies": { 402 | "brace-expansion": "^1.1.7" 403 | }, 404 | "engines": { 405 | "node": "*" 406 | } 407 | }, 408 | "node_modules/minimist": { 409 | "version": "1.2.5", 410 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 411 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 412 | }, 413 | "node_modules/nanoassert": { 414 | "version": "1.1.0", 415 | "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", 416 | "integrity": "sha1-TzFS4JVA/eKMdvRLGbvNHVpCR40=" 417 | }, 418 | "node_modules/neo-async": { 419 | "version": "2.6.2", 420 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", 421 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" 422 | }, 423 | "node_modules/once": { 424 | "version": "1.4.0", 425 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 426 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 427 | "dependencies": { 428 | "wrappy": "1" 429 | } 430 | }, 431 | "node_modules/path-is-absolute": { 432 | "version": "1.0.1", 433 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 434 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 435 | "engines": { 436 | "node": ">=0.10.0" 437 | } 438 | }, 439 | "node_modules/path-parse": { 440 | "version": "1.0.6", 441 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 442 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 443 | }, 444 | "node_modules/pretty-format": { 445 | "version": "26.6.2", 446 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", 447 | "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", 448 | "dev": true, 449 | "dependencies": { 450 | "@jest/types": "^26.6.2", 451 | "ansi-regex": "^5.0.0", 452 | "ansi-styles": "^4.0.0", 453 | "react-is": "^17.0.1" 454 | }, 455 | "engines": { 456 | "node": ">= 10" 457 | } 458 | }, 459 | "node_modules/r1csfile": { 460 | "version": "0.0.32", 461 | "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.32.tgz", 462 | "integrity": "sha512-DkRXeOg0iRmfhgIuWICvdkOiLHpyb7+AcUd/WHpqBJEUp27pe7wKXBR4Jr3TPYCT4sTV9a/F3bovyAC4wystnQ==", 463 | "dependencies": { 464 | "@iden3/bigarray": "0.0.2", 465 | "@iden3/binfileutils": "0.0.8", 466 | "fastfile": "0.0.19", 467 | "ffjavascript": "0.2.35" 468 | } 469 | }, 470 | "node_modules/react-is": { 471 | "version": "17.0.1", 472 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz", 473 | "integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==", 474 | "dev": true 475 | }, 476 | "node_modules/rechoir": { 477 | "version": "0.6.2", 478 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 479 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 480 | "dependencies": { 481 | "resolve": "^1.1.6" 482 | }, 483 | "engines": { 484 | "node": ">= 0.10" 485 | } 486 | }, 487 | "node_modules/resolve": { 488 | "version": "1.20.0", 489 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 490 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 491 | "dependencies": { 492 | "is-core-module": "^2.2.0", 493 | "path-parse": "^1.0.6" 494 | }, 495 | "funding": { 496 | "url": "https://github.com/sponsors/ljharb" 497 | } 498 | }, 499 | "node_modules/shelljs": { 500 | "version": "0.8.4", 501 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", 502 | "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", 503 | "dependencies": { 504 | "glob": "^7.0.0", 505 | "interpret": "^1.0.0", 506 | "rechoir": "^0.6.2" 507 | }, 508 | "bin": { 509 | "shjs": "bin/shjs" 510 | }, 511 | "engines": { 512 | "node": ">=4" 513 | } 514 | }, 515 | "node_modules/snarkjs": { 516 | "version": "0.3.59", 517 | "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.3.59.tgz", 518 | "integrity": "sha512-fj8EOtziIz6FvNmcT97L4QM+QNzoCf8zTo4ghpYY4wFf0ZkgX9tSR2SZy1BjtaQnlC+LiF55wOG+jucP9Aw5BA==", 519 | "dependencies": { 520 | "@iden3/binfileutils": "0.0.8", 521 | "blake2b-wasm": "git+https://github.com/jbaylina/blake2b-wasm.git", 522 | "circom_runtime": "0.1.13", 523 | "fastfile": "0.0.19", 524 | "ffjavascript": "0.2.35", 525 | "logplease": "^1.2.15", 526 | "r1csfile": "0.0.32" 527 | }, 528 | "bin": { 529 | "snarkjs": "build/cli.cjs" 530 | } 531 | }, 532 | "node_modules/source-map": { 533 | "version": "0.6.1", 534 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 535 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 536 | "engines": { 537 | "node": ">=0.10.0" 538 | } 539 | }, 540 | "node_modules/supports-color": { 541 | "version": "7.2.0", 542 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 543 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 544 | "dev": true, 545 | "dependencies": { 546 | "has-flag": "^4.0.0" 547 | }, 548 | "engines": { 549 | "node": ">=8" 550 | } 551 | }, 552 | "node_modules/typescript": { 553 | "version": "4.1.3", 554 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", 555 | "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", 556 | "dev": true, 557 | "bin": { 558 | "tsc": "bin/tsc", 559 | "tsserver": "bin/tsserver" 560 | }, 561 | "engines": { 562 | "node": ">=4.2.0" 563 | } 564 | }, 565 | "node_modules/uglify-js": { 566 | "version": "3.14.3", 567 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", 568 | "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", 569 | "optional": true, 570 | "bin": { 571 | "uglifyjs": "bin/uglifyjs" 572 | }, 573 | "engines": { 574 | "node": ">=0.8.0" 575 | } 576 | }, 577 | "node_modules/wasmcurves": { 578 | "version": "0.0.14", 579 | "resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.0.14.tgz", 580 | "integrity": "sha512-G1iMkxlRaQSdqQ1JrwHcU+awLmwyH6kFKfT8g9obd8MWe+u5oSdFXrODB0zmSI5aGGvJPG+4cAmqCGYv9R+7qg==", 581 | "dependencies": { 582 | "big-integer": "^1.6.42", 583 | "blakejs": "^1.1.0" 584 | } 585 | }, 586 | "node_modules/web-worker": { 587 | "version": "1.0.0", 588 | "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.0.0.tgz", 589 | "integrity": "sha512-BzuMqeKVkKKwHV6tJuwePFcxYMxvC97D448mXTgh/CxXAB4sRtoV26gRPN+JDxsXRR7QZyioMV9O6NzQaASf7Q==" 590 | }, 591 | "node_modules/wordwrap": { 592 | "version": "1.0.0", 593 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 594 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" 595 | }, 596 | "node_modules/wrappy": { 597 | "version": "1.0.2", 598 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 599 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 600 | } 601 | }, 602 | "dependencies": { 603 | "@iden3/bigarray": { 604 | "version": "0.0.2", 605 | "resolved": "https://registry.npmjs.org/@iden3/bigarray/-/bigarray-0.0.2.tgz", 606 | "integrity": "sha512-Xzdyxqm1bOFF6pdIsiHLLl3HkSLjbhqJHVyqaTxXt3RqXBEnmsUmEW47H7VOi/ak7TdkRpNkxjyK5Zbkm+y52g==" 607 | }, 608 | "@iden3/binfileutils": { 609 | "version": "0.0.8", 610 | "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.8.tgz", 611 | "integrity": "sha512-/GqTsujUssGuQY+sd/XaLrA+OiCwzm+6yH28C57QQDWCHET2Logry9fGxU10n6XKdhCQBjZ7T/YMQkLwwkpRTQ==", 612 | "requires": { 613 | "fastfile": "0.0.19", 614 | "ffjavascript": "^0.2.30" 615 | } 616 | }, 617 | "@jest/types": { 618 | "version": "26.6.2", 619 | "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", 620 | "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", 621 | "dev": true, 622 | "requires": { 623 | "@types/istanbul-lib-coverage": "^2.0.0", 624 | "@types/istanbul-reports": "^3.0.0", 625 | "@types/node": "*", 626 | "@types/yargs": "^15.0.0", 627 | "chalk": "^4.0.0" 628 | } 629 | }, 630 | "@types/istanbul-lib-coverage": { 631 | "version": "2.0.3", 632 | "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", 633 | "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", 634 | "dev": true 635 | }, 636 | "@types/istanbul-lib-report": { 637 | "version": "3.0.0", 638 | "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", 639 | "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", 640 | "dev": true, 641 | "requires": { 642 | "@types/istanbul-lib-coverage": "*" 643 | } 644 | }, 645 | "@types/istanbul-reports": { 646 | "version": "3.0.0", 647 | "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", 648 | "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", 649 | "dev": true, 650 | "requires": { 651 | "@types/istanbul-lib-report": "*" 652 | } 653 | }, 654 | "@types/jest": { 655 | "version": "26.0.19", 656 | "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.19.tgz", 657 | "integrity": "sha512-jqHoirTG61fee6v6rwbnEuKhpSKih0tuhqeFbCmMmErhtu3BYlOZaXWjffgOstMM4S/3iQD31lI5bGLTrs97yQ==", 658 | "dev": true, 659 | "requires": { 660 | "jest-diff": "^26.0.0", 661 | "pretty-format": "^26.0.0" 662 | } 663 | }, 664 | "@types/node": { 665 | "version": "14.14.31", 666 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", 667 | "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", 668 | "dev": true 669 | }, 670 | "@types/yargs": { 671 | "version": "15.0.13", 672 | "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", 673 | "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==", 674 | "dev": true, 675 | "requires": { 676 | "@types/yargs-parser": "*" 677 | } 678 | }, 679 | "@types/yargs-parser": { 680 | "version": "20.2.0", 681 | "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", 682 | "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", 683 | "dev": true 684 | }, 685 | "ansi-regex": { 686 | "version": "5.0.0", 687 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 688 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 689 | "dev": true 690 | }, 691 | "ansi-styles": { 692 | "version": "4.3.0", 693 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 694 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 695 | "dev": true, 696 | "requires": { 697 | "color-convert": "^2.0.1" 698 | } 699 | }, 700 | "argparse": { 701 | "version": "2.0.1", 702 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 703 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" 704 | }, 705 | "balanced-match": { 706 | "version": "1.0.0", 707 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 708 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 709 | }, 710 | "big-integer": { 711 | "version": "1.6.48", 712 | "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", 713 | "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" 714 | }, 715 | "blake2b-wasm": { 716 | "version": "git+ssh://git@github.com/jbaylina/blake2b-wasm.git#0d5f024b212429c7f50a7f533aa3a2406b5b42b3", 717 | "from": "blake2b-wasm@git+https://github.com/jbaylina/blake2b-wasm.git", 718 | "requires": { 719 | "nanoassert": "^1.0.0" 720 | } 721 | }, 722 | "blakejs": { 723 | "version": "1.1.0", 724 | "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", 725 | "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" 726 | }, 727 | "brace-expansion": { 728 | "version": "1.1.11", 729 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 730 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 731 | "requires": { 732 | "balanced-match": "^1.0.0", 733 | "concat-map": "0.0.1" 734 | } 735 | }, 736 | "chalk": { 737 | "version": "4.1.0", 738 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 739 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 740 | "dev": true, 741 | "requires": { 742 | "ansi-styles": "^4.1.0", 743 | "supports-color": "^7.1.0" 744 | } 745 | }, 746 | "circom_runtime": { 747 | "version": "0.1.13", 748 | "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.13.tgz", 749 | "integrity": "sha512-vmv19/0p5OTe5uCI7PWqPtB5vPoYWjczqKYnabaC5HOxX99R4K1MuNqEXsNEAoEfZrmfAQd7vXLcATN9NVnsPA==", 750 | "requires": { 751 | "ffjavascript": "0.2.35", 752 | "fnv-plus": "^1.3.1" 753 | } 754 | }, 755 | "color-convert": { 756 | "version": "2.0.1", 757 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 758 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 759 | "dev": true, 760 | "requires": { 761 | "color-name": "~1.1.4" 762 | } 763 | }, 764 | "color-name": { 765 | "version": "1.1.4", 766 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 767 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 768 | "dev": true 769 | }, 770 | "concat-map": { 771 | "version": "0.0.1", 772 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 773 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 774 | }, 775 | "diff-sequences": { 776 | "version": "26.6.2", 777 | "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", 778 | "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", 779 | "dev": true 780 | }, 781 | "fastfile": { 782 | "version": "0.0.19", 783 | "resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.19.tgz", 784 | "integrity": "sha512-tz9nWR5KYb6eR2odFQ7oxqEkx8F3YQZ6NBJoJR92YEG3DqYOqyxMck8PKvTVNKx3uwvOqGnLXNScnqpdHRdHGQ==" 785 | }, 786 | "ffjavascript": { 787 | "version": "0.2.35", 788 | "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.35.tgz", 789 | "integrity": "sha512-xnC51tWbi0ah4SH+02jEfJyO+P+NiZWnxQrLDLtBYY1Dv3QM5ydxzd+gxnLEfWdT8i1bMM5pIh5P25l6fNCaVQ==", 790 | "requires": { 791 | "big-integer": "^1.6.48", 792 | "wasmcurves": "0.0.14", 793 | "web-worker": "^1.0.0" 794 | } 795 | }, 796 | "fnv-plus": { 797 | "version": "1.3.1", 798 | "resolved": "https://registry.npmjs.org/fnv-plus/-/fnv-plus-1.3.1.tgz", 799 | "integrity": "sha512-Gz1EvfOneuFfk4yG458dJ3TLJ7gV19q3OM/vVvvHf7eT02Hm1DleB4edsia6ahbKgAYxO9gvyQ1ioWZR+a00Yw==" 800 | }, 801 | "fs.realpath": { 802 | "version": "1.0.0", 803 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 804 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 805 | }, 806 | "function-bind": { 807 | "version": "1.1.1", 808 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 809 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 810 | }, 811 | "glob": { 812 | "version": "7.1.6", 813 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 814 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 815 | "requires": { 816 | "fs.realpath": "^1.0.0", 817 | "inflight": "^1.0.4", 818 | "inherits": "2", 819 | "minimatch": "^3.0.4", 820 | "once": "^1.3.0", 821 | "path-is-absolute": "^1.0.0" 822 | } 823 | }, 824 | "handlebars": { 825 | "version": "4.7.7", 826 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", 827 | "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", 828 | "requires": { 829 | "minimist": "^1.2.5", 830 | "neo-async": "^2.6.0", 831 | "source-map": "^0.6.1", 832 | "uglify-js": "^3.1.4", 833 | "wordwrap": "^1.0.0" 834 | } 835 | }, 836 | "has": { 837 | "version": "1.0.3", 838 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 839 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 840 | "requires": { 841 | "function-bind": "^1.1.1" 842 | } 843 | }, 844 | "has-flag": { 845 | "version": "4.0.0", 846 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 847 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 848 | "dev": true 849 | }, 850 | "inflight": { 851 | "version": "1.0.6", 852 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 853 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 854 | "requires": { 855 | "once": "^1.3.0", 856 | "wrappy": "1" 857 | } 858 | }, 859 | "inherits": { 860 | "version": "2.0.4", 861 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 862 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 863 | }, 864 | "interpret": { 865 | "version": "1.4.0", 866 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", 867 | "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" 868 | }, 869 | "is-core-module": { 870 | "version": "2.2.0", 871 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", 872 | "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", 873 | "requires": { 874 | "has": "^1.0.3" 875 | } 876 | }, 877 | "jest-diff": { 878 | "version": "26.6.2", 879 | "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", 880 | "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", 881 | "dev": true, 882 | "requires": { 883 | "chalk": "^4.0.0", 884 | "diff-sequences": "^26.6.2", 885 | "jest-get-type": "^26.3.0", 886 | "pretty-format": "^26.6.2" 887 | } 888 | }, 889 | "jest-get-type": { 890 | "version": "26.3.0", 891 | "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", 892 | "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", 893 | "dev": true 894 | }, 895 | "js-yaml": { 896 | "version": "4.0.0", 897 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", 898 | "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", 899 | "requires": { 900 | "argparse": "^2.0.1" 901 | } 902 | }, 903 | "logplease": { 904 | "version": "1.2.15", 905 | "resolved": "https://registry.npmjs.org/logplease/-/logplease-1.2.15.tgz", 906 | "integrity": "sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==" 907 | }, 908 | "minimatch": { 909 | "version": "3.0.4", 910 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 911 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 912 | "requires": { 913 | "brace-expansion": "^1.1.7" 914 | } 915 | }, 916 | "minimist": { 917 | "version": "1.2.5", 918 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 919 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 920 | }, 921 | "nanoassert": { 922 | "version": "1.1.0", 923 | "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", 924 | "integrity": "sha1-TzFS4JVA/eKMdvRLGbvNHVpCR40=" 925 | }, 926 | "neo-async": { 927 | "version": "2.6.2", 928 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", 929 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" 930 | }, 931 | "once": { 932 | "version": "1.4.0", 933 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 934 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 935 | "requires": { 936 | "wrappy": "1" 937 | } 938 | }, 939 | "path-is-absolute": { 940 | "version": "1.0.1", 941 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 942 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 943 | }, 944 | "path-parse": { 945 | "version": "1.0.6", 946 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 947 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 948 | }, 949 | "pretty-format": { 950 | "version": "26.6.2", 951 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", 952 | "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", 953 | "dev": true, 954 | "requires": { 955 | "@jest/types": "^26.6.2", 956 | "ansi-regex": "^5.0.0", 957 | "ansi-styles": "^4.0.0", 958 | "react-is": "^17.0.1" 959 | } 960 | }, 961 | "r1csfile": { 962 | "version": "0.0.32", 963 | "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.32.tgz", 964 | "integrity": "sha512-DkRXeOg0iRmfhgIuWICvdkOiLHpyb7+AcUd/WHpqBJEUp27pe7wKXBR4Jr3TPYCT4sTV9a/F3bovyAC4wystnQ==", 965 | "requires": { 966 | "@iden3/bigarray": "0.0.2", 967 | "@iden3/binfileutils": "0.0.8", 968 | "fastfile": "0.0.19", 969 | "ffjavascript": "0.2.35" 970 | } 971 | }, 972 | "react-is": { 973 | "version": "17.0.1", 974 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz", 975 | "integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==", 976 | "dev": true 977 | }, 978 | "rechoir": { 979 | "version": "0.6.2", 980 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 981 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 982 | "requires": { 983 | "resolve": "^1.1.6" 984 | } 985 | }, 986 | "resolve": { 987 | "version": "1.20.0", 988 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 989 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 990 | "requires": { 991 | "is-core-module": "^2.2.0", 992 | "path-parse": "^1.0.6" 993 | } 994 | }, 995 | "shelljs": { 996 | "version": "0.8.4", 997 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", 998 | "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", 999 | "requires": { 1000 | "glob": "^7.0.0", 1001 | "interpret": "^1.0.0", 1002 | "rechoir": "^0.6.2" 1003 | } 1004 | }, 1005 | "snarkjs": { 1006 | "version": "0.3.59", 1007 | "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.3.59.tgz", 1008 | "integrity": "sha512-fj8EOtziIz6FvNmcT97L4QM+QNzoCf8zTo4ghpYY4wFf0ZkgX9tSR2SZy1BjtaQnlC+LiF55wOG+jucP9Aw5BA==", 1009 | "requires": { 1010 | "@iden3/binfileutils": "0.0.8", 1011 | "blake2b-wasm": "git+https://github.com/jbaylina/blake2b-wasm.git", 1012 | "circom_runtime": "0.1.13", 1013 | "fastfile": "0.0.19", 1014 | "ffjavascript": "0.2.35", 1015 | "logplease": "^1.2.15", 1016 | "r1csfile": "0.0.32" 1017 | } 1018 | }, 1019 | "source-map": { 1020 | "version": "0.6.1", 1021 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1022 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 1023 | }, 1024 | "supports-color": { 1025 | "version": "7.2.0", 1026 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1027 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1028 | "dev": true, 1029 | "requires": { 1030 | "has-flag": "^4.0.0" 1031 | } 1032 | }, 1033 | "typescript": { 1034 | "version": "4.1.3", 1035 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", 1036 | "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", 1037 | "dev": true 1038 | }, 1039 | "uglify-js": { 1040 | "version": "3.14.3", 1041 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", 1042 | "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", 1043 | "optional": true 1044 | }, 1045 | "wasmcurves": { 1046 | "version": "0.0.14", 1047 | "resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.0.14.tgz", 1048 | "integrity": "sha512-G1iMkxlRaQSdqQ1JrwHcU+awLmwyH6kFKfT8g9obd8MWe+u5oSdFXrODB0zmSI5aGGvJPG+4cAmqCGYv9R+7qg==", 1049 | "requires": { 1050 | "big-integer": "^1.6.42", 1051 | "blakejs": "^1.1.0" 1052 | } 1053 | }, 1054 | "web-worker": { 1055 | "version": "1.0.0", 1056 | "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.0.0.tgz", 1057 | "integrity": "sha512-BzuMqeKVkKKwHV6tJuwePFcxYMxvC97D448mXTgh/CxXAB4sRtoV26gRPN+JDxsXRR7QZyioMV9O6NzQaASf7Q==" 1058 | }, 1059 | "wordwrap": { 1060 | "version": "1.0.0", 1061 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1062 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" 1063 | }, 1064 | "wrappy": { 1065 | "version": "1.0.2", 1066 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1067 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1068 | } 1069 | } 1070 | } 1071 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multisetups", 3 | "version": "0.0.1", 4 | "description": "Perform trusted setups for multiple circuits with snarkjs", 5 | "main": "build/index.js", 6 | "scripts": { 7 | "watch": "tsc --watch", 8 | "build": "tsc", 9 | "prepare": "tsc" 10 | }, 11 | "bin": { 12 | "multisetups": "build/index.js" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/weijiekoh/multisetups.git" 17 | }, 18 | "keywords": [ 19 | "snarkjs", 20 | "circom" 21 | ], 22 | "author": "Koh Wei Jie", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/weijiekoh/multisetups/issues" 26 | }, 27 | "homepage": "https://github.com/weijiekoh/multisetups", 28 | "dependencies": { 29 | "argparse": "2.0.1", 30 | "handlebars": "^4.7.7", 31 | "js-yaml": "4.0.0", 32 | "shelljs": "0.8.4", 33 | "snarkjs": "0.3.59" 34 | }, 35 | "devDependencies": { 36 | "@types/jest": "26.0.19", 37 | "typescript": "4.1.3" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /scripts/git-snapshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export GIT_HEAD=$(git rev-parse HEAD) 4 | export GIT_HEAD_NAME=$(git name-rev --name-only $GIT_HEAD) 5 | export GIT_UPSTREAM=$(git config remote.origin.url) 6 | GIT_UPSTREAM=${GIT_UPSTREAM:-$(git config remote.upstream.url)} 7 | -------------------------------------------------------------------------------- /ts/attest.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentParser } from 'argparse' 2 | import * as shelljs from 'shelljs' 3 | import * as fs from 'fs' 4 | import * as os from 'os' 5 | 6 | import * as Handlebars from 'handlebars' 7 | 8 | import { 9 | getZkeyFiles, 10 | countDirents, 11 | } from './utils' 12 | 13 | const configureSubparsers = (subparsers: ArgumentParser) => { 14 | const parser = subparsers.add_parser( 15 | 'attest', 16 | { add_help: true }, 17 | ) 18 | 19 | parser.add_argument( 20 | '-t', 21 | '--template', 22 | { 23 | required: true, 24 | action: 'store', 25 | type: 'str', 26 | help: 'The template file to generate the attestation from.' 27 | } 28 | ) 29 | 30 | parser.add_argument( 31 | '-d', 32 | '--dir', 33 | { 34 | required: true, 35 | action: 'store', 36 | type: 'str', 37 | help: 'The directory to write the attestation to.' 38 | } 39 | ) 40 | } 41 | 42 | const attest = async ( 43 | templateFile: string, 44 | dirname: string, 45 | ) => { 46 | if (!fs.existsSync(dirname)) { 47 | fs.mkdirSync(dirname) 48 | } 49 | 50 | // The directory must not be empty 51 | const numFiles = countDirents(dirname) 52 | if (numFiles === 0) { 53 | console.error(`Error: ${dirname} is empty. Run the 'download' subcommand first.`) 54 | return 1 55 | } 56 | 57 | const zkeys = getZkeyFiles(dirname) 58 | if (zkeys.length !== 1) { 59 | console.error( 60 | `Error: found ${zkeys.length} zkeys in ${dirname}. ` + 61 | `There must only be one.` 62 | ) 63 | return 1 64 | } 65 | const contribNum = zkeys[0].num 66 | 67 | const outFile = `${dirname}/attestation.${contribNum}.md` 68 | if (fs.existsSync(outFile)) { 69 | console.error(`Error: ${outFile} already exists; aborting.`) 70 | return 1 71 | } 72 | 73 | const transcriptFile = `${dirname}/transcript.${contribNum}.txt` 74 | if (!fs.existsSync(transcriptFile)) { 75 | console.error(`Error: ${transcriptFile} doesn't exist; aborting.`) 76 | return 1 77 | } 78 | 79 | const template = fs.readFileSync(templateFile).toString() 80 | const compiled = Handlebars.compile(template) 81 | 82 | const now = new Date() 83 | const attestation = compiled({ 84 | ceremony: process.env.CEREMONY, 85 | date: now.toDateString(), 86 | time: now.toTimeString(), 87 | repo: { 88 | head: process.env.GIT_HEAD, 89 | head_name: process.env.GIT_HEAD_NAME, 90 | upstream: process.env.GIT_UPSTREAM, 91 | }, 92 | os: { 93 | arch: os.arch(), 94 | platform: os.platform(), 95 | type: os.type(), 96 | version: os.version(), 97 | }, 98 | cpu: { 99 | model: os.cpus()[0].model, 100 | cores: os.cpus().length, 101 | bugs: getCpuBugs(), 102 | }, 103 | mem: { 104 | total: os.totalmem() / 1024**2, 105 | }, 106 | uptime: os.uptime(), 107 | transcript: getTranscript(transcriptFile) 108 | }) 109 | fs.writeFileSync(outFile, attestation); 110 | console.log( 111 | `Wrote prepopulated attestation to ${outFile}.\n` + 112 | `Please edit this file, sign it, and run the 'upload' subcommand.`) 113 | 114 | return 0 115 | } 116 | 117 | const getTranscript = (transcriptFile: string): string => { 118 | return fs.readFileSync(transcriptFile) 119 | .toString() 120 | .trim() 121 | .replace(/\x1B\[[\d;]+m/g, '') 122 | } 123 | 124 | const getCpuBugs = (): string => { 125 | const bugs = shelljs.exec(`grep '^bugs' /proc/cpuinfo | sort -u`, { silent: true }) 126 | return bugs.replace(/^bugs\s+:\s+/, '').trim() 127 | } 128 | 129 | export { 130 | attest, 131 | configureSubparsers, 132 | } 133 | -------------------------------------------------------------------------------- /ts/contribute.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentParser } from 'argparse' 2 | import * as crypto from 'crypto' 3 | import * as shelljs from 'shelljs' 4 | import * as fs from 'fs' 5 | import * as path from 'path' 6 | 7 | import { 8 | FORMAT, 9 | parseZkeyFilename, 10 | countDirents 11 | } from './utils' 12 | 13 | const configureSubparsers = (subparsers: ArgumentParser) => { 14 | const parser = subparsers.add_parser( 15 | 'contribute', 16 | { add_help: true }, 17 | ) 18 | 19 | parser.add_argument( 20 | '-d', 21 | '--dir', 22 | { 23 | required: true, 24 | action: 'store', 25 | type: 'str', 26 | help: 'The directory that contains the .zkey files. Each .zkey ' + 27 | 'file must follow this naming scheme: ' + FORMAT 28 | } 29 | ) 30 | 31 | parser.add_argument( 32 | '-n', 33 | '--new', 34 | { 35 | required: true, 36 | action: 'store', 37 | type: 'str', 38 | help: 'The directory to store the new .zkey files.', 39 | } 40 | ) 41 | 42 | parser.add_argument( 43 | '-e', 44 | '--entropy', 45 | { 46 | required: false, 47 | action: 'store', 48 | default: crypto.randomBytes(128).toString('hex'), 49 | type: 'str', 50 | help: 'Custom entropy' 51 | } 52 | ) 53 | } 54 | 55 | const contribute = async ( 56 | dirname: string, 57 | newDirname: string, 58 | entropy: string, 59 | ) => { 60 | if (!fs.existsSync(newDirname)) { 61 | fs.mkdirSync(newDirname) 62 | } 63 | 64 | // newDirname must be empty 65 | const numNewFiles = countDirents(newDirname) 66 | if (numNewFiles !== 0) { 67 | console.error(`Error: ${newDirname} is not empty.`) 68 | return 1 69 | } 70 | 71 | // The directory must not be empty 72 | const numFiles = countDirents(dirname) 73 | if (numFiles === 0) { 74 | console.error(`Error: ${dirname} is empty. Run the 'download' subcommand first.`) 75 | return 1 76 | } 77 | 78 | // Perform contributions 79 | let contribNum = 0 80 | const contribs: any[] = [] 81 | for (const file of fs.readdirSync(dirname)) { 82 | const m = parseZkeyFilename(file) 83 | if (m) { 84 | const name = m.name 85 | const num = m.num 86 | contribNum = num + 1 87 | 88 | const newName = `${name}.${num + 1}.zkey` 89 | contribs.push({ 90 | original: file, 91 | 'new': newName, 92 | }) 93 | //} else { 94 | //console.error(`Error: unexpected file ${file}`) 95 | //return 1 96 | } 97 | } 98 | 99 | let transcript = '' 100 | 101 | let currentEntropy = entropy + crypto.randomBytes(128).toString('hex') 102 | 103 | for (const c of contribs) { 104 | currentEntropy = crypto.createHash('sha512').update(currentEntropy, 'utf8').digest('hex') 105 | 106 | const o = path.join(dirname, c.original) 107 | const n = path.join(newDirname, c['new']) 108 | const cmd = `node ./node_modules/.bin/snarkjs zkey contribute ${o} ${n}` 109 | let out = shelljs.exec(`echo ${currentEntropy} | ${cmd}`, { silent: true }) 110 | out = out.replace(/Enter a random text\. \(Entropy\): /, '$&\n') 111 | transcript += `${cmd}\n` 112 | transcript += `${out}\n\n` 113 | } 114 | 115 | const transcriptFilepath = path.join(newDirname, `transcript.${contribNum}.txt`) 116 | fs.writeFileSync(transcriptFilepath, transcript.trim() + '\n') 117 | console.log( 118 | `Contribution generated, and transcript written to ${transcriptFilepath}.\n` + 119 | `Please run the 'attest' command next.` 120 | ) 121 | 122 | return 0 123 | } 124 | 125 | export { 126 | contribute, 127 | configureSubparsers, 128 | } 129 | -------------------------------------------------------------------------------- /ts/download.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentParser } from 'argparse' 2 | import * as crypto from 'crypto' 3 | import * as shelljs from 'shelljs' 4 | import * as fs from 'fs' 5 | import * as path from 'path' 6 | 7 | import { 8 | validateZkeyDir, 9 | countDirents, 10 | } from './utils' 11 | 12 | const configureSubparsers = (subparsers: ArgumentParser) => { 13 | const parser = subparsers.add_parser( 14 | 'download', 15 | { add_help: true }, 16 | ) 17 | 18 | parser.add_argument( 19 | '-m', 20 | '--multihash', 21 | { 22 | required: true, 23 | action: 'store', 24 | type: 'str', 25 | help: 'The multihash that you received from the coordinator.' 26 | } 27 | ) 28 | 29 | parser.add_argument( 30 | '-d', 31 | '--dir', 32 | { 33 | required: true, 34 | action: 'store', 35 | type: 'str', 36 | help: 'The directory to store the downloaded .zkey files.', 37 | } 38 | ) 39 | 40 | } 41 | 42 | const download = async ( 43 | multihash: string, 44 | dirname: string, 45 | ) => { 46 | if (!fs.existsSync(dirname)) { 47 | fs.mkdirSync(dirname) 48 | } 49 | 50 | // The directory must be empty 51 | const numFiles = countDirents(dirname) 52 | if (numFiles > 0) { 53 | console.error(`Error: ${dirname} should be empty`) 54 | return 1 55 | } 56 | 57 | // Download files 58 | const cmd = `ipfs get -o ${dirname} /ipfs/${multihash}` 59 | const out = shelljs.exec(cmd) 60 | 61 | if (out.code !== 0) { 62 | console.error(`Error: could not download files from /ipfs/${multihash}`) 63 | console.error(out.code, out.stderr) 64 | return 1 65 | } 66 | 67 | const isZkeyDirValid = validateZkeyDir(dirname) === 0 68 | if (!isZkeyDirValid) { 69 | return 1 70 | } 71 | 72 | return 0 73 | } 74 | 75 | export { 76 | download, 77 | configureSubparsers, 78 | } 79 | -------------------------------------------------------------------------------- /ts/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import * as argparse from 'argparse' 4 | import * as yaml from 'js-yaml' 5 | import * as fs from 'fs' 6 | 7 | import { 8 | init, 9 | configureSubparsers as configureSubparsersForInit, 10 | } from './init' 11 | 12 | import { 13 | download, 14 | configureSubparsers as configureSubparsersForDownload, 15 | } from './download' 16 | 17 | import { 18 | contribute, 19 | configureSubparsers as configureSubparsersForContribute, 20 | } from './contribute' 21 | 22 | import { 23 | attest, 24 | configureSubparsers as configureSubparsersForAttest, 25 | } from './attest' 26 | 27 | import { 28 | verify, 29 | configureSubparsers as configureSubparsersForVerify, 30 | } from './verify' 31 | 32 | import { 33 | upload, 34 | configureSubparsers as configureSubparsersForUpload, 35 | } from './upload' 36 | 37 | const run = async () => { 38 | const parser = new argparse.ArgumentParser({ 39 | description: 'multisetups: create and contribute to a trusted setup ceremony using snarkjs for multiple circuits', 40 | }) 41 | 42 | const subparsers = parser.add_subparsers({ 43 | title: 'Subcommands', 44 | dest: 'subcommand', 45 | required: true, 46 | }) 47 | 48 | configureSubparsersForInit(subparsers) 49 | configureSubparsersForDownload(subparsers) 50 | configureSubparsersForUpload(subparsers) 51 | configureSubparsersForContribute(subparsers) 52 | configureSubparsersForAttest(subparsers) 53 | configureSubparsersForVerify(subparsers) 54 | 55 | const args = parser.parse_args() 56 | 57 | const loadConfig = (configFile: string) => { 58 | try { 59 | return yaml.load(fs.readFileSync(configFile).toString()) 60 | } catch { 61 | console.error('Error: could not read', args.config) 62 | return 63 | } 64 | } 65 | 66 | try { 67 | if (args.subcommand === 'init') { 68 | //const config = loadConfig(args.config) 69 | //return (await init(config)) 70 | return (await init(args.dir)) 71 | } else if (args.subcommand === 'download') { 72 | return (await download(args.multihash, args.dir)) 73 | } else if (args.subcommand === 'contribute') { 74 | return (await contribute(args.dir, args['new'], args.entropy)) 75 | } else if (args.subcommand === 'attest') { 76 | return (await attest(args.template, args.dir)) 77 | } else if (args.subcommand === 'upload') { 78 | return (await upload(args.dir)) 79 | } else if (args.subcommand === 'verify') { 80 | return (await verify(args.dir, args.ptau)) 81 | } 82 | } catch (e) { 83 | console.error(e) 84 | return 1 85 | } 86 | 87 | return 0 88 | } 89 | 90 | const main = async () => { 91 | process.exit(await run()) 92 | } 93 | 94 | if (require.main === module) { 95 | main() 96 | } 97 | -------------------------------------------------------------------------------- /ts/init.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentParser } from 'argparse' 2 | import * as shelljs from 'shelljs' 3 | import * as fs from 'fs' 4 | import * as path from 'path' 5 | import { FORMAT, validateZkeyDir } from './utils' 6 | 7 | 8 | const configureSubparsers = (subparsers: ArgumentParser) => { 9 | const parser = subparsers.add_parser( 10 | 'init', 11 | { add_help: true }, 12 | ) 13 | 14 | parser.add_argument( 15 | '-d', 16 | '--dir', 17 | { 18 | required: true, 19 | action: 'store', 20 | type: 'str', 21 | help: 'The directory that contains the .zkey files. Each .zkey ' + 22 | 'file must follow this naming scheme: ' + FORMAT 23 | } 24 | ) 25 | } 26 | 27 | const init = async ( 28 | dirname: string, 29 | ) => { 30 | if (!fs.existsSync(dirname)) { 31 | console.error(`Error: ${dirname} does not exist`) 32 | return 1 33 | } 34 | 35 | const isZkeyDirValid = validateZkeyDir(dirname) === 0 36 | if (!isZkeyDirValid) { 37 | return 1 38 | } 39 | 40 | const cmd = `ipfs add --pin -Q -r ${dirname}` 41 | const out = shelljs.exec(cmd, { silent: true }) 42 | if (out.code !== 0 || out.stderr) { 43 | console.error(`Error: could not add ${dirname} to IPFS.`) 44 | console.error(out.stderr) 45 | return 1 46 | } 47 | const multihash = out.stdout.trim() 48 | console.log('Ceremony initialised. Please give this multihash to the first participant and keep your IPFS node running and connected to the IPFS network.') 49 | console.log(multihash) 50 | 51 | return 0 52 | } 53 | 54 | export { 55 | init, 56 | configureSubparsers, 57 | } 58 | -------------------------------------------------------------------------------- /ts/upload.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentParser } from 'argparse' 2 | import * as crypto from 'crypto' 3 | import * as shelljs from 'shelljs' 4 | import * as fs from 'fs' 5 | import * as path from 'path' 6 | 7 | import { 8 | FORMAT, 9 | countDirents, 10 | } from './utils' 11 | 12 | const configureSubparsers = (subparsers: ArgumentParser) => { 13 | const parser = subparsers.add_parser( 14 | 'upload', 15 | { add_help: true }, 16 | ) 17 | 18 | parser.add_argument( 19 | '-d', 20 | '--dir', 21 | { 22 | required: true, 23 | action: 'store', 24 | type: 'str', 25 | help: 'The directory that contains the .zkey files. Each .zkey ' + 26 | 'file must follow this naming scheme: ' + FORMAT 27 | } 28 | ) 29 | 30 | } 31 | 32 | const upload = async ( 33 | dirname: string, 34 | ) => { 35 | if (!fs.existsSync(dirname)) { 36 | console.log(`Error: ${dirname} does not exist`) 37 | } 38 | 39 | // The directory must not be empty 40 | const numFiles = countDirents(dirname) 41 | if (numFiles === 0) { 42 | console.error(`Error: ${dirname} should not be empty`) 43 | return 1 44 | } 45 | 46 | // Upload files 47 | const cmd = `ipfs add --pin -Q -r ${dirname}` 48 | const out = shelljs.exec(cmd, { silent: true }) 49 | if (out.code !== 0 || out.stderr) { 50 | console.error(`Error: could not add ${dirname} to IPFS.`) 51 | console.error(out.stderr) 52 | return 1 53 | } 54 | const multihash = out.stdout.trim() 55 | console.log('Contribution uploaded. Please send this multihash to the coordinator and keep your IPFS node running and connected to the IPFS network.') 56 | console.log(multihash) 57 | return 0 58 | } 59 | 60 | export { 61 | upload, 62 | configureSubparsers, 63 | } 64 | -------------------------------------------------------------------------------- /ts/utils.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import * as path from 'path' 3 | 4 | const FORMAT = '..zkey' 5 | 6 | const parseZkeyFilename = (file: string) => { 7 | const r = /^(.+)\.(\d+)\.zkey$/ 8 | const m = file.match(r) 9 | if (m) { 10 | return { 11 | name: m[1], 12 | num: Number(m[2]), 13 | } 14 | } 15 | return null 16 | } 17 | 18 | const getZkeyFiles = ( 19 | dirname: string, 20 | ): Array => { 21 | const zkeyFiles: any[] = [] 22 | for (const file of fs.readdirSync(dirname)) { 23 | const m = parseZkeyFilename(file) 24 | if (m) { 25 | const name = m.name 26 | const num = m.num 27 | zkeyFiles.push({ 28 | name, 29 | num, 30 | filename: path.join(dirname, file), 31 | }) 32 | } 33 | } 34 | return zkeyFiles 35 | } 36 | 37 | const validateZkeyDir = ( 38 | dirname: string, 39 | ) => { 40 | if (!fs.existsSync(dirname)) { 41 | console.error(`Error: ${dirname} does not exist`) 42 | return 1 43 | } 44 | const zkeyFiles = getZkeyFiles(dirname) 45 | 46 | if (zkeyFiles.length === 0) { 47 | console.error('Error: there are no .zkey files in', dirname) 48 | return 1 49 | } 50 | 51 | // Validate zkey filenames 52 | const uniqNames = new Set() 53 | for (const z of zkeyFiles) { 54 | uniqNames.add(z.name) 55 | //if (z.num !== 0) { 56 | //console.log(z) 57 | //console.error(`Error: all .zkey files in ${dirname} should have the correct format: ${FORMAT}`) 58 | //return 1 59 | //} 60 | } 61 | if (uniqNames.size !== zkeyFiles.length) { 62 | console.error(`The .zkey file names should be unique.`) 63 | return 1 64 | } 65 | 66 | return 0 67 | } 68 | 69 | const countDirents = ( 70 | dirname: string, 71 | ): number => { 72 | let numFiles = 0 73 | for (const _file of fs.readdirSync(dirname)) { 74 | numFiles ++ 75 | } 76 | return numFiles 77 | } 78 | 79 | export { 80 | FORMAT, 81 | getZkeyFiles, 82 | validateZkeyDir, 83 | parseZkeyFilename, 84 | countDirents, 85 | } 86 | -------------------------------------------------------------------------------- /ts/verify.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentParser } from 'argparse' 2 | import * as crypto from 'crypto' 3 | import * as shelljs from 'shelljs' 4 | import * as fs from 'fs' 5 | import * as path from 'path' 6 | 7 | import { 8 | FORMAT, 9 | validateZkeyDir, 10 | parseZkeyFilename, 11 | } from './utils' 12 | 13 | const configureSubparsers = (subparsers: ArgumentParser) => { 14 | const parser = subparsers.add_parser( 15 | 'verify', 16 | { add_help: true }, 17 | ) 18 | 19 | parser.add_argument( 20 | '-d', 21 | '--dir', 22 | { 23 | required: true, 24 | action: 'store', 25 | type: 'str', 26 | help: 'The directory that contains the .zkey files to verify. Each .zkey ' + 27 | 'file must follow this naming scheme: ' + FORMAT 28 | } 29 | ) 30 | 31 | parser.add_argument( 32 | '-p', 33 | '--ptau', 34 | { 35 | required: true, 36 | action: 'store', 37 | type: 'str', 38 | help: 'The path to the .ptau file', 39 | } 40 | ) 41 | } 42 | 43 | const verify = async ( 44 | dirname: string, 45 | ptauFile: string, 46 | ) => { 47 | // The directory must not be empty 48 | let numFiles = 0 49 | for (const file of fs.readdirSync(dirname)) { 50 | numFiles ++ 51 | } 52 | 53 | if (numFiles === 0) { 54 | console.error(`Error: ${dirname} is empty. Run the 'download' subcommand first.`) 55 | return 1 56 | } 57 | 58 | // Perform contributions 59 | let contribNum 60 | const contribs: string[] = [] 61 | for (const file of fs.readdirSync(dirname)) { 62 | const m = parseZkeyFilename(file) 63 | if (m) { 64 | contribs.push(file) 65 | } 66 | } 67 | 68 | console.log('You should run the following commands to verify the contribution:') 69 | for (const c of contribs) { 70 | const cmd = `node ./node_modules/.bin/snarkjs zkey verify ${ptauFile} ${c}` 71 | console.log(cmd) 72 | } 73 | 74 | return 0 75 | } 76 | 77 | export { 78 | verify, 79 | configureSubparsers, 80 | } 81 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "alwaysStrict": true, 5 | "allowJs": true, 6 | "noImplicitAny": false, 7 | "forceConsistentCasingInFileNames": true, 8 | "noUnusedLocals": false, 9 | "noUnusedParameters": false, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "sourceMap": true, 13 | "strict": true, 14 | "outDir": "./build" 15 | }, 16 | "exclude": [ 17 | "node_modules/**" 18 | ], 19 | "include": [ 20 | "./ts" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /zkeys/Hasher_2.test.0.zkey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/privacy-ethereum/multisetups/1732c0604f8ce62ec164c1a8f28d8534f373231d/zkeys/Hasher_2.test.0.zkey -------------------------------------------------------------------------------- /zkeys/Hasher_3.prod.0.zkey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/privacy-ethereum/multisetups/1732c0604f8ce62ec164c1a8f28d8534f373231d/zkeys/Hasher_3.prod.0.zkey --------------------------------------------------------------------------------