arnaucube
arnaucube/snarkjsPublic Self-hosted repository
snarkjs/cli.js
cli.jsRaw
  1#!/usr/bin/env node
  2
  3/*
  4    Copyright 2018 0KIMS association.
  5
  6    This file is part of jaz (Zero Knowledge Circuit Compiler).
  7
  8    jaz is a free software: you can redistribute it and/or modify it
  9    under the terms of the GNU General Public License as published by
 10    the Free Software Foundation, either version 3 of the License, or
 11    (at your option) any later version.
 12
 13    jaz is distributed in the hope that it will be useful, but WITHOUT
 14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 15    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
 16    License for more details.
 17
 18    You should have received a copy of the GNU General Public License
 19    along with jaz. If not, see <https://www.gnu.org/licenses/>.
 20*/
 21
 22/* eslint-disable no-console */
 23
 24const fs = require("fs");
 25const path = require("path");
 26
 27const zkSnark = require("./index.js");
 28const {stringifyBigInts, unstringifyBigInts} = require("./src/stringifybigint.js");
 29
 30
 31const version = require("./package").version;
 32
 33const argv = require("yargs")
 34    .version(version)
 35    .usage(`snarkjs <command> <options>
 36
 37setup command
 38=============
 39
 40    snarkjs setup <option>
 41
 42    Runs a setup for a circuit generating the proving and the verification key.
 43
 44    -c or --circuit <circuitFile>
 45
 46        Filename of the compiled circuit file generated by circom.
 47
 48        Default: circuit.json
 49
 50    --pk or --provingkey <provingKeyFile>
 51
 52        Output filename where the proving key will be stored.
 53
 54        Default: proving_key.json
 55
 56    --vk or --verificationkey <verificationKeyFile>
 57
 58        Output Filename where the verification key will be stored.
 59
 60        Default: verification_key.json
 61
 62calculate witness command
 63=========================
 64
 65    snarkjs calculatewitness <options>
 66
 67    Calculate the witness of a circuit given an input.
 68
 69    -c or --circuit <circuitFile>
 70
 71        Filename of the compiled circuit file generated by circom.
 72
 73        Default: circuit.json
 74
 75    -i or --input <inputFile>
 76
 77        JSON file with the inputs of the circuit.
 78
 79        Default: input.json
 80
 81        Example of for a circuit with tow inputs a and b:
 82
 83            {"a": "22", "b": "33"}
 84
 85    -w or --witness
 86
 87        Output filename with the generated witness.
 88
 89        Default: witness.json
 90
 91generate a proof command
 92========================
 93
 94    snarkjs proof <options>
 95
 96    -w or --witness
 97
 98        Input filename used to calculate the proof.
 99
100        Default: witness.json
101
102    --pk or --provingkey <provingKeyFile>
103
104        Input filename with the proving key (generated during the setup).
105
106        Default: proving_key.json
107
108    -p or --proof
109
110        Output filenam with the zero knowlage proof.
111
112        Default: proof.json
113
114    --pub or --public <publicFilename>
115
116        Output filename with the value of the public wires/signals.
117        This info will be needed to verify the proof.
118
119        Default: public.json
120
121verify command
122==============
123
124    snarkjs verify <options>
125
126    The command returns "OK" if the proof is valid
127    and  "INVALID" in case it is not a valid proof.
128
129    --vk or --verificationkey <verificationKeyFile>
130
131        Input Filename with the verification key (generated during the setup).
132
133        Default: verification_key.json
134
135    -p or --proof
136
137        Input filenam with the zero knowlage proof you want to verify
138
139        Default: proof.json
140
141    --pub or --public <publicFilename>
142
143        Input filename with the public wires/signals.
144
145        Default: public.json
146
147generate solidity verifier command
148==================================
149
150    snarkjs generateverifier <options>
151
152    Generates a solidity smart contract that verifies the zero knowlage proof.
153
154    --vk or --verificationkey <verificationKeyFile>
155
156        Input Filename with the verification key (generated during the setup).
157
158        Default: verification_key.json
159
160    -v or --verifier
161
162        Output file with a solidity smart contract that verifies a zero knowlage proof.
163
164        Default: verifier.sol
165
166generate call parameters
167========================
168
169    snarkjs generatecall <options>
170
171    Outputs into the console the raw parameters to be used in 'verifyProof'
172    method of the solidity verifier.
173
174    -p or --proof
175
176        Input filenam with the zero knowlage proof you want to use
177
178        Default: proof.json
179
180    --pub or --public <publicFilename>
181
182        Input filename with the public wires/signals.
183
184        Default: public.json
185
186
187        `)
188    .alias("c", "circuit")
189    .alias("pk", "provingkey")
190    .alias("vk", "verificationkey")
191    .alias("w", "witness")
192    .alias("p", "proof")
193    .alias("i", "input")
194    .alias("pub", "public")
195    .alias("v", "verifier")
196    .help("h")
197    .alias("h", "help")
198    .epilogue(`Copyright (C) 2018  0kims association
199    This program comes with ABSOLUTELY NO WARRANTY;
200    This is free software, and you are welcome to redistribute it
201    under certain conditions; see the COPYING file in the official
202    repo directory at  https://github.com/iden3/circom `)
203    .argv;
204
205const circuitName = (argv.circuit) ? argv.circuit : "circuit.json";
206const provingKeyName = (argv.provingkey) ? argv.provingkey : "proving_key.json";
207const verificationKeyName = (argv.verificationkey) ? argv.verificationkey : "verification_key.json";
208const inputName = (argv.input) ? argv.input : "input.json";
209const witnessName = (argv.witness) ? argv.witness : "witness.json";
210const proofName = (argv.proof) ? argv.proof : "proof.json";
211const publicName = (argv.public) ? argv.public : "public.json";
212const verifierName = (argv.public) ? argv.public : "verifier.sol";
213
214function p256(n) {
215    let nstr = n.toString(16);
216    while (nstr.length < 64) nstr = "0"+nstr;
217    nstr = `"0x${nstr}"`;
218    return nstr;
219}
220
221try {
222    if (argv._[0].toUpperCase() == "SETUP") {
223        const cirDef = JSON.parse(fs.readFileSync(circuitName, "utf8"));
224        const cir = new zkSnark.Circuit(cirDef);
225        const setup = zkSnark.setup(cir);
226
227        fs.writeFileSync(provingKeyName, JSON.stringify(stringifyBigInts(setup.vk_proof), null, 1), "utf-8");
228        fs.writeFileSync(verificationKeyName, JSON.stringify(stringifyBigInts(setup.vk_verifier), null, 1), "utf-8");
229        process.exit(0);
230    } else if (argv._[0].toUpperCase() == "CALCULATEWITNESS") {
231        const cirDef = JSON.parse(fs.readFileSync(circuitName, "utf8"));
232        const cir = new zkSnark.Circuit(cirDef);
233        const input = unstringifyBigInts(JSON.parse(fs.readFileSync(inputName, "utf8")));
234
235        const witness = cir.calculateWitness(input);
236
237        fs.writeFileSync(witnessName, JSON.stringify(stringifyBigInts(witness), null, 1), "utf-8");
238        process.exit(0);
239    } else if (argv._[0].toUpperCase() == "PROOF") {
240        const witness = unstringifyBigInts(JSON.parse(fs.readFileSync(witnessName, "utf8")));
241        const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync(provingKeyName, "utf8")));
242
243        const {proof, publicSignals} = zkSnark.genProof(provingKey, witness);
244
245        fs.writeFileSync(proofName, JSON.stringify(stringifyBigInts(proof), null, 1), "utf-8");
246        fs.writeFileSync(publicName, JSON.stringify(stringifyBigInts(publicSignals), null, 1), "utf-8");
247        process.exit(0);
248    } else if (argv._[0].toUpperCase() == "VERIFY") {
249        const public = unstringifyBigInts(JSON.parse(fs.readFileSync(publicName, "utf8")));
250        const verificationKey = unstringifyBigInts(JSON.parse(fs.readFileSync(verificationKeyName, "utf8")));
251        const proof = unstringifyBigInts(JSON.parse(fs.readFileSync(proofName, "utf8")));
252        const isValid = zkSnark.isValid(verificationKey, proof, public);
253
254        if (isValid) {
255            console.log("OK");
256            process.exit(0);
257        } else {
258            console.log("INVALID");
259            process.exit(1);
260        }
261    } else if (argv._[0].toUpperCase() == "GENERATEVERIFIER") {
262
263        const verificationKey = unstringifyBigInts(JSON.parse(fs.readFileSync(verificationKeyName, "utf8")));
264        let template = fs.readFileSync(path.join( __dirname,  "templates", "verifier.sol"), "utf-8");
265
266        const vka_str = `[${verificationKey.vk_a[0][1].toString()},`+
267                         `${verificationKey.vk_a[0][0].toString()}], `+
268                        `[${verificationKey.vk_a[1][1].toString()},` +
269                         `${verificationKey.vk_a[1][0].toString()}]`;
270        template = template.replace("<%vk_a%>", vka_str);
271
272        const vkb_str = `${verificationKey.vk_b[0].toString()},`+
273                        `${verificationKey.vk_b[1].toString()}`;
274        template = template.replace("<%vk_b%>", vkb_str);
275
276        const vkc_str = `[${verificationKey.vk_c[0][1].toString()},`+
277                         `${verificationKey.vk_c[0][0].toString()}], `+
278                        `[${verificationKey.vk_c[1][1].toString()},` +
279                         `${verificationKey.vk_c[1][0].toString()}]`;
280        template = template.replace("<%vk_c%>", vkc_str);
281
282        const vkg_str = `[${verificationKey.vk_g[0][1].toString()},`+
283                         `${verificationKey.vk_g[0][0].toString()}], `+
284                        `[${verificationKey.vk_g[1][1].toString()},` +
285                         `${verificationKey.vk_g[1][0].toString()}]`;
286        template = template.replace("<%vk_g%>", vkg_str);
287
288        const vkgb1_str = `${verificationKey.vk_gb_1[0].toString()},`+
289                          `${verificationKey.vk_gb_1[1].toString()}`;
290        template = template.replace("<%vk_gb1%>", vkgb1_str);
291
292        const vkgb2_str = `[${verificationKey.vk_gb_2[0][1].toString()},`+
293                           `${verificationKey.vk_gb_2[0][0].toString()}], `+
294                          `[${verificationKey.vk_gb_2[1][1].toString()},` +
295                           `${verificationKey.vk_gb_2[1][0].toString()}]`;
296        template = template.replace("<%vk_gb2%>", vkgb2_str);
297
298        const vkz_str = `[${verificationKey.vk_z[0][1].toString()},`+
299                         `${verificationKey.vk_z[0][0].toString()}], `+
300                        `[${verificationKey.vk_z[1][1].toString()},` +
301                         `${verificationKey.vk_z[1][0].toString()}]`;
302        template = template.replace("<%vk_z%>", vkz_str);
303
304        // The points
305
306        template = template.replace("<%vk_input_length%>", (verificationKey.A.length-1).toString());
307        template = template.replace("<%vk_ic_length%>", verificationKey.A.length.toString());
308        let vi = "";
309        for (let i=0; i<verificationKey.A.length; i++) {
310            if (vi != "") vi = vi + "        ";
311            vi = vi + `vk.IC[${i}] = Pairing.G1Point(${verificationKey.A[i][0].toString()},`+
312                                                    `${verificationKey.A[i][1].toString()});\n`;
313        }
314        template = template.replace("<%vk_ic_pts%>", vi);
315
316
317        fs.writeFileSync(verifierName, template, "utf-8");
318        process.exit(0);
319
320    } else if (argv._[0].toUpperCase() == "GENERATECALL") {
321
322        const public = unstringifyBigInts(JSON.parse(fs.readFileSync(publicName, "utf8")));
323        const proof = unstringifyBigInts(JSON.parse(fs.readFileSync(proofName, "utf8")));
324
325        inputs = "";
326        for (let i=0; i<public.length; i++) {
327            if (inputs != "") inputs = inputs + ",";
328            inputs = inputs + p256(public[i]);
329        }
330
331        const S=`[${p256(proof.pi_a[0])}, ${p256(proof.pi_a[1])}],` +
332                `[${p256(proof.pi_ap[0])}, ${p256(proof.pi_ap[1])}],` +
333                `[[${p256(proof.pi_b[0][1])}, ${p256(proof.pi_b[0][0])}],[${p256(proof.pi_b[1][1])}, ${p256(proof.pi_b[1][0])}]],` +
334                `[${p256(proof.pi_bp[0])}, ${p256(proof.pi_bp[1])}],` +
335                `[${p256(proof.pi_c[0])}, ${p256(proof.pi_c[1])}],` +
336                `[${p256(proof.pi_cp[0])}, ${p256(proof.pi_cp[1])}],` +
337                `[${p256(proof.pi_h[0])}, ${p256(proof.pi_h[1])}],` +
338                `[${p256(proof.pi_kp[0])}, ${p256(proof.pi_kp[1])}],` +
339                `[${inputs}]` ;
340
341        console.log(S);
342        process.exit(0);
343    }
344} catch(err) {
345    console.log("ERROR: " + err);
346    process.exit(1);
347}
348
349
350
351
352