2018-10-21 19:24:49 +03:00
/ *
Copyright 2018 0 KIMS association .
This file is part of jaz ( Zero Knowledge Circuit Compiler ) .
jaz is a free software : you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
jaz is distributed in the hope that it will be useful , but WITHOUT
ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public
License for more details .
You should have received a copy of the GNU General Public License
along with jaz . If not , see < https : //www.gnu.org/licenses/>.
* /
/* eslint-disable no-console */
2020-07-11 11:31:52 +03:00
import fs from "fs" ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
import { load as loadR1cs } from "r1csfile" ;
2020-03-26 22:16:29 +03:00
2020-07-11 11:31:52 +03:00
import loadSyms from "./src/loadsyms.js" ;
import * as r1cs from "./src/r1cs.js" ;
2020-05-09 16:05:45 +03:00
2020-07-11 11:31:52 +03:00
import clProcessor from "./src/clprocessor.js" ;
2020-05-09 16:05:45 +03:00
2020-07-11 11:31:52 +03:00
import * as powersOfTaw from "./src/powersoftau.js" ;
2020-05-09 16:05:45 +03:00
2020-07-11 11:31:52 +03:00
import { utils } from "ffjavascript" ;
const { stringifyBigInts , unstringifyBigInts } = utils ;
2020-06-08 12:03:36 +03:00
2020-07-11 11:31:52 +03:00
import * as zkey from "./src/zkey.js" ;
import * as groth16 from "./src/groth16.js" ;
import * as wtns from "./src/wtns.js" ;
import * as curves from "./src/curves.js" ;
import path from "path" ;
2020-06-08 12:03:36 +03:00
2020-07-11 11:31:52 +03:00
import Logger from "logplease" ;
const logger = Logger . create ( "snarkJS" , { showTimestamp : false } ) ;
Logger . setLogLevel ( "INFO" ) ;
2020-05-31 01:46:49 +03:00
2020-08-29 15:12:24 +03:00
const _ _dirname = path . dirname ( new URL ( import . meta . url ) . pathname ) ;
2020-05-09 16:05:45 +03:00
const commands = [
2020-07-11 11:31:52 +03:00
{
cmd : "powersoftau new <curve> <power> [powersoftau_0000.ptau]" ,
description : "Starts a powers of tau ceremony" ,
alias : [ "ptn" ] ,
options : "-verbose|v" ,
action : powersOfTawNew
} ,
{
cmd : "powersoftau contribute <powersoftau.ptau> <new_powersoftau.ptau>" ,
description : "creates a ptau file with a new contribution" ,
alias : [ "ptc" ] ,
options : "-verbose|v -name|n -entropy|e" ,
action : powersOfTawContribute
} ,
{
2020-07-14 12:55:12 +03:00
cmd : "powersoftau export challenge <powersoftau_0000.ptau> [challenge]" ,
description : "Creates a challenge" ,
2020-07-11 11:31:52 +03:00
alias : [ "ptec" ] ,
options : "-verbose|v" ,
2020-07-14 12:55:12 +03:00
action : powersOfTawExportChallenge
2020-07-11 11:31:52 +03:00
} ,
{
2020-07-14 12:55:12 +03:00
cmd : "powersoftau challenge contribute <curve> <challenge> [response]" ,
description : "Contribute to a challenge" ,
2020-07-11 11:31:52 +03:00
alias : [ "ptcc" ] ,
options : "-verbose|v -entropy|e" ,
2020-07-14 12:55:12 +03:00
action : powersOfTawChallengeContribute
2020-07-11 11:31:52 +03:00
} ,
{
cmd : "powersoftau import response <powersoftau_old.ptau> <response> <<powersoftau_new.ptau>" ,
description : "import a response to a ptau file" ,
alias : [ "ptir" ] ,
options : "-verbose|v -nopoints -nocheck -name|n" ,
action : powersOfTawImport
} ,
{
cmd : "powersoftau beacon <old_powersoftau.ptau> <new_powersoftau.ptau> <beaconHash(Hex)> <numIterationsExp>" ,
description : "adds a beacon" ,
alias : [ "ptb" ] ,
options : "-verbose|v -name|n" ,
action : powersOfTawBeacon
} ,
{
cmd : "powersoftau prepare phase2 <powersoftau.ptau> <new_powersoftau.ptau>" ,
description : "Prepares phase 2. " ,
longDescription : " This process calculates the evaluation of the Lagrange polinomials at tau for alpha*tau and beta tau" ,
alias : [ "pt2" ] ,
options : "-verbose|v" ,
action : powersOfTawPreparePhase2
} ,
2020-07-13 08:21:03 +03:00
{
cmd : "powersoftau verify <powersoftau.ptau>" ,
description : "verifies a powers of tau file" ,
alias : [ "ptv" ] ,
options : "-verbose|v" ,
action : powersOfTawVerify
} ,
2020-07-11 11:31:52 +03:00
{
cmd : "powersoftau export json <powersoftau_0000.ptau> <powersoftau_0000.json>" ,
description : "Exports a power of tau file to a JSON" ,
alias : [ "ptej" ] ,
options : "-verbose|v" ,
action : powersOfTawExportJson
} ,
2020-05-09 16:05:45 +03:00
{
cmd : "r1cs info [circuit.r1cs]" ,
description : "Print statistiscs of a circuit" ,
alias : [ "ri" , "info -r|r1cs:circuit.r1cs" ] ,
action : r1csInfo
} ,
{
cmd : "r1cs print [circuit.r1cs] [circuit.sym]" ,
description : "Print the constraints of a circuit" ,
alias : [ "rp" , "print -r|r1cs:circuit.r1cs -s|sym" ] ,
action : r1csPrint
} ,
{
2020-06-30 16:45:21 +03:00
cmd : "r1cs export json [circuit.r1cs] [circuit.json]" ,
description : "Export r1cs to JSON file" ,
alias : [ "rej" ] ,
action : r1csExportJSON
} ,
{
cmd : "wtns calculate [circuit.wasm] [input.json] [witness.wtns]" ,
2020-05-09 16:05:45 +03:00
description : "Caclculate specific witness of a circuit given an input" ,
alias : [ "wc" , "calculatewitness -ws|wasm:circuit.wasm -i|input:input.json -wt|witness:witness.wtns" ] ,
2020-06-30 16:45:21 +03:00
action : wtnsCalculate
2020-05-09 16:05:45 +03:00
} ,
{
2020-06-30 16:45:21 +03:00
cmd : "wtns debug [circuit.wasm] [input.json] [witness.wtns] [circuit.sym]" ,
2020-05-09 16:05:45 +03:00
description : "Calculate the witness with debug info." ,
longDescription : "Calculate the witness with debug info. \nOptions:\n-g or --g : Log signal gets\n-s or --s : Log signal sets\n-t or --trigger : Log triggers " ,
options : "-get|g -set|s -trigger|t" ,
alias : [ "wd" ] ,
2020-06-30 16:45:21 +03:00
action : wtnsDebug
} ,
{
cmd : "wtns export json [witness.wtns] [witnes.json]" ,
description : "Calculate the witness with debug info." ,
longDescription : "Calculate the witness with debug info. \nOptions:\n-g or --g : Log signal gets\n-s or --s : Log signal sets\n-t or --trigger : Log triggers " ,
2020-07-11 11:31:52 +03:00
options : "-verbose|v" ,
2020-06-30 16:45:21 +03:00
alias : [ "wej" ] ,
action : wtnsExportJson
2020-05-09 16:05:45 +03:00
} ,
2020-06-14 18:37:22 +03:00
{
cmd : "zkey new [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]" ,
2020-05-31 01:46:49 +03:00
description : "Creates an initial pkey file with zero contributions " ,
2020-06-14 18:37:22 +03:00
alias : [ "zkn" ] ,
options : "-verbose|v" ,
action : zkeyNew
} ,
2020-07-13 08:21:03 +03:00
{
cmd : "zkey contribute <circuit_old.zkey> <circuit_new.zkey>" ,
description : "creates a zkey file with a new contribution" ,
alias : [ "zkc" ] ,
options : "-verbose|v -entropy|e -name|n" ,
action : zkeyContribute
} ,
2020-06-14 18:37:22 +03:00
{
cmd : "zkey export bellman [circuit.zkey] [circuit.mpcparams]" ,
description : "Export a zKey to a MPCParameters file compatible with kobi/phase2 (Bellman)" ,
alias : [ "zkeb" ] ,
options : "-verbose|v" ,
action : zkeyExportBellman
} ,
2020-07-13 08:21:03 +03:00
{
cmd : "zkey bellman contribute <curve> <circuit.mpcparams> <circuit_response.mpcparams>" ,
2020-07-22 11:39:18 +03:00
description : "contributes to a challenge file in bellman format" ,
2020-07-13 08:21:03 +03:00
alias : [ "zkbc" ] ,
options : "-verbose|v -entropy|e" ,
action : zkeyBellmanContribute
} ,
2020-06-14 18:37:22 +03:00
{
cmd : "zkey import bellman <circuit_old.zkey> <circuit.mpcparams> <circuit_new.zkey>" ,
description : "Export a zKey to a MPCParameters file compatible with kobi/phase2 (Bellman) " ,
alias : [ "zkib" ] ,
2020-07-11 11:31:52 +03:00
options : "-verbose|v -name|n" ,
2020-06-14 18:37:22 +03:00
action : zkeyImportBellman
} ,
2020-06-18 20:14:06 +03:00
{
cmd : "zkey beacon <circuit_old.zkey> <circuit_new.zkey> <beaconHash(Hex)> <numIterationsExp>" ,
description : "adds a beacon" ,
alias : [ "zkb" ] ,
options : "-verbose|v -name|n" ,
action : zkeyBeacon
} ,
{
2020-07-13 08:21:03 +03:00
cmd : "zkey verify [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]" ,
description : "Verify zkey file contributions and verify that matches with the original circuit.r1cs and ptau" ,
alias : [ "zkv" ] ,
options : "-verbose|v" ,
action : zkeyVerify
2020-06-18 20:14:06 +03:00
} ,
2020-06-14 18:37:22 +03:00
{
2020-07-11 11:31:52 +03:00
cmd : "zkey export verificationkey [circuit.zkey] [verification_key.json]" ,
2020-06-14 18:37:22 +03:00
description : "Exports a verification key" ,
alias : [ "zkev" ] ,
action : zkeyExportVKey
} ,
{
cmd : "zkey export json [circuit.zkey] [circuit.zkey.json]" ,
description : "Exports a circuit key to a JSON file" ,
alias : [ "zkej" ] ,
2020-05-31 01:46:49 +03:00
options : "-verbose|v" ,
2020-06-14 18:37:22 +03:00
action : zkeyExportJson
2020-05-31 01:46:49 +03:00
} ,
2020-07-13 08:21:03 +03:00
{
cmd : "zkey export solidityverifier [circuit.zkey] [verifier.sol]" ,
description : "Creates a verifier in solidity" ,
alias : [ "zkesv" , "generateverifier -vk|verificationkey -v|verifier" ] ,
action : zkeyExportSolidityVerifier
} ,
{
cmd : "zkey export soliditycalldata <public.json> <proof.json>" ,
description : "Generates call parameters ready to be called." ,
alias : [ "zkesc" , "generatecall -pub|public -p|proof" ] ,
action : zkeyExportSolidityCalldata
} ,
{
cmd : "groth16 prove [circuit.zkey] [witness.wtns] [proof.json] [public.json]" ,
description : "Generates a zk Proof from witness" ,
alias : [ "g16p" , "zpw" , "zksnark proof" , "proof -pk|provingkey -wt|witness -p|proof -pub|public" ] ,
options : "-verbose|v -protocol" ,
action : groth16Prove
} ,
{
cmd : "groth16 fullprove [input.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json]" ,
description : "Generates a zk Proof from input" ,
alias : [ "g16f" , "g16i" ] ,
options : "-verbose|v -protocol" ,
action : groth16FullProve
} ,
{
cmd : "groth16 verify [verification_key.json] [public.json] [proof.json]" ,
description : "Verify a zk Proof" ,
alias : [ "g16v" , "verify -vk|verificationkey -pub|public -p|proof" ] ,
action : groth16Verify
} ,
2020-05-09 16:05:45 +03:00
] ;
clProcessor ( commands ) . then ( ( res ) => {
process . exit ( res ) ;
} , ( err ) => {
2020-07-11 11:31:52 +03:00
logger . error ( err ) ;
2020-05-09 16:05:45 +03:00
process . exit ( 1 ) ;
} ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
/ *
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
TODO COMMANDS
=== === === === =
2019-06-16 01:12:50 +03:00
2020-05-09 16:05:45 +03:00
{
2020-07-13 08:21:03 +03:00
cmd : "zksnark setup [circuit.r1cs] [circuit.zkey] [verification_key.json]" ,
description : "Run a simple setup for a circuit generating the proving key." ,
alias : [ "zs" , "setup -r1cs|r -provingkey|pk -verificationkey|vk" ] ,
options : "-verbose|v -protocol" ,
action : zksnarkSetup
2020-05-09 16:05:45 +03:00
} ,
{
cmd : "witness verify <circuit.r1cs> <witness.wtns>" ,
description : "Verify a witness agains a r1cs" ,
alias : [ "wv" ] ,
action : witnessVerify
} ,
2020-07-13 08:21:03 +03:00
{
cmd : "powersOfTau export response"
}
2020-05-09 16:05:45 +03:00
* /
2019-06-16 01:12:50 +03:00
2020-05-09 16:05:45 +03:00
function p256 ( n ) {
let nstr = n . toString ( 16 ) ;
while ( nstr . length < 64 ) nstr = "0" + nstr ;
nstr = ` "0x ${ nstr } " ` ;
return nstr ;
}
2019-06-16 01:12:50 +03:00
2020-05-09 16:05:45 +03:00
function changeExt ( fileName , newExt ) {
let S = fileName ;
while ( ( S . length > 0 ) && ( S [ S . length - 1 ] != "." ) ) S = S . slice ( 0 , S . length - 1 ) ;
if ( S . length > 0 ) {
return S + newExt ;
} else {
return fileName + "." + newExt ;
}
}
2019-06-16 01:12:50 +03:00
2020-05-09 16:05:45 +03:00
// r1cs export circomJSON [circuit.r1cs] [circuit.json]
async function r1csInfo ( params , options ) {
const r1csName = params [ 0 ] || "circuit.r1cs" ;
2019-06-16 01:12:50 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
await r1cs . info ( r1csName , logger ) ;
2020-03-26 22:16:29 +03:00
2020-04-18 21:21:16 +03:00
2020-05-09 16:05:45 +03:00
return 0 ;
}
2020-04-18 21:21:16 +03:00
2020-05-09 16:05:45 +03:00
// r1cs print [circuit.r1cs] [circuit.sym]
async function r1csPrint ( params , options ) {
const r1csName = params [ 0 ] || "circuit.r1cs" ;
2020-06-30 16:45:21 +03:00
const symName = params [ 1 ] || changeExt ( r1csName , "sym" ) ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2020-05-09 16:05:45 +03:00
const cir = await loadR1cs ( r1csName , true , true ) ;
2019-06-16 01:12:50 +03:00
2020-05-09 16:05:45 +03:00
const sym = await loadSyms ( symName ) ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
await r1cs . print ( cir , sym , logger ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
return 0 ;
}
2018-10-21 19:24:49 +03:00
2020-06-30 16:45:21 +03:00
// r1cs export json [circuit.r1cs] [circuit.json]
async function r1csExportJSON ( params , options ) {
const r1csName = params [ 0 ] || "circuit.r1cs" ;
const jsonName = params [ 1 ] || changeExt ( r1csName , "json" ) ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
const r1csObj = await r1cs . exportJson ( r1csName , logger ) ;
const S = JSON . stringify ( utils . stringifyBigInts ( r1csObj ) , null , 1 ) ;
await fs . promises . writeFile ( jsonName , S ) ;
2020-06-30 16:45:21 +03:00
return 0 ;
}
// wtns calculate <circuit.wasm> <input.json> <witness.wtns>
async function wtnsCalculate ( params , options ) {
2020-05-09 16:05:45 +03:00
const wasmName = params [ 0 ] || "circuit.wasm" ;
const inputName = params [ 1 ] || "input.json" ;
const witnessName = params [ 2 ] || "witness.wtns" ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
const input = unstringifyBigInts ( JSON . parse ( await fs . promises . readFile ( inputName , "utf8" ) ) ) ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
await wtns . calculate ( input , wasmName , witnessName , { } ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
return 0 ;
}
2018-10-21 19:24:49 +03:00
2020-06-30 16:45:21 +03:00
// wtns debug <circuit.wasm> <input.json> <witness.wtns> <circuit.sym>
2020-05-09 16:05:45 +03:00
// -get|g -set|s -trigger|t
2020-06-30 16:45:21 +03:00
async function wtnsDebug ( params , options ) {
2020-05-09 16:05:45 +03:00
const wasmName = params [ 0 ] || "circuit.wasm" ;
const inputName = params [ 1 ] || "input.json" ;
const witnessName = params [ 2 ] || "witness.wtns" ;
const symName = params [ 3 ] || changeExt ( wasmName , "sym" ) ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
const input = unstringifyBigInts ( JSON . parse ( await fs . promises . readFile ( inputName , "utf8" ) ) ) ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
await wtns . debug ( input , wasmName , witnessName , symName , options , logger ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
return 0 ;
}
2020-04-18 21:21:16 +03:00
2020-06-30 16:45:21 +03:00
// wtns export json [witness.wtns] [witness.json]
// -get|g -set|s -trigger|t
async function wtnsExportJson ( params , options ) {
const wtnsName = params [ 0 ] || "witness.wtns" ;
const jsonName = params [ 1 ] || "witness.json" ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
const w = await wtns . exportJson ( wtnsName ) ;
2020-06-30 16:45:21 +03:00
await fs . promises . writeFile ( jsonName , JSON . stringify ( stringifyBigInts ( w ) , null , 1 ) ) ;
return 0 ;
}
2020-07-11 11:31:52 +03:00
/ *
2020-05-09 16:05:45 +03:00
// zksnark setup [circuit.r1cs] [circuit.zkey] [verification_key.json]
async function zksnarkSetup ( params , options ) {
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
const r1csName = params [ 0 ] || "circuit.r1cs" ;
const zkeyName = params [ 1 ] || changeExt ( r1csName , "zkey" ) ;
const verificationKeyName = params [ 2 ] || "verification_key.json" ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
const protocol = options . protocol || "groth16" ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
const cir = await loadR1cs ( r1csName , true ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
if ( ! zkSnark [ protocol ] ) throw new Error ( "Invalid protocol" ) ;
const setup = zkSnark [ protocol ] . setup ( cir , options . verbose ) ;
2018-10-21 19:24:49 +03:00
2020-06-14 18:37:22 +03:00
await zkey . utils . write ( zkeyName , setup . vk _proof ) ;
2020-05-09 16:05:45 +03:00
// await fs.promises.writeFile(provingKeyName, JSON.stringify(stringifyBigInts(setup.vk_proof), null, 1), "utf-8");
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
await fs . promises . writeFile ( verificationKeyName , JSON . stringify ( stringifyBigInts ( setup . vk _verifier ) , null , 1 ) , "utf-8" ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
return 0 ;
}
2020-07-11 11:31:52 +03:00
* /
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
// groth16 prove [circuit.zkey] [witness.wtns] [proof.json] [public.json]
2020-07-13 08:21:03 +03:00
async function groth16Prove ( params , options ) {
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
const zkeyName = params [ 0 ] || "circuit.zkey" ;
const witnessName = params [ 1 ] || "witness.wtns" ;
const proofName = params [ 2 ] || "proof.json" ;
const publicName = params [ 3 ] || "public.json" ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2018-11-10 16:43:37 +03:00
2020-07-11 11:31:52 +03:00
const { proof , publicSignals } = await groth16 . prove ( zkeyName , witnessName , logger ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
await fs . promises . writeFile ( proofName , JSON . stringify ( stringifyBigInts ( proof ) , null , 1 ) , "utf-8" ) ;
await fs . promises . writeFile ( publicName , JSON . stringify ( stringifyBigInts ( publicSignals ) , null , 1 ) , "utf-8" ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
return 0 ;
}
2020-06-08 12:03:36 +03:00
2020-07-11 11:31:52 +03:00
// groth16 fullprove [input.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json]
2020-07-13 08:21:03 +03:00
async function groth16FullProve ( params , options ) {
2020-06-08 12:03:36 +03:00
2020-07-11 11:31:52 +03:00
const inputName = params [ 0 ] || "input.json" ;
const wasmName = params [ 1 ] || "circuit.wasm" ;
const zkeyName = params [ 2 ] || "circuit.zkey" ;
const proofName = params [ 3 ] || "proof.json" ;
const publicName = params [ 4 ] || "public.json" ;
2020-06-08 12:03:36 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2020-06-08 12:03:36 +03:00
2020-07-11 11:31:52 +03:00
const input = unstringifyBigInts ( JSON . parse ( await fs . promises . readFile ( inputName , "utf8" ) ) ) ;
2020-06-08 12:03:36 +03:00
2020-07-11 11:31:52 +03:00
const { proof , publicSignals } = await groth16 . fullProve ( input , wasmName , zkeyName , logger ) ;
2020-06-08 12:03:36 +03:00
await fs . promises . writeFile ( proofName , JSON . stringify ( stringifyBigInts ( proof ) , null , 1 ) , "utf-8" ) ;
await fs . promises . writeFile ( publicName , JSON . stringify ( stringifyBigInts ( publicSignals ) , null , 1 ) , "utf-8" ) ;
return 0 ;
}
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
// groth16 verify [verification_key.json] [public.json] [proof.json]
2020-07-13 08:21:03 +03:00
async function groth16Verify ( params , options ) {
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
const verificationKeyName = params [ 0 ] || "verification_key.json" ;
2020-07-11 11:31:52 +03:00
const publicName = params [ 1 ] || "public.json" ;
const proofName = params [ 2 ] || "proof.json" ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
const verificationKey = unstringifyBigInts ( JSON . parse ( fs . readFileSync ( verificationKeyName , "utf8" ) ) ) ;
const pub = unstringifyBigInts ( JSON . parse ( fs . readFileSync ( publicName , "utf8" ) ) ) ;
const proof = unstringifyBigInts ( JSON . parse ( fs . readFileSync ( proofName , "utf8" ) ) ) ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2018-10-21 19:24:49 +03:00
2020-07-13 08:21:03 +03:00
const isValid = await groth16 . verify ( verificationKey , pub , proof , logger ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
if ( isValid ) {
return 0 ;
} else {
return 1 ;
}
}
2018-11-10 16:43:37 +03:00
2020-06-08 12:03:36 +03:00
// zkey export vkey [circuit.zkey] [verification_key.json]",
2020-07-11 11:31:52 +03:00
async function zkeyExportVKey ( params , options ) {
2020-06-08 12:03:36 +03:00
const zkeyName = params [ 0 ] || "circuit.zkey" ;
const verificationKeyName = params [ 2 ] || "verification_key.json" ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
const vKey = await zkey . exportVerificationKey ( zkeyName ) ;
const S = JSON . stringify ( utils . stringifyBigInts ( vKey ) , null , 1 ) ;
await fs . promises . writeFile ( verificationKeyName , S ) ;
2020-06-08 12:03:36 +03:00
}
2020-06-14 18:37:22 +03:00
// zkey export json [circuit.zkey] [circuit.zkey.json]",
async function zkeyExportJson ( params , options ) {
const zkeyName = params [ 0 ] || "circuit.zkey" ;
const zkeyJsonName = params [ 1 ] || "circuit.zkey.json" ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
const zKey = await zkey . exportJson ( zkeyName , logger ) ;
const S = JSON . stringify ( utils . stringifyBigInts ( zKey ) , null , 1 ) ;
await fs . promises . writeFile ( zkeyJsonName , S ) ;
2020-06-14 18:37:22 +03:00
}
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
// solidity genverifier [circuit.zkey] [verifier.sol]
async function zkeyExportSolidityVerifier ( params , options ) {
let zkeyName ;
2020-05-09 16:05:45 +03:00
let verifierName ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
if ( params . length < 1 ) {
2020-07-11 11:31:52 +03:00
zkeyName = "circuit.zkey" ;
2020-05-09 16:05:45 +03:00
} else {
2020-07-11 11:31:52 +03:00
zkeyName = params [ 0 ] ;
2020-05-09 16:05:45 +03:00
}
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
if ( params . length < 2 ) {
verifierName = "verifier.sol" ;
} else {
verifierName = params [ 1 ] ;
}
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2020-05-09 16:05:45 +03:00
2020-07-13 09:47:02 +03:00
let templateName ;
2020-07-13 09:54:48 +03:00
try {
2020-07-13 09:47:02 +03:00
templateName = path . join ( _ _dirname , "templates" , "verifier_groth16.sol" ) ;
2020-07-13 09:54:48 +03:00
await fs . promises . stat ( templateName ) ;
} catch ( err ) {
2020-07-13 09:47:02 +03:00
templateName = path . join ( _ _dirname , ".." , "templates" , "verifier_groth16.sol" ) ;
}
2020-07-11 11:31:52 +03:00
const verifierCode = await zkey . exportSolidityVerifier ( zkeyName , templateName , logger ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
fs . writeFileSync ( verifierName , verifierCode , "utf-8" ) ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
return 0 ;
}
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
// solidity gencall <public.json> <proof.json>
2020-07-11 11:31:52 +03:00
async function zkeyExportSolidityCalldata ( params , options ) {
2020-05-09 16:05:45 +03:00
let publicName ;
let proofName ;
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
if ( params . length < 1 ) {
publicName = "public.json" ;
} else {
publicName = params [ 0 ] ;
}
2018-10-21 19:24:49 +03:00
2020-05-09 16:05:45 +03:00
if ( params . length < 2 ) {
proofName = "proof.json" ;
} else {
proofName = params [ 1 ] ;
}
2018-10-22 09:34:49 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2018-10-22 09:34:49 +03:00
2020-07-11 11:31:52 +03:00
const pub = unstringifyBigInts ( JSON . parse ( fs . readFileSync ( publicName , "utf8" ) ) ) ;
2020-05-09 16:05:45 +03:00
const proof = unstringifyBigInts ( JSON . parse ( fs . readFileSync ( proofName , "utf8" ) ) ) ;
2018-10-22 09:34:49 +03:00
2020-05-09 16:05:45 +03:00
let inputs = "" ;
2020-07-11 11:31:52 +03:00
for ( let i = 0 ; i < pub . length ; i ++ ) {
2020-05-09 16:05:45 +03:00
if ( inputs != "" ) inputs = inputs + "," ;
2020-07-11 11:31:52 +03:00
inputs = inputs + p256 ( pub [ i ] ) ;
2020-05-09 16:05:45 +03:00
}
2018-10-22 09:34:49 +03:00
2020-05-09 16:05:45 +03:00
let S ;
if ( ( typeof proof . protocol === "undefined" ) || ( proof . protocol == "original" ) ) {
S = ` [ ${ p256 ( proof . pi _a [ 0 ] ) } , ${ p256 ( proof . pi _a [ 1 ] ) } ], ` +
` [ ${ p256 ( proof . pi _ap [ 0 ] ) } , ${ p256 ( proof . pi _ap [ 1 ] ) } ], ` +
` [[ ${ p256 ( proof . pi _b [ 0 ] [ 1 ] ) } , ${ p256 ( proof . pi _b [ 0 ] [ 0 ] ) } ],[ ${ p256 ( proof . pi _b [ 1 ] [ 1 ] ) } , ${ p256 ( proof . pi _b [ 1 ] [ 0 ] ) } ]], ` +
` [ ${ p256 ( proof . pi _bp [ 0 ] ) } , ${ p256 ( proof . pi _bp [ 1 ] ) } ], ` +
` [ ${ p256 ( proof . pi _c [ 0 ] ) } , ${ p256 ( proof . pi _c [ 1 ] ) } ], ` +
` [ ${ p256 ( proof . pi _cp [ 0 ] ) } , ${ p256 ( proof . pi _cp [ 1 ] ) } ], ` +
` [ ${ p256 ( proof . pi _h [ 0 ] ) } , ${ p256 ( proof . pi _h [ 1 ] ) } ], ` +
` [ ${ p256 ( proof . pi _kp [ 0 ] ) } , ${ p256 ( proof . pi _kp [ 1 ] ) } ], ` +
` [ ${ inputs } ] ` ;
} else if ( ( proof . protocol == "groth16" ) || ( proof . protocol == "kimleeoh" ) ) {
S = ` [ ${ p256 ( proof . pi _a [ 0 ] ) } , ${ p256 ( proof . pi _a [ 1 ] ) } ], ` +
` [[ ${ p256 ( proof . pi _b [ 0 ] [ 1 ] ) } , ${ p256 ( proof . pi _b [ 0 ] [ 0 ] ) } ],[ ${ p256 ( proof . pi _b [ 1 ] [ 1 ] ) } , ${ p256 ( proof . pi _b [ 1 ] [ 0 ] ) } ]], ` +
` [ ${ p256 ( proof . pi _c [ 0 ] ) } , ${ p256 ( proof . pi _c [ 1 ] ) } ], ` +
` [ ${ inputs } ] ` ;
} else {
throw new Error ( "InvalidProof" ) ;
}
2018-10-22 09:34:49 +03:00
2020-05-09 16:05:45 +03:00
console . log ( S ) ;
2018-10-22 09:34:49 +03:00
2020-05-09 16:05:45 +03:00
return 0 ;
}
2018-10-22 09:34:49 +03:00
2020-06-30 16:45:21 +03:00
// powersoftau new <curve> <power> [powersoftau_0000.ptau]",
2020-05-09 16:05:45 +03:00
async function powersOfTawNew ( params , options ) {
2020-06-30 16:45:21 +03:00
let curveName ;
2020-05-09 16:05:45 +03:00
let power ;
2020-05-31 01:46:49 +03:00
let ptauName ;
2018-10-22 09:34:49 +03:00
2020-06-30 16:45:21 +03:00
curveName = params [ 0 ] ;
power = parseInt ( params [ 1 ] ) ;
2020-05-27 08:03:44 +03:00
if ( ( power < 1 ) || ( power > 28 ) ) {
throw new Error ( "Power must be between 1 and 28" ) ;
2020-05-09 16:05:45 +03:00
}
2018-10-22 09:34:49 +03:00
2020-06-30 16:45:21 +03:00
if ( params . length < 3 ) {
2020-05-31 01:46:49 +03:00
ptauName = "powersOfTaw" + power + "_0000.ptau" ;
2020-05-09 16:05:45 +03:00
} else {
2020-06-30 16:45:21 +03:00
ptauName = params [ 2 ] ;
2020-05-09 16:05:45 +03:00
}
2018-10-22 09:34:49 +03:00
2020-06-30 16:45:21 +03:00
const curve = await curves . getCurveFromName ( curveName ) ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
return await powersOfTaw . newAccumulator ( curve , power , ptauName , logger ) ;
2020-05-09 16:05:45 +03:00
}
2020-03-26 22:16:29 +03:00
2020-07-14 12:55:12 +03:00
async function powersOfTawExportChallenge ( params , options ) {
2020-05-31 01:46:49 +03:00
let ptauName ;
2020-07-14 12:55:12 +03:00
let challengeName ;
2020-03-26 22:16:29 +03:00
2020-05-31 01:46:49 +03:00
ptauName = params [ 0 ] ;
2020-03-26 22:16:29 +03:00
2020-05-09 16:05:45 +03:00
if ( params . length < 2 ) {
2020-07-14 12:55:12 +03:00
challengeName = "challenge" ;
2020-05-09 16:05:45 +03:00
} else {
2020-07-14 12:55:12 +03:00
challengeName = params [ 1 ] ;
2020-05-09 16:05:45 +03:00
}
2019-06-16 01:12:50 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2020-07-14 12:55:12 +03:00
return await powersOfTaw . exportChallenge ( ptauName , challengeName , logger ) ;
2020-05-09 16:05:45 +03:00
}
2018-10-21 19:24:49 +03:00
2020-07-14 12:55:12 +03:00
// powersoftau challenge contribute <curve> <challenge> [response]
async function powersOfTawChallengeContribute ( params , options ) {
let challengeName ;
2020-05-09 16:05:45 +03:00
let responseName ;
2018-10-21 19:24:49 +03:00
2020-06-30 16:45:21 +03:00
const curve = await curves . getCurveFromName ( params [ 0 ] ) ;
2018-10-21 19:24:49 +03:00
2020-07-14 12:55:12 +03:00
challengeName = params [ 1 ] ;
2020-06-18 20:14:06 +03:00
if ( params . length < 3 ) {
2020-07-14 12:55:12 +03:00
responseName = changeExt ( challengeName , "response" ) ;
2020-05-09 16:05:45 +03:00
} else {
2020-06-18 20:14:06 +03:00
responseName = params [ 2 ] ;
2018-10-21 19:24:49 +03:00
}
2020-05-09 16:05:45 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2020-07-14 12:55:12 +03:00
return await powersOfTaw . challengeContribute ( curve , challengeName , responseName , options . entropy , logger ) ;
2018-10-21 19:24:49 +03:00
}
2020-05-11 21:23:04 +03:00
async function powersOfTawImport ( params , options ) {
let oldPtauName ;
let response ;
let newPtauName ;
let importPoints = true ;
let doCheck = true ;
oldPtauName = params [ 0 ] ;
response = params [ 1 ] ;
newPtauName = params [ 2 ] ;
if ( options . nopoints ) importPoints = false ;
if ( options . nocheck ) doCheck = false ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
const res = await powersOfTaw . importResponse ( oldPtauName , response , newPtauName , options . name , importPoints , logger ) ;
2020-05-11 21:23:04 +03:00
if ( res ) return res ;
if ( ! doCheck ) return ;
// TODO Verify
}
async function powersOfTawVerify ( params , options ) {
let ptauName ;
ptauName = params [ 0 ] ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
const res = await powersOfTaw . verify ( ptauName , logger ) ;
2020-06-14 18:37:22 +03:00
if ( res === true ) {
2020-05-26 19:45:49 +03:00
return 0 ;
2020-05-11 21:23:04 +03:00
} else {
2020-05-26 19:45:49 +03:00
return 1 ;
2020-05-11 21:23:04 +03:00
}
}
2020-05-15 22:30:37 +03:00
async function powersOfTawBeacon ( params , options ) {
let oldPtauName ;
let newPtauName ;
let beaconHashStr ;
let numIterationsExp ;
oldPtauName = params [ 0 ] ;
newPtauName = params [ 1 ] ;
beaconHashStr = params [ 2 ] ;
numIterationsExp = params [ 3 ] ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
return await powersOfTaw . beacon ( oldPtauName , newPtauName , options . name , beaconHashStr , numIterationsExp , logger ) ;
2020-05-15 22:30:37 +03:00
}
async function powersOfTawContribute ( params , options ) {
let oldPtauName ;
let newPtauName ;
oldPtauName = params [ 0 ] ;
newPtauName = params [ 1 ] ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
return await powersOfTaw . contribute ( oldPtauName , newPtauName , options . name , options . entropy , logger ) ;
2020-05-15 22:30:37 +03:00
}
2020-05-26 19:45:49 +03:00
async function powersOfTawPreparePhase2 ( params , options ) {
let oldPtauName ;
let newPtauName ;
2020-05-11 21:23:04 +03:00
2020-05-26 19:45:49 +03:00
oldPtauName = params [ 0 ] ;
newPtauName = params [ 1 ] ;
2018-10-21 19:24:49 +03:00
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
return await powersOfTaw . preparePhase2 ( oldPtauName , newPtauName , logger ) ;
2019-06-16 01:12:50 +03:00
}
2018-10-21 19:24:49 +03:00
2020-06-14 18:37:22 +03:00
// powersoftau export json <powersoftau_0000.ptau> <powersoftau_0000.json>",
async function powersOfTawExportJson ( params , options ) {
let ptauName ;
let jsonName ;
ptauName = params [ 0 ] ;
jsonName = params [ 1 ] ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
const pTau = await powersOfTaw . exportJson ( ptauName , logger ) ;
const S = JSON . stringify ( stringifyBigInts ( pTau ) , null , 1 ) ;
await fs . promises . writeFile ( jsonName , S ) ;
2020-06-14 18:37:22 +03:00
}
2020-05-31 01:46:49 +03:00
// phase2 new <circuit.r1cs> <powersoftau.ptau> <circuit.zkey>
2020-06-14 18:37:22 +03:00
async function zkeyNew ( params , options ) {
2020-05-31 01:46:49 +03:00
let r1csName ;
let ptauName ;
let zkeyName ;
if ( params . length < 1 ) {
r1csName = "circuit.r1cs" ;
} else {
r1csName = params [ 0 ] ;
}
if ( params . length < 2 ) {
ptauName = "powersoftau.ptau" ;
} else {
ptauName = params [ 1 ] ;
}
2020-06-18 20:14:06 +03:00
if ( params . length < 3 ) {
2020-05-31 01:46:49 +03:00
zkeyName = "circuit.zkey" ;
} else {
zkeyName = params [ 2 ] ;
}
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
return zkey . newZKey ( r1csName , ptauName , zkeyName , logger ) ;
2020-05-31 01:46:49 +03:00
}
2020-06-14 18:37:22 +03:00
// zkey export bellman [circuit.zkey] [circuit.mpcparams]
async function zkeyExportBellman ( params , options ) {
let zkeyName ;
let mpcparamsName ;
if ( params . length < 1 ) {
zkeyName = "circuit.zkey" ;
} else {
zkeyName = params [ 0 ] ;
}
if ( params . length < 2 ) {
mpcparamsName = "circuit.mpcparams" ;
} else {
mpcparamsName = params [ 1 ] ;
}
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
return zkey . exportBellman ( zkeyName , mpcparamsName , logger ) ;
2020-06-14 18:37:22 +03:00
}
// zkey import bellman <circuit_old.zkey> <circuit.mpcparams> <circuit_new.zkey>
async function zkeyImportBellman ( params , options ) {
let zkeyNameOld ;
let mpcParamsName ;
let zkeyNameNew ;
zkeyNameOld = params [ 0 ] ;
mpcParamsName = params [ 1 ] ;
zkeyNameNew = params [ 2 ] ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
return zkey . importBellman ( zkeyNameOld , mpcParamsName , zkeyNameNew , options . name , logger ) ;
2020-06-14 18:37:22 +03:00
}
// phase2 verify [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]
async function zkeyVerify ( params , options ) {
let r1csName ;
let ptauName ;
let zkeyName ;
if ( params . length < 1 ) {
r1csName = "circuit.r1cs" ;
} else {
r1csName = params [ 0 ] ;
}
if ( params . length < 2 ) {
ptauName = "powersoftau.ptau" ;
} else {
ptauName = params [ 1 ] ;
}
if ( params . length < 3 ) {
zkeyName = "circuit.zkey" ;
} else {
zkeyName = params [ 2 ] ;
}
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
const res = await zkey . verify ( r1csName , ptauName , zkeyName , logger ) ;
2020-06-14 18:37:22 +03:00
if ( res === true ) {
return 0 ;
} else {
return 1 ;
}
}
2020-06-16 17:45:32 +03:00
// zkey contribute <circuit_old.zkey> <circuit_new.zkey>
2020-06-14 18:37:22 +03:00
async function zkeyContribute ( params , options ) {
let zkeyOldName ;
let zkeyNewName ;
zkeyOldName = params [ 0 ] ;
zkeyNewName = params [ 1 ] ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2020-06-14 18:37:22 +03:00
2020-07-11 11:31:52 +03:00
return zkey . contribute ( zkeyOldName , zkeyNewName , options . name , options . entropy , logger ) ;
2020-06-14 18:37:22 +03:00
}
2020-06-18 20:14:06 +03:00
// zkey beacon <circuit_old.zkey> <circuit_new.zkey> <beaconHash(Hex)> <numIterationsExp>
async function zkeyBeacon ( params , options ) {
let zkeyOldName ;
let zkeyNewName ;
let beaconHashStr ;
let numIterationsExp ;
zkeyOldName = params [ 0 ] ;
zkeyNewName = params [ 1 ] ;
beaconHashStr = params [ 2 ] ;
numIterationsExp = params [ 3 ] ;
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
return await zkey . beacon ( zkeyOldName , zkeyNewName , options . name , beaconHashStr , numIterationsExp , logger ) ;
2020-06-18 20:14:06 +03:00
}
2020-07-14 12:55:12 +03:00
// zkey challenge contribute <curve> <challenge> [response]",
2020-07-11 11:31:52 +03:00
async function zkeyBellmanContribute ( params , options ) {
2020-07-14 12:55:12 +03:00
let challengeName ;
2020-06-18 20:14:06 +03:00
let responseName ;
2020-06-30 22:39:25 +03:00
const curve = await curves . getCurveFromName ( params [ 0 ] ) ;
2020-06-18 20:14:06 +03:00
2020-07-14 12:55:12 +03:00
challengeName = params [ 1 ] ;
2020-06-18 20:14:06 +03:00
if ( params . length < 3 ) {
2020-07-14 12:55:12 +03:00
responseName = changeExt ( challengeName , "response" ) ;
2020-06-18 20:14:06 +03:00
} else {
responseName = params [ 2 ] ;
}
2020-07-11 11:31:52 +03:00
if ( options . verbose ) Logger . setLogLevel ( "DEBUG" ) ;
2020-07-14 12:55:12 +03:00
return zkey . bellmanContribute ( curve , challengeName , responseName , options . entropy , logger ) ;
2020-06-18 20:14:06 +03:00
}