From a4da81f0a7ba17896935bfc6b18cdc90bea2c133 Mon Sep 17 00:00:00 2001 From: Jordi Baylina Date: Sun, 14 Jun 2020 17:37:22 +0200 Subject: [PATCH] phase2 verification done --- cli.js | 194 +++++++-- src/binfileutils.js | 17 + src/groth16_prover.js | 6 +- src/keypair.js | 27 +- src/misc.js | 48 +++ src/phase2.js | 3 - src/powersoftau.js | 5 +- src/powersoftau_beacon.js | 212 +++++----- src/powersoftau_challangecontribute.js | 8 +- src/powersoftau_contribute.js | 8 +- ...port.js => powersoftau_exportchallange.js} | 9 +- src/powersoftau_exportjson.js | 73 ++++ src/powersoftau_import.js | 7 +- src/powersoftau_new.js | 17 +- src/powersoftau_utils.js | 28 -- src/powersoftau_verify.js | 22 +- src/prover_groth16.js | 2 +- src/prover_kimleeoh.js | 4 +- src/setup_groth16.js | 12 +- src/setup_kimleeoh.js | 14 +- src/soliditygenerator.js | 12 +- src/verifier_groth16.js | 2 +- src/verifier_kimleeoh.js | 2 +- src/zkey.js | 10 + src/zkey_beacon.js | 5 + src/zkey_contribute.js | 4 + src/zkey_export_bellman.js | 137 +++++++ src/zkey_export_json.js | 12 + src/zkey_import_bellman.js | 181 +++++++++ src/{phase2_new.js => zkey_new.js} | 147 ++++++- src/{zkeyfile.js => zkey_utils.js} | 198 +++++---- src/zkey_verify.js | 376 ++++++++++++++++++ 32 files changed, 1475 insertions(+), 327 deletions(-) delete mode 100644 src/phase2.js rename src/{powersoftau_export.js => powersoftau_exportchallange.js} (91%) create mode 100644 src/powersoftau_exportjson.js create mode 100644 src/zkey.js create mode 100644 src/zkey_beacon.js create mode 100644 src/zkey_contribute.js create mode 100644 src/zkey_export_bellman.js create mode 100644 src/zkey_export_json.js create mode 100644 src/zkey_import_bellman.js rename src/{phase2_new.js => zkey_new.js} (74%) rename src/{zkeyfile.js => zkey_utils.js} (64%) create mode 100644 src/zkey_verify.js diff --git a/cli.js b/cli.js index a49ac3b..a7ee5bc 100755 --- a/cli.js +++ b/cli.js @@ -30,7 +30,6 @@ const {stringifyBigInts, unstringifyBigInts} = require("ffjavascript").utils; const loadR1cs = require("r1csfile").load; const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder; -const zkeyFile = require("./src/zkeyfile"); const wtnsFile = require("./src/wtnsfile"); const loadSyms = require("./src/loadsyms"); @@ -43,12 +42,12 @@ const powersOfTaw = require("./src/powersoftau"); const bn128 = require("ffjavascript").bn128; const solidityGenerator = require("./src/soliditygenerator.js"); -const phase2 = require("./src/phase2"); const Scalar = require("ffjavascript").Scalar; const assert = require("assert"); const groth16Prover = require("./src/groth16_prover"); +const zkey = require("./src/zkey"); const commands = [ { @@ -97,12 +96,6 @@ const commands = [ alias: ["zv", "verify -vk|verificationkey -pub|public -p|proof"], action: zksnarkVerify }, - { - cmd: "zkey export vkey [circuit.zkey] [verification_key.json]", - description: "Exports a verification key to JSON", - alias: ["zkev"], - action: zKeyExportVKey - }, { cmd: "solidity genverifier ", description: "Creates a verifier in solidity", @@ -125,7 +118,7 @@ const commands = [ { cmd: "powersoftau export challange [challange]", description: "Creates a challange", - alias: ["pte"], + alias: ["ptec"], options: "-verbose|v", action: powersOfTawExportChallange }, @@ -159,7 +152,7 @@ const commands = [ }, { cmd: "powersoftau contribute ", - description: "verifies a powers of tau file", + description: "creates a ptau file with a new contribution", alias: ["ptc"], options: "-verbose|v -name|n -entropy|e", action: powersOfTawContribute @@ -173,11 +166,59 @@ const commands = [ action: powersOfTawPreparePhase2 }, { - cmd: "phase2 new [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]", - description: "Creates an initial pkey file with zero contributions ", - alias: ["p2n"], + cmd: "powersoftau export json ", + description: "Exports a power of tau file to a JSON", + alias: ["ptej"], options: "-verbose|v", - action: phase2new + action: powersOfTawExportJson + }, + { + cmd: "zkey new [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]", + description: "Creates an initial pkey file with zero contributions ", + alias: ["zkn"], + options: "-verbose|v", + action: zkeyNew + }, + { + 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 + }, + { + cmd: "zkey import bellman ", + description: "Export a zKey to a MPCParameters file compatible with kobi/phase2 (Bellman) ", + alias: ["zkib"], + options: "-verbose|v", + action: zkeyImportBellman + }, + { + 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 + }, + { + cmd: "zkey contribute ", + description: "creates a zkey file with a new contribution", + alias: ["zkc"], + options: "-verbose|v", + action: zkeyContribute + }, + { + cmd: "zkey export vkey [circuit.zkey] [verification_key.json]", + 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"], + options: "-verbose|v", + action: zkeyExportJson }, ]; @@ -224,12 +265,6 @@ TODO COMMANDS action: witnessVerify }, -ptau new Starts a ceremony with a new challange for the powes of Tau ceremony -ptau contribute Contribute in the ceremony of powers of tau -ptau beacon Apply a beacon random to the ceremony -ptau verify Verify the powers of tau ceremony -ptau preparePhase2 Prepare Powers of Taus for a phase 2 -phase2 new Starts a second phase ceremony for a given circuit with a first challange and a reference Hash. phase2 constribute Contribute in the seconf phase ceremony phase2 beacon Contribute in the seconf phase ceremony with a Powers of Tau phase2 verify Verify the Powers of tau @@ -374,7 +409,7 @@ async function zksnarkSetup(params, options) { if (!zkSnark[protocol]) throw new Error("Invalid protocol"); const setup = zkSnark[protocol].setup(cir, options.verbose); - await zkeyFile.write(zkeyName, setup.vk_proof); + await zkey.utils.write(zkeyName, setup.vk_proof); // await fs.promises.writeFile(provingKeyName, JSON.stringify(stringifyBigInts(setup.vk_proof), null, 1), "utf-8"); await fs.promises.writeFile(verificationKeyName, JSON.stringify(stringifyBigInts(setup.vk_verifier), null, 1), "utf-8"); @@ -453,12 +488,11 @@ async function zksnarkVerify(params, options) { } // zkey export vkey [circuit.zkey] [verification_key.json]", -async function zKeyExportVKey(params) { +async function zkeyExportVKey(params) { const zkeyName = params[0] || "circuit.zkey"; const verificationKeyName = params[2] || "verification_key.json"; - const zKey = await zkeyFile.read(zkeyName); - + const zKey = await zkey.utils.read(zkeyName); let curve; if (Scalar.eq(zKey.q, bn128.q)) { @@ -472,19 +506,26 @@ async function zKeyExportVKey(params) { IC: zKey.IC, - vk_alfa_1: zKey.vk_alfa_1, + vk_alpha_1: zKey.vk_alpha_1, vk_beta_2: zKey.vk_beta_2, vk_gamma_2: zKey.vk_gamma_2, vk_delta_2: zKey.vk_delta_2, - vk_alfabeta_12: curve.pairing( zKey.vk_alfa_1 , zKey.vk_beta_2 ) + vk_alphabeta_12: curve.pairing( zKey.vk_alpha_1 , zKey.vk_beta_2 ) }; await fs.promises.writeFile(verificationKeyName, JSON.stringify(stringifyBigInts(vKey), null, 1), "utf-8"); } +// 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"; + + return await zkey.exportJson(zkeyName, zkeyJsonName, options.verbose); +} // solidity genverifier async function solidityGenVerifier(params, options) { @@ -638,7 +679,7 @@ async function powersOfTawImport(params, options) { if (options.nopoints) importPoints = false; if (options.nocheck) doCheck = false; - const res = await powersOfTaw.impoertResponse(oldPtauName, response, newPtauName, options.name, importPoints, options.verbose); + const res = await powersOfTaw.importResponse(oldPtauName, response, newPtauName, options.name, importPoints, options.verbose); if (res) return res; if (!doCheck) return; @@ -652,7 +693,7 @@ async function powersOfTawVerify(params, options) { ptauName = params[0]; const res = await powersOfTaw.verify(ptauName, options.verbose); - if (res) { + if (res === true) { console.log("Powers of tau OK!"); return 0; } else { @@ -695,9 +736,20 @@ async function powersOfTawPreparePhase2(params, options) { return await powersOfTaw.preparePhase2(oldPtauName, newPtauName, options.verbose); } +// powersoftau export json ", +async function powersOfTawExportJson(params, options) { + let ptauName; + let jsonName; + + ptauName = params[0]; + jsonName = params[1]; + + return await powersOfTaw.exportJson(ptauName, jsonName, options.verbose); +} + // phase2 new -async function phase2new(params, options) { +async function zkeyNew(params, options) { let r1csName; let ptauName; let zkeyName; @@ -722,3 +774,87 @@ async function phase2new(params, options) { return phase2.new(r1csName, ptauName, zkeyName, options.verbose); } + +// 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]; + } + + return phase2.exportMPCParams(zkeyName, mpcparamsName, options.verbose); + +} + + +// zkey import bellman +async function zkeyImportBellman(params, options) { + let zkeyNameOld; + let mpcParamsName; + let zkeyNameNew; + + zkeyNameOld = params[0]; + mpcParamsName = params[1]; + zkeyNameNew = params[2]; + + return zkey.importBellman(zkeyNameOld, mpcParamsName, zkeyNameNew, options.verbose); +} + +// 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]; + } + + const res = await zkey.verify(r1csName, ptauName, zkeyName, options.verbose); + if (res === true) { + console.log("zKey OK!"); + return 0; + } else { + console.log("=======>INVALID zKey<=========="); + return 1; + } + +} + + +// phase2 contribute + +async function zkeyContribute(params, options) { + let zkeyOldName; + let zkeyNewName; + + zkeyOldName = params[0]; + zkeyNewName = params[1]; + + + return phase2.contribute(zkeyOldName, zkeyNewName, options.verbose); +} diff --git a/src/binfileutils.js b/src/binfileutils.js index 725ec72..890e397 100644 --- a/src/binfileutils.js +++ b/src/binfileutils.js @@ -118,6 +118,22 @@ async function readFullSection(fd, sections, idSection) { return res; } +async function sectionIsEqual(fd1, sections1, fd2, sections2, idSection) { + const MAX_BUFF_SIZE = fd1.pageSize * 16; + await startReadUniqueSection(fd1, sections1, idSection); + await startReadUniqueSection(fd2, sections2, idSection); + if (sections1[idSection][0].size != sections2[idSection][0].size) return false; + const totalBytes=sections1[idSection][0].size; + for (let i=0; i0) S += "\n"; + S += "\t\t"; + for (let j=0; j<4; j++) { + if (j>0) S += " "; + S += a.getUint32(i*16+j*4).toString(16).padStart(8, "0"); + } + } + return S; +} + +function hashIsEqual(h1, h2) { + if (h1.byteLength != h2.byteLength) return false; + var dv1 = new Int8Array(h1); + var dv2 = new Int8Array(h2); + for (var i = 0 ; i != h1.byteLength ; i++) + { + if (dv1[i] != dv2[i]) return false; + } + return true; +} + +function cloneHasher(h) { + const ph = h.getPartialHash(); + const res = Blake2b(64); + res.setPartialHash(ph); + return res; +} + +async function sameRatio(curve, g1s, g1sx, g2s, g2sx) { + if (curve.G1.isZero(g1s)) return false; + if (curve.G1.isZero(g1sx)) return false; + if (curve.G2.isZero(g2s)) return false; + if (curve.G2.isZero(g2sx)) return false; + // return curve.F12.eq(curve.pairing(g1s, g2sx), curve.pairing(g1sx, g2s)); + const res = await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); + return res; +} + module.exports.bitReverse = bitReverse; module.exports.log2 = log2; +module.exports.formatHash = formatHash; +module.exports.hashIsEqual = hashIsEqual; +module.exports.cloneHasher = cloneHasher; +module.exports.sameRatio = sameRatio; diff --git a/src/phase2.js b/src/phase2.js deleted file mode 100644 index 3bd56ab..0000000 --- a/src/phase2.js +++ /dev/null @@ -1,3 +0,0 @@ - - -module.exports.new = require("./phase2_new.js"); diff --git a/src/powersoftau.js b/src/powersoftau.js index 5263bd6..2410bf9 100644 --- a/src/powersoftau.js +++ b/src/powersoftau.js @@ -1,10 +1,11 @@ module.exports.newAccumulator = require("./powersoftau_new"); -module.exports.exportChallange = require("./powersoftau_export"); +module.exports.exportChallange = require("./powersoftau_exportchallange"); module.exports.challangeContribute = require("./powersoftau_challangecontribute"); -module.exports.impoertResponse = require("./powersoftau_import"); +module.exports.importResponse = require("./powersoftau_import"); module.exports.verify = require("./powersoftau_verify"); module.exports.challangeContribute = require("./powersoftau_challangecontribute"); module.exports.beacon = require("./powersoftau_beacon"); module.exports.contribute = require("./powersoftau_contribute"); module.exports.preparePhase2 = require("./powersoftau_preparephase2"); +module.exports.exportJson = require("./powersoftau_exportjson"); diff --git a/src/powersoftau_beacon.js b/src/powersoftau_beacon.js index db8745e..e1252ab 100644 --- a/src/powersoftau_beacon.js +++ b/src/powersoftau_beacon.js @@ -1,6 +1,7 @@ const Blake2b = require("blake2b-wasm"); const utils = require("./powersoftau_utils"); -const applyKey = require("./mpc_applykey"); +const misc = require("./misc"); +const binFileUtils = require("./binfileutils"); function hex2ByteArray(s) { return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function (h) { @@ -27,12 +28,19 @@ async function beacon(oldPtauFilename, newPTauFilename, name, numIterationsExp, return false; } + await Blake2b.ready(); - const {fd: fdOld, sections} = await utils.readBinFile(oldPtauFilename, "ptau", 1); - const {curve, power} = await utils.readPTauHeader(fdOld, sections); + const {fd: fdOld, sections} = await binFileUtils.readBinFile(oldPtauFilename, "ptau", 1); + const {curve, power, ceremonyPower} = await utils.readPTauHeader(fdOld, sections); + if (power != ceremonyPower) { + throw new Error("This file has been reduced. You cannot contribute into a reduced file."); + } + if (sections[12]) { + console.log("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again."); + } const contributions = await utils.readContributions(fdOld, curve, sections); - const currentContribution = { + const curContribution = { name: name, type: 1, // Beacon numIterationsExp: numIterationsExp, @@ -44,124 +52,130 @@ async function beacon(oldPtauFilename, newPTauFilename, name, numIterationsExp, if (contributions.length>0) { lastChallangeHash = contributions[contributions.length-1].nextChallange; } else { - lastChallangeHash = utils.calculateFirstChallangeHash(curve, power); + lastChallangeHash = utils.calculateFirstChallangeHash(curve, power, verbose); } - currentContribution.key = utils.keyFromBeacon(curve, lastChallangeHash, beaconHash, numIterationsExp); - - const fdNew = await utils.createBinFile(newPTauFilename, "ptau", 1, 7); - await utils.writePTauHeader(fdNew, curve, power); - - const newChallangeHasher = new Blake2b(64); - newChallangeHasher.update(lastChallangeHash); + curContribution.key = utils.keyFromBeacon(curve, lastChallangeHash, beaconHash, numIterationsExp); const responseHasher = new Blake2b(64); responseHasher.update(lastChallangeHash); - currentContribution.tauG1 = (await applyKey({ - fdFrom: fdOld, - sections, - curve, - fdTo: fdNew, - sectionId: 2, - NPoints: (1 << power) * 2 -1, - G: "G1", - first: curve.Fr.one, - inc: currentContribution.key.tau.prvKey, - newChallangeHasher, - responseHasher, - returnPoints: [1], - sectionName: "tauG1", - verbose - }))[0]; + const fdNew = await binFileUtils.createBinFile(newPTauFilename, "ptau", 1, 7); + await utils.writePTauHeader(fdNew, curve, power); - currentContribution.tauG2 = (await applyKey({ - fdFrom: fdOld, - sections, - curve, - fdTo: fdNew, - sectionId: 3, - NPoints: 1 << power, - G: "G2", - first: curve.Fr.one, - inc: currentContribution.key.tau.prvKey, - newChallangeHasher, - responseHasher, - returnPoints: [1], - sectionName: "tauG2", - verbose - }))[0]; + const startSections = []; - currentContribution.alphaG1 = (await applyKey({ - fdFrom: fdOld, - sections, - curve, - fdTo: fdNew, - sectionId: 4, - NPoints: 1 << power, - G: "G1", - first: currentContribution.key.alpha.prvKey, - inc: currentContribution.key.tau.prvKey, - newChallangeHasher, - responseHasher, - returnPoints: [0], - sectionName: "alphaTauG1", - verbose - }))[0]; + let firstPoints; + firstPoints = await processSection(2, "G1", (1<0) S += "\n"; - S += "\t\t"; - for (let j=0; j<4; j++) { - if (j>0) S += " "; - S += a.getUint32(i*16+j*4).toString(16).padStart(8, "0"); - } - } - return S; -} - -function hashIsEqual(h1, h2) { - if (h1.byteLength != h2.byteLength) return false; - var dv1 = new Int8Array(h1); - var dv2 = new Int8Array(h2); - for (var i = 0 ; i != h1.byteLength ; i++) - { - if (dv1[i] != dv2[i]) return false; - } - return true; -} - function calculateFirstChallangeHash(curve, power, verbose) { if (verbose) console.log("Calculating First Challange Hash"); @@ -405,10 +379,8 @@ module.exports.readPTauHeader = readPTauHeader; module.exports.writePTauHeader = writePTauHeader; module.exports.readPtauPubKey = readPtauPubKey; module.exports.writePtauPubKey = writePtauPubKey; -module.exports.formatHash = formatHash; module.exports.readContributions = readContributions; module.exports.writeContributions = writeContributions; -module.exports.hashIsEqual = hashIsEqual; module.exports.calculateFirstChallangeHash = calculateFirstChallangeHash; module.exports.toPtauPubKeyRpr = toPtauPubKeyRpr; module.exports.fromPtauPubKeyRpr = fromPtauPubKeyRpr; diff --git a/src/powersoftau_verify.js b/src/powersoftau_verify.js index 41398c5..684753d 100644 --- a/src/powersoftau_verify.js +++ b/src/powersoftau_verify.js @@ -5,16 +5,8 @@ const assert = require("assert"); const crypto = require("crypto"); const binFileUtils = require("./binfileutils"); const ChaCha = require("ffjavascript").ChaCha; - -async function sameRatio(curve, g1s, g1sx, g2s, g2sx) { - if (curve.G1.isZero(g1s)) return false; - if (curve.G1.isZero(g1sx)) return false; - if (curve.G2.isZero(g2s)) return false; - if (curve.G2.isZero(g2sx)) return false; - // return curve.F12.eq(curve.pairing(g1s, g2sx), curve.pairing(g1sx, g2s)); - const res = await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s); - return res; -} +const misc = require("./misc"); +const sameRatio = misc.sameRatio; async function verifyContribution(curve, cur, prev) { let sr; @@ -235,14 +227,14 @@ async function verify(tauFilename, verbose) { const nextContributionHash = nextContributionHasher.digest(); // Check the nextChallangeHash - if (!utils.hashIsEqual(nextContributionHash,curContr.nextChallange)) { + if (!misc.hashIsEqual(nextContributionHash,curContr.nextChallange)) { console.log("Hash of the values does not match the next challange of the last contributor in the contributions section"); return false; } if (verbose) { console.log("Next challange hash: "); - console.log(utils.formatHash(nextContributionHash)); + console.log(misc.formatHash(nextContributionHash)); } // Verify Previous contributions @@ -280,7 +272,7 @@ async function verify(tauFilename, verbose) { console.log("-----------------------------------------------------"); console.log(`Contribution #${curContr.id}: ${curContr.name ||""}`); console.log("\tBased on challange"); - console.log(utils.formatHash(prevContr.nextChallange)); + console.log(misc.formatHash(prevContr.nextChallange)); const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3); utils.toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false); @@ -291,10 +283,10 @@ async function verify(tauFilename, verbose) { const responseHash = responseHasher.digest(); console.log("\tResponse Hash"); - console.log(utils.formatHash(responseHash)); + console.log(misc.formatHash(responseHash)); console.log("\tNext Challange"); - console.log(utils.formatHash(curContr.nextChallange)); + console.log(misc.formatHash(curContr.nextChallange)); } async function processSectionBetaG2() { diff --git a/src/prover_groth16.js b/src/prover_groth16.js index e790755..e81eab4 100644 --- a/src/prover_groth16.js +++ b/src/prover_groth16.js @@ -70,7 +70,7 @@ module.exports = function genProof(vk_proof, witness, verbose) { if ((verbose)&&(s%1000 == 1)) console.log("C: ", s); } - proof.pi_a = G1.add( proof.pi_a, vk_proof.vk_alfa_1 ); + proof.pi_a = G1.add( proof.pi_a, vk_proof.vk_alpha_1 ); proof.pi_a = G1.add( proof.pi_a, G1.mulScalar( vk_proof.vk_delta_1, r )); proof.pi_b = G2.add( proof.pi_b, vk_proof.vk_beta_2 ); diff --git a/src/prover_kimleeoh.js b/src/prover_kimleeoh.js index 39b9d25..bbb29a7 100644 --- a/src/prover_kimleeoh.js +++ b/src/prover_kimleeoh.js @@ -73,10 +73,10 @@ module.exports = function genProof(vk_proof, witness) { proof.pi_c = G1.add( proof.pi_c, G1.mulScalar( vk_proof.C[s], witness[s])); } - proof.pi_a = G1.add( proof.pi_a, vk_proof.vk_alfa_1 ); + proof.pi_a = G1.add( proof.pi_a, vk_proof.vk_alpha_1 ); proof.pi_a = G1.add( proof.pi_a, G1.mulScalar( G1.g, r )); - piadelta = G1.add( piadelta, vk_proof.vk_alfadelta_1); + piadelta = G1.add( piadelta, vk_proof.vk_alphadelta_1); piadelta = G1.add( piadelta, G1.mulScalar( vk_proof.vk_delta_1, r )); proof.pi_b = G2.add( proof.pi_b, vk_proof.vk_beta_2 ); diff --git a/src/setup_groth16.js b/src/setup_groth16.js index a97e921..7c39d3c 100644 --- a/src/setup_groth16.js +++ b/src/setup_groth16.js @@ -53,13 +53,13 @@ module.exports = function setup(circuit, verbose) { IC: setup.vk_proof.IC, - vk_alfa_1: setup.vk_proof.vk_alfa_1, + vk_alpha_1: setup.vk_proof.vk_alpha_1, vk_beta_2: setup.vk_proof.vk_beta_2, vk_gamma_2: setup.vk_proof.vk_gamma_2, vk_delta_2: setup.vk_proof.vk_delta_2, - vk_alfabeta_12: bn128.pairing( setup.vk_proof.vk_alfa_1 , setup.vk_proof.vk_beta_2 ) + vk_alphabeta_12: bn128.pairing( setup.vk_proof.vk_alpha_1 , setup.vk_proof.vk_beta_2 ) }; return setup; @@ -157,7 +157,7 @@ function calculateEncriptedValuesAtT(setup, circuit, verbose) { setup.vk_proof.C = new Array(circuit.nVars); setup.vk_proof.IC = new Array(circuit.nPubInputs + circuit.nOutputs + 1); - setup.toxic.kalfa = F.random(); + setup.toxic.kalpha = F.random(); setup.toxic.kbeta = F.random(); setup.toxic.kgamma = F.random(); setup.toxic.kdelta = F.random(); @@ -165,7 +165,7 @@ function calculateEncriptedValuesAtT(setup, circuit, verbose) { let invDelta = F.inv(setup.toxic.kdelta); let invGamma = F.inv(setup.toxic.kgamma); - setup.vk_proof.vk_alfa_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kalfa)); + setup.vk_proof.vk_alpha_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kalpha)); setup.vk_proof.vk_beta_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kbeta)); setup.vk_proof.vk_delta_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kdelta)); @@ -199,7 +199,7 @@ function calculateEncriptedValuesAtT(setup, circuit, verbose) { F.add( F.add( F.mul(v.a_t[s], setup.toxic.kbeta), - F.mul(v.b_t[s], setup.toxic.kalfa)), + F.mul(v.b_t[s], setup.toxic.kalpha)), v.c_t[s])); const IC = G1.mulScalar(G1.g, ps); @@ -213,7 +213,7 @@ function calculateEncriptedValuesAtT(setup, circuit, verbose) { F.add( F.add( F.mul(v.a_t[s], setup.toxic.kbeta), - F.mul(v.b_t[s], setup.toxic.kalfa)), + F.mul(v.b_t[s], setup.toxic.kalpha)), v.c_t[s])); const C = G1.mulScalar(G1.g, ps); setup.vk_proof.C[s]=C; diff --git a/src/setup_kimleeoh.js b/src/setup_kimleeoh.js index 2e0b0bc..c79f78a 100644 --- a/src/setup_kimleeoh.js +++ b/src/setup_kimleeoh.js @@ -128,28 +128,28 @@ function calculateEncriptedValuesAtT(setup, circuit) { setup.vk_proof.C = new Array(circuit.nVars); setup.vk_verifier.IC = new Array(circuit.nPubInputs + circuit.nOutputs + 1); - setup.toxic.kalfa = F.random(); + setup.toxic.kalpha = F.random(); setup.toxic.kbeta = F.random(); setup.toxic.kgamma = F.random(); setup.toxic.kdelta = F.random(); const gammaSquare = F.mul(setup.toxic.kgamma, setup.toxic.kgamma); - setup.vk_proof.vk_alfa_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kalfa)); + setup.vk_proof.vk_alpha_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kalpha)); setup.vk_proof.vk_beta_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kbeta)); setup.vk_proof.vk_delta_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kdelta)); - setup.vk_proof.vk_alfadelta_1 = G1.affine(G1.mulScalar( G1.g, F.mul(setup.toxic.kalfa, setup.toxic.kdelta))); + setup.vk_proof.vk_alphadelta_1 = G1.affine(G1.mulScalar( G1.g, F.mul(setup.toxic.kalpha, setup.toxic.kdelta))); setup.vk_proof.vk_beta_2 = G2.affine(G2.mulScalar( G2.g, setup.toxic.kbeta)); - setup.vk_verifier.vk_alfa_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kalfa)); + setup.vk_verifier.vk_alpha_1 = G1.affine(G1.mulScalar( G1.g, setup.toxic.kalpha)); setup.vk_verifier.vk_beta_2 = G2.affine(G2.mulScalar( G2.g, setup.toxic.kbeta)); setup.vk_verifier.vk_gamma_2 = G2.affine(G2.mulScalar( G2.g, setup.toxic.kgamma)); setup.vk_verifier.vk_delta_2 = G2.affine(G2.mulScalar( G2.g, setup.toxic.kdelta)); - setup.vk_verifier.vk_alfabeta_12 = bn128.pairing( setup.vk_verifier.vk_alfa_1 , setup.vk_verifier.vk_beta_2 ); + setup.vk_verifier.vk_alphabeta_12 = bn128.pairing( setup.vk_verifier.vk_alpha_1 , setup.vk_verifier.vk_beta_2 ); for (let s=0; s", vkalfa1_str); + const vkalpha1_str = `${verificationKey.vk_alpha_1[0].toString()},`+ + `${verificationKey.vk_alpha_1[1].toString()}`; + template = template.replace("<%vk_alpha1%>", vkalpha1_str); const vkbeta2_str = `[${verificationKey.vk_beta_2[0][1].toString()},`+ `${verificationKey.vk_beta_2[0][0].toString()}], `+ @@ -112,9 +112,9 @@ function generateVerifier_kimleeoh(verificationKey) { let template = fs.readFileSync(path.join( __dirname, "..", "templates", "verifier_groth16.sol"), "utf-8"); - const vkalfa1_str = `${verificationKey.vk_alfa_1[0].toString()},`+ - `${verificationKey.vk_alfa_1[1].toString()}`; - template = template.replace("<%vk_alfa1%>", vkalfa1_str); + const vkalpha1_str = `${verificationKey.vk_alpha_1[0].toString()},`+ + `${verificationKey.vk_alpha_1[1].toString()}`; + template = template.replace("<%vk_alpha1%>", vkalpha1_str); const vkbeta2_str = `[${verificationKey.vk_beta_2[0][1].toString()},`+ `${verificationKey.vk_beta_2[0][0].toString()}], `+ diff --git a/src/verifier_groth16.js b/src/verifier_groth16.js index 061b546..7b5346e 100644 --- a/src/verifier_groth16.js +++ b/src/verifier_groth16.js @@ -34,7 +34,7 @@ module.exports = function isValid(vk_verifier, proof, publicSignals) { if (! bn128.F12.eq( bn128.pairing( proof.pi_a , proof.pi_b ), bn128.F12.mul( - vk_verifier.vk_alfabeta_12, + vk_verifier.vk_alphabeta_12, bn128.F12.mul( bn128.pairing( cpub , vk_verifier.vk_gamma_2 ), bn128.pairing( proof.pi_c , vk_verifier.vk_delta_2 ) diff --git a/src/verifier_kimleeoh.js b/src/verifier_kimleeoh.js index ec17c54..e643667 100644 --- a/src/verifier_kimleeoh.js +++ b/src/verifier_kimleeoh.js @@ -63,7 +63,7 @@ module.exports = function isValid(vk_verifier, proof, publicSignals) { G2.add(proof.pi_b, G2.mulScalar(vk_verifier.vk_delta_2, h2)) ), bn128.F12.mul( - vk_verifier.vk_alfabeta_12, + vk_verifier.vk_alphabeta_12, bn128.F12.mul( bn128.pairing( cpub , vk_verifier.vk_gamma_2 ), bn128.pairing( proof.pi_c , G2.g ) diff --git a/src/zkey.js b/src/zkey.js new file mode 100644 index 0000000..ba961e1 --- /dev/null +++ b/src/zkey.js @@ -0,0 +1,10 @@ + + +module.exports.new = require("./zkey_new.js"); +module.exports.exportBellman = require("./zkey_export_bellman.js"); +module.exports.importBellman = require("./zkey_import_bellman.js"); +module.exports.verify = require("./zkey_verify.js"); +module.exports.contribute = require("./zkey_contribute.js"); +module.exports.beacon = require("./zkey_beacon.js"); +module.exports.exportJson = require("./zkey_export_json.js"); +module.exports.utils = require("./zkey_utils.js"); diff --git a/src/zkey_beacon.js b/src/zkey_beacon.js new file mode 100644 index 0000000..b778f58 --- /dev/null +++ b/src/zkey_beacon.js @@ -0,0 +1,5 @@ + + +async function beacon(oldZKeyFileName, newZKeyFileName, name, numIterationsExp, beaconHashStr, verbose) { + +} diff --git a/src/zkey_contribute.js b/src/zkey_contribute.js new file mode 100644 index 0000000..fb11d57 --- /dev/null +++ b/src/zkey_contribute.js @@ -0,0 +1,4 @@ + +module.exports = async function phase2contribute(zkeyNameOld, zkeyNameNew, verbose) { + +}; diff --git a/src/zkey_export_bellman.js b/src/zkey_export_bellman.js new file mode 100644 index 0000000..ca40fe6 --- /dev/null +++ b/src/zkey_export_bellman.js @@ -0,0 +1,137 @@ + +const binFileUtils = require("./binfileutils"); +const zkeyUtils = require("./zkey_utils"); +const fastFile = require("fastFile"); +const getCurve = require("./curves").getCurveFromQ; + +module.exports = async function phase2exportMPCParams(zkeyName, mpcparamsName, verbose) { + + const {fd: fdZKey, sections: sectionsZKey} = await binFileUtils.readBinFile(zkeyName, "zkey", 2); + const zkey = await zkeyUtils.readHeader(fdZKey, sectionsZKey, "groth16"); + + const curve = getCurve(zkey.q); + await curve.loadEngine(); + const sG1 = curve.G1.F.n8*2; + const sG2 = curve.G2.F.n8*2; + + const mpcParams = await zkeyUtils.readMPCParams(fdZKey, sectionsZKey); + + const fdMPCParams = await fastFile.createOverride(mpcparamsName); + + ///////////////////// + // Verification Key Section + ///////////////////// + await writeG1(zkey.vk_alpha_1); + await writeG1(zkey.vk_beta_1); + await writeG2(zkey.vk_beta_2); + await writeG2(zkey.vk_gamma_2); + await writeG1(zkey.vk_delta_1); + await writeG2(zkey.vk_delta_2); + + // IC + let buffBasesIC; + buffBasesIC = await binFileUtils.readFullSection(fdZKey, sectionsZKey, 3); + buffBasesIC = await curve.G1.batchLEMtoU(buffBasesIC); + + await writePointArray("G1", buffBasesIC); + + ///////////////////// + // h Section + ///////////////////// + const buffBasesH_Lodd = await binFileUtils.readFullSection(fdZKey, sectionsZKey, 9); + + let buffBasesH_Tau; + buffBasesH_Tau = await curve.G1.fft(buffBasesH_Lodd, "affine", "jacobian", verbose ? console.log : undefined); + buffBasesH_Tau = await curve.G1.batchApplyKey(buffBasesH_Tau, curve.Fr.neg(curve.Fr.e(2)), curve.PFr.w[zkey.power+1], "jacobian", "affine", verbose ? console.log : undefined); + + // Remove last element. (The degree of H will be allways m-2) + buffBasesH_Tau = buffBasesH_Tau.slice(0, buffBasesH_Tau.byteLength - sG1); + buffBasesH_Tau = await curve.G1.batchLEMtoU(buffBasesH_Tau); + await writePointArray("G1", buffBasesH_Tau); + + ///////////////////// + // C section (l section in some notations) + ///////////////////// + let buffBasesC; + buffBasesC = await binFileUtils.readFullSection(fdZKey, sectionsZKey, 8); + buffBasesC = await curve.G1.batchLEMtoU(buffBasesC); + await writePointArray("G1", buffBasesC); + + ///////////////////// + // A Section (C section) + ///////////////////// + let buffBasesA; + buffBasesA = await binFileUtils.readFullSection(fdZKey, sectionsZKey, 5); + buffBasesA = await curve.G1.batchLEMtoU(buffBasesA); + await writePointArray("G1", buffBasesA); + + ///////////////////// + // B1 Section + ///////////////////// + let buffBasesB1; + buffBasesB1 = await binFileUtils.readFullSection(fdZKey, sectionsZKey, 6); + buffBasesB1 = await curve.G1.batchLEMtoU(buffBasesB1); + await writePointArray("G1", buffBasesB1); + + ///////////////////// + // B2 Section + ///////////////////// + let buffBasesB2; + buffBasesB2 = await binFileUtils.readFullSection(fdZKey, sectionsZKey, 7); + buffBasesB2 = await curve.G2.batchLEMtoU(buffBasesB2); + await writePointArray("G2", buffBasesB2); + + await fdMPCParams.write(mpcParams.csHash); + await writeU32(mpcParams.contributions.length); + + for (let i=0; i newMPCParams.contributions.length) { + console.log("The impoerted file does not include new contributions"); + return false; + } + + for (let i=0; i