beacon phase2, verification and challange contribution
This commit is contained in:
parent
0e32995f26
commit
b45eb248e2
78
cli.js
78
cli.js
@ -46,8 +46,9 @@ const Scalar = require("ffjavascript").Scalar;
|
||||
|
||||
const assert = require("assert");
|
||||
|
||||
const groth16Prover = require("./src/groth16_prover");
|
||||
const zkey = require("./src/zkey");
|
||||
const zksnark = require("./src/zksnark");
|
||||
const curves = require("./src/curves");
|
||||
|
||||
const commands = [
|
||||
{
|
||||
@ -123,7 +124,7 @@ const commands = [
|
||||
action: powersOfTawExportChallange
|
||||
},
|
||||
{
|
||||
cmd: "powersoftau challange contribute <challange> [response]",
|
||||
cmd: "powersoftau challange contribute <curve> <challange> [response]",
|
||||
description: "Contribute to a challange",
|
||||
alias: ["ptcc"],
|
||||
options: "-verbose|v -entropy|e",
|
||||
@ -207,6 +208,20 @@ const commands = [
|
||||
options: "-verbose|v -entropy|e -name|n",
|
||||
action: zkeyContribute
|
||||
},
|
||||
{
|
||||
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
|
||||
},
|
||||
{
|
||||
cmd: "zkey challange contribute <curve> <challange> [response]",
|
||||
description: "contributes to a llallange file in bellman format",
|
||||
alias: ["zkcc"],
|
||||
options: "-verbose|v -entropy|e",
|
||||
action: zkeyChallangeContribute
|
||||
},
|
||||
{
|
||||
cmd: "zkey export vkey [circuit.zkey] [verification_key.json]",
|
||||
description: "Exports a verification key",
|
||||
@ -454,7 +469,7 @@ async function zksnarkProve(params, options) {
|
||||
const publicName = params[3] || "public.json";
|
||||
|
||||
|
||||
const {proof, publicSignals} = await groth16Prover(zkeyName, witnessName, options.verbose);
|
||||
const {proof, publicSignals} = await zksnark.groth16.prover(zkeyName, witnessName, options.verbose);
|
||||
|
||||
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");
|
||||
@ -473,10 +488,14 @@ async function zksnarkVerify(params, options) {
|
||||
const pub = unstringifyBigInts(JSON.parse(fs.readFileSync(publicName, "utf8")));
|
||||
const proof = unstringifyBigInts(JSON.parse(fs.readFileSync(proofName, "utf8")));
|
||||
|
||||
/*
|
||||
const protocol = verificationKey.protocol;
|
||||
if (!zkSnark[protocol]) throw new Error("Invalid protocol");
|
||||
|
||||
const isValid = zkSnark[protocol].isValid(verificationKey, proof, pub);
|
||||
*/
|
||||
|
||||
const isValid = await zksnark.groth16.verifier(verificationKey, proof, pub);
|
||||
|
||||
if (isValid) {
|
||||
console.log("OK");
|
||||
@ -512,7 +531,7 @@ async function zkeyExportVKey(params) {
|
||||
vk_gamma_2: zKey.vk_gamma_2,
|
||||
vk_delta_2: zKey.vk_delta_2,
|
||||
|
||||
vk_alphabeta_12: curve.pairing( zKey.vk_alpha_1 , zKey.vk_beta_2 )
|
||||
vk_alphabeta_12: await curve.pairing( zKey.vk_alpha_1 , zKey.vk_beta_2 )
|
||||
};
|
||||
|
||||
await fs.promises.writeFile(verificationKeyName, JSON.stringify(stringifyBigInts(vKey), null, 1), "utf-8");
|
||||
@ -648,20 +667,22 @@ async function powersOfTawExportChallange(params, options) {
|
||||
return await powersOfTaw.exportChallange(ptauName, challangeName, options.verbose);
|
||||
}
|
||||
|
||||
|
||||
// powersoftau challange contribute <curve> <challange> [response]
|
||||
async function powersOfTawChallangeContribute(params, options) {
|
||||
let challangeName;
|
||||
let responseName;
|
||||
|
||||
challangeName = params[0];
|
||||
const curve = curves.getCurveFromName(params[0]);
|
||||
|
||||
if (params.length < 2) {
|
||||
challangeName = params[1];
|
||||
|
||||
if (params.length < 3) {
|
||||
responseName = changeExt(challangeName, "response");
|
||||
} else {
|
||||
responseName = params[1];
|
||||
responseName = params[2];
|
||||
}
|
||||
|
||||
return await powersOfTaw.challangeContribute(bn128, challangeName, responseName, options.entropy, options.verbose);
|
||||
return await powersOfTaw.challangeContribute(curve, challangeName, responseName, options.entropy, options.verbose);
|
||||
}
|
||||
|
||||
|
||||
@ -766,7 +787,7 @@ async function zkeyNew(params, options) {
|
||||
ptauName = params[1];
|
||||
}
|
||||
|
||||
if (params.length < 2) {
|
||||
if (params.length < 3) {
|
||||
zkeyName = "circuit.zkey";
|
||||
} else {
|
||||
zkeyName = params[2];
|
||||
@ -792,7 +813,7 @@ async function zkeyExportBellman(params, options) {
|
||||
mpcparamsName = params[1];
|
||||
}
|
||||
|
||||
return zkey.exportMPCParams(zkeyName, mpcparamsName, options.verbose);
|
||||
return zkey.exportBellman(zkeyName, mpcparamsName, options.verbose);
|
||||
|
||||
}
|
||||
|
||||
@ -857,3 +878,38 @@ async function zkeyContribute(params, options) {
|
||||
|
||||
return zkey.contribute(zkeyOldName, zkeyNewName, options.name, options.entropy, options.verbose);
|
||||
}
|
||||
|
||||
// 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];
|
||||
|
||||
return await zkey.beacon(zkeyOldName, zkeyNewName, options.name ,numIterationsExp, beaconHashStr, options.verbose);
|
||||
}
|
||||
|
||||
|
||||
// zkey challange contribute <curve> <challange> [response]",
|
||||
async function zkeyChallangeContribute(params, options) {
|
||||
let challangeName;
|
||||
let responseName;
|
||||
|
||||
const curve = curves.getCurveFromName(params[0]);
|
||||
|
||||
challangeName = params[1];
|
||||
|
||||
if (params.length < 3) {
|
||||
responseName = changeExt(challangeName, "response");
|
||||
} else {
|
||||
responseName = params[2];
|
||||
}
|
||||
|
||||
return zkey.challangeContribute(curve, challangeName, responseName, options.entropy, options.verbose);
|
||||
}
|
||||
|
||||
|
@ -10,3 +10,20 @@ module.exports.getCurveFromQ = function getCurveFromQ(q) {
|
||||
}
|
||||
return curve;
|
||||
};
|
||||
|
||||
module.exports.getCurveFromName = function getCurveFromName(name) {
|
||||
let curve;
|
||||
const normName = normalizeName(name);
|
||||
if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) {
|
||||
curve = bn128;
|
||||
} else {
|
||||
throw new Error(`Curve not supported: ${name}`);
|
||||
}
|
||||
return curve;
|
||||
|
||||
function normalizeName(n) {
|
||||
return n.toUpperCase().match(/[A-Za-z0-9]+/g).join("");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
44
src/misc.js
44
src/misc.js
@ -109,6 +109,47 @@ async function getRandomRng(entropy) {
|
||||
return rng;
|
||||
}
|
||||
|
||||
function rngFromBeaconParams(beaconHash, numIterationsExp) {
|
||||
let nIterationsInner;
|
||||
let nIterationsOuter;
|
||||
if (numIterationsExp<32) {
|
||||
nIterationsInner = (1 << numIterationsExp) >>> 0;
|
||||
nIterationsOuter = 1;
|
||||
} else {
|
||||
nIterationsInner = 0x100000000;
|
||||
nIterationsOuter = (1 << (numIterationsExp-32)) >>> 0;
|
||||
}
|
||||
|
||||
let curHash = beaconHash;
|
||||
for (let i=0; i<nIterationsOuter; i++) {
|
||||
for (let j=0; j<nIterationsInner; j++) {
|
||||
curHash = crypto.createHash("sha256").update(curHash).digest();
|
||||
}
|
||||
}
|
||||
|
||||
const curHashV = new DataView(curHash.buffer, curHash.byteOffset, curHash.byteLength);
|
||||
const seed = [];
|
||||
for (let i=0; i<8; i++) {
|
||||
seed[i] = curHashV.getUint32(i*4, false);
|
||||
}
|
||||
|
||||
const rng = new ChaCha(seed);
|
||||
|
||||
return rng;
|
||||
}
|
||||
|
||||
function hex2ByteArray(s) {
|
||||
return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function (h) {
|
||||
return parseInt(h, 16);
|
||||
}));
|
||||
}
|
||||
|
||||
function byteArray2hex(byteArray) {
|
||||
return Array.prototype.map.call(byteArray, function(byte) {
|
||||
return ("0" + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join("");
|
||||
}
|
||||
|
||||
module.exports.bitReverse = bitReverse;
|
||||
module.exports.log2 = log2;
|
||||
module.exports.formatHash = formatHash;
|
||||
@ -116,3 +157,6 @@ module.exports.hashIsEqual = hashIsEqual;
|
||||
module.exports.cloneHasher = cloneHasher;
|
||||
module.exports.sameRatio = sameRatio;
|
||||
module.exports.getRandomRng = getRandomRng;
|
||||
module.exports.rngFromBeaconParams = rngFromBeaconParams;
|
||||
module.exports.hex2ByteArray = hex2ByteArray;
|
||||
module.exports.byteArray2hex = byteArray2hex;
|
||||
|
@ -31,14 +31,34 @@ async function applyKeyToSection(fdOld, sections, fdNew, idSection, curve, group
|
||||
|
||||
await binFileUtils.endWriteSection(fdNew);
|
||||
await binFileUtils.endReadSection(fdOld);
|
||||
|
||||
|
||||
}
|
||||
|
||||
async function applyKeyToBinFile(fdOld, fdNew, curve, groupName, nPoints, first, inc, sectionName, verbose) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
module.exports.applyKeyToBinFile = applyKeyToBinFile;
|
||||
|
||||
async function applyKeyToChallangeSection(fdOld, fdNew, responseHasher, curve, groupName, nPoints, first, inc, formatOut, sectionName, verbose) {
|
||||
const G = curve[groupName];
|
||||
const sG = G.F.n8*2;
|
||||
const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks
|
||||
let t = first;
|
||||
for (let i=0 ; i<nPoints ; i+= chunkSize) {
|
||||
if ((verbose)&&i) console.log(`${sectionName}: ` + i);
|
||||
const n= Math.min(nPoints-i, chunkSize );
|
||||
const buffInU = await fdOld.read(n * sG);
|
||||
const buffInLEM = await G.batchUtoLEM(buffInU);
|
||||
const buffOutLEM = await G.batchApplyKey(buffInLEM, t, inc);
|
||||
let buffOut;
|
||||
if (formatOut == "COMPRESSED") {
|
||||
buffOut = await G.batchLEMtoC(buffOutLEM);
|
||||
} else {
|
||||
buffOut = await G.batchLEMtoU(buffOutLEM);
|
||||
}
|
||||
|
||||
if (responseHasher) responseHasher.update(buffOutC);
|
||||
await fdNew.write(buffOut);
|
||||
t = curve.Fr.mul(t, curve.Fr.pow(inc, n));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports.applyKeyToChallangeSection = applyKeyToChallangeSection;
|
||||
module.exports.applyKeyToSection = applyKeyToSection;
|
||||
|
@ -3,14 +3,10 @@ const utils = require("./powersoftau_utils");
|
||||
const misc = require("./misc");
|
||||
const binFileUtils = require("./binfileutils");
|
||||
|
||||
function hex2ByteArray(s) {
|
||||
return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function (h) {
|
||||
return parseInt(h, 16);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
async function beacon(oldPtauFilename, newPTauFilename, name, numIterationsExp, beaconHashStr, verbose) {
|
||||
const beaconHash = hex2ByteArray(beaconHashStr);
|
||||
const beaconHash = misc.hex2ByteArray(beaconHashStr);
|
||||
if ( (beaconHash.byteLength == 0)
|
||||
|| (beaconHash.byteLength*2 !=beaconHashStr.length))
|
||||
{
|
||||
|
@ -19,28 +19,12 @@
|
||||
const fastFile = require("fastfile");
|
||||
const assert = require("assert");
|
||||
const Blake2b = require("blake2b-wasm");
|
||||
const readline = require("readline");
|
||||
const crypto = require("crypto");
|
||||
const ChaCha = require("ffjavascript").ChaCha;
|
||||
const fs = require("fs");
|
||||
const utils = require("./powersoftau_utils");
|
||||
const misc = require("./misc");
|
||||
|
||||
const { applyKeyToChallangeSection } = require("./mpc_applykey");
|
||||
const keyPair = require("./keypair");
|
||||
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
function askEntropy() {
|
||||
return new Promise((resolve) => {
|
||||
rl.question("Enter a random text. (Entropy): ", (input) => resolve(input) );
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async function challangeContribute(curve, challangeFilename, responesFileName, entropy, verbose) {
|
||||
await Blake2b.ready();
|
||||
|
||||
@ -63,10 +47,6 @@ async function challangeContribute(curve, challangeFilename, responesFileName, e
|
||||
|
||||
const fdTo = await fastFile.createOverride(responesFileName);
|
||||
|
||||
while (!entropy) {
|
||||
entropy = await askEntropy();
|
||||
}
|
||||
|
||||
// Calculate the hash
|
||||
console.log("Hashing challange");
|
||||
const challangeHasher = Blake2b(64);
|
||||
@ -84,21 +64,7 @@ async function challangeContribute(curve, challangeFilename, responesFileName, e
|
||||
console.log("Current Challange Hash: ");
|
||||
console.log(misc.formatHash(challangeHash));
|
||||
|
||||
const hasher = Blake2b(64);
|
||||
|
||||
hasher.update(crypto.randomBytes(64));
|
||||
|
||||
const enc = new TextEncoder(); // always utf-8
|
||||
hasher.update(enc.encode(entropy));
|
||||
|
||||
const hash = Buffer.from(hasher.digest());
|
||||
|
||||
const seed = [];
|
||||
for (let i=0;i<8;i++) {
|
||||
seed[i] = hash.readUInt32BE(i*4);
|
||||
}
|
||||
|
||||
const rng = new ChaCha(seed);
|
||||
const rng = await misc.getRandomRng(entropy);
|
||||
|
||||
const key = keyPair.createPTauKey(curve, challangeHash, rng);
|
||||
|
||||
@ -125,12 +91,11 @@ async function challangeContribute(curve, challangeFilename, responesFileName, e
|
||||
await fdTo.write(challangeHash);
|
||||
responseHasher.update(challangeHash);
|
||||
|
||||
|
||||
await contributeSection("G1", (1<<power)*2-1, curve.Fr.one, key.tau.prvKey, "tauG1" );
|
||||
await contributeSection("G2", (1<<power) , curve.Fr.one, key.tau.prvKey, "tauG2" );
|
||||
await contributeSection("G1", (1<<power) , key.alpha.prvKey, key.tau.prvKey, "alphaTauG1" );
|
||||
await contributeSection("G1", (1<<power) , key.beta.prvKey, key.tau.prvKey, "betaTauG1" );
|
||||
await contributeSection("G2", 1 , key.beta.prvKey, key.tau.prvKey, "betaG2" );
|
||||
await applyKeyToChallangeSection(fdFrom, fdTo, responseHasher, curve, "G1", (1<<power)*2-1, curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG1" , verbose );
|
||||
await applyKeyToChallangeSection(fdFrom, fdTo, responseHasher, curve, "G2", (1<<power) , curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG2" , verbose );
|
||||
await applyKeyToChallangeSection(fdFrom, fdTo, responseHasher, curve, "G1", (1<<power) , key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", verbose );
|
||||
await applyKeyToChallangeSection(fdFrom, fdTo, responseHasher, curve, "G1", (1<<power) , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG1" , verbose );
|
||||
await applyKeyToChallangeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1 , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG2" , verbose );
|
||||
|
||||
// Write and hash key
|
||||
const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3);
|
||||
@ -143,26 +108,6 @@ async function challangeContribute(curve, challangeFilename, responesFileName, e
|
||||
|
||||
await fdTo.close();
|
||||
await fdFrom.close();
|
||||
|
||||
async function contributeSection(groupName, nPoints, first, inc, sectionName) {
|
||||
|
||||
const G = curve[groupName];
|
||||
const sG = G.F.n8*2;
|
||||
const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks
|
||||
let t = first;
|
||||
for (let i=0 ; i<nPoints ; i+= chunkSize) {
|
||||
if ((verbose)&&i) console.log(`${sectionName}: ` + i);
|
||||
const n= Math.min(nPoints-i, chunkSize );
|
||||
const buffInU = await fdFrom.read(n * sG);
|
||||
const buffInLEM = await G.batchUtoLEM(buffInU);
|
||||
const buffOutLEM = await G.batchApplyKey(buffInLEM, t, inc);
|
||||
const buffOutC = await G.batchLEMtoC(buffOutLEM);
|
||||
|
||||
responseHasher.update(buffOutC);
|
||||
await fdTo.write(buffOutC);
|
||||
t = curve.Fr.mul(t, curve.Fr.pow(inc, n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = challangeContribute;
|
||||
|
@ -7,24 +7,10 @@
|
||||
|
||||
const Blake2b = require("blake2b-wasm");
|
||||
const utils = require("./powersoftau_utils");
|
||||
const ChaCha = require("ffjavascript").ChaCha;
|
||||
const crypto = require("crypto");
|
||||
const keyPair = require("./keypair");
|
||||
const readline = require("readline");
|
||||
const binFileUtils = require("./binfileutils");
|
||||
const misc = require("./misc");
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
function askEntropy() {
|
||||
return new Promise((resolve) => {
|
||||
rl.question("Enter a random text. (Entropy): ", (input) => resolve(input) );
|
||||
});
|
||||
}
|
||||
|
||||
async function contribute(oldPtauFilename, newPTauFilename, name, entropy, verbose) {
|
||||
await Blake2b.ready();
|
||||
|
||||
@ -51,20 +37,9 @@ async function contribute(oldPtauFilename, newPTauFilename, name, entropy, verbo
|
||||
}
|
||||
|
||||
// Generate a random key
|
||||
while (!entropy) {
|
||||
entropy = await askEntropy();
|
||||
}
|
||||
const hasher = Blake2b(64);
|
||||
hasher.update(crypto.randomBytes(64));
|
||||
const enc = new TextEncoder(); // always utf-8
|
||||
hasher.update(enc.encode(entropy));
|
||||
const hash = Buffer.from(hasher.digest());
|
||||
|
||||
const seed = [];
|
||||
for (let i=0;i<8;i++) {
|
||||
seed[i] = hash.readUInt32BE(i*4);
|
||||
}
|
||||
const rng = new ChaCha(seed);
|
||||
const rng = await misc.getRandomRng(entropy);
|
||||
|
||||
curContribution.key = keyPair.createPTauKey(curve, lastChallangeHash, rng);
|
||||
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
const fastFile = require("fastfile");
|
||||
const assert = require("assert");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const bn128 = require("ffjavascript").bn128;
|
||||
const Blake2b = require("blake2b-wasm");
|
||||
const ChaCha = require("ffjavascript").ChaCha;
|
||||
const keyPair = require("./keypair");
|
||||
const crypto = require("crypto");
|
||||
const misc = require("./misc");
|
||||
|
||||
async function writePTauHeader(fd, curve, power, ceremonyPower) {
|
||||
// Write the header
|
||||
@ -345,30 +343,8 @@ function calculateFirstChallangeHash(curve, power, verbose) {
|
||||
|
||||
|
||||
function keyFromBeacon(curve, challangeHash, beaconHash, numIterationsExp) {
|
||||
let nIterationsInner;
|
||||
let nIterationsOuter;
|
||||
if (numIterationsExp<32) {
|
||||
nIterationsInner = (1 << numIterationsExp) >>> 0;
|
||||
nIterationsOuter = 1;
|
||||
} else {
|
||||
nIterationsInner = 0x100000000;
|
||||
nIterationsOuter = (1 << (numIterationsExp-32)) >>> 0;
|
||||
}
|
||||
|
||||
let curHash = beaconHash;
|
||||
for (let i=0; i<nIterationsOuter; i++) {
|
||||
for (let j=0; j<nIterationsInner; j++) {
|
||||
curHash = crypto.createHash("sha256").update(curHash).digest();
|
||||
}
|
||||
}
|
||||
|
||||
const curHashV = new DataView(curHash.buffer, curHash.byteOffset, curHash.byteLength);
|
||||
const seed = [];
|
||||
for (let i=0; i<8; i++) {
|
||||
seed[i] = curHashV.getUint32(i*4, false);
|
||||
}
|
||||
|
||||
const rng = new ChaCha(seed);
|
||||
const rng = misc.rngFromBeaconParams(beaconHash, numIterationsExp);
|
||||
|
||||
const key = keyPair.createPTauKey(curve, challangeHash, rng);
|
||||
|
||||
|
@ -271,8 +271,9 @@ async function verify(tauFilename, verbose) {
|
||||
function printContribution(curContr, prevContr) {
|
||||
console.log("-----------------------------------------------------");
|
||||
console.log(`Contribution #${curContr.id}: ${curContr.name ||""}`);
|
||||
console.log("\tBased on challange");
|
||||
console.log(misc.formatHash(prevContr.nextChallange));
|
||||
|
||||
console.log("\tNext Challange");
|
||||
console.log(misc.formatHash(curContr.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);
|
||||
@ -285,8 +286,14 @@ async function verify(tauFilename, verbose) {
|
||||
console.log("\tResponse Hash");
|
||||
console.log(misc.formatHash(responseHash));
|
||||
|
||||
console.log("\tNext Challange");
|
||||
console.log(misc.formatHash(curContr.nextChallange));
|
||||
console.log("\tBased on challange");
|
||||
console.log(misc.formatHash(prevContr.nextChallange));
|
||||
|
||||
if (curContr.type == 1) {
|
||||
console.log(`Beacon generator: ${misc.byteArray2Hex(curContr.beaconHash)}`);
|
||||
console.log(`Beacon iterations Exp: ${curContr.numIterationsExp}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function processSectionBetaG2() {
|
||||
|
@ -8,3 +8,4 @@ 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");
|
||||
module.exports.challangeContribute = require("./zkey_challangecontribute.js");
|
||||
|
@ -1,5 +1,110 @@
|
||||
const binFileUtils = require("./binfileutils");
|
||||
const zkeyUtils = require("./zkey_utils");
|
||||
const getCurve = require("./curves").getCurveFromQ;
|
||||
const misc = require("./misc");
|
||||
const Blake2b = require("blake2b-wasm");
|
||||
const utils = require("./zkey_utils");
|
||||
const hashToG2 = require("./keypair").hashToG2;
|
||||
const {applyKeyToSection} = require("./mpc_applykey");
|
||||
|
||||
|
||||
async function beacon(oldZKeyFileName, newZKeyFileName, name, numIterationsExp, beaconHashStr, verbose) {
|
||||
module.exports = async function beacon(zkeyNameOld, zkeyNameNew, name, numIterationsExp, beaconHashStr, verbose) {
|
||||
await Blake2b.ready();
|
||||
|
||||
}
|
||||
const beaconHash = misc.hex2ByteArray(beaconHashStr);
|
||||
if ( (beaconHash.byteLength == 0)
|
||||
|| (beaconHash.byteLength*2 !=beaconHashStr.length))
|
||||
{
|
||||
console.log("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)");
|
||||
return false;
|
||||
}
|
||||
if (beaconHash.length>=256) {
|
||||
console.log("Maximum lenght of beacon hash is 255 bytes");
|
||||
return false;
|
||||
}
|
||||
|
||||
numIterationsExp = parseInt(numIterationsExp);
|
||||
if ((numIterationsExp<10)||(numIterationsExp>63)) {
|
||||
console.log("Invalid numIterationsExp. (Must be between 10 and 63)");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const {fd: fdOld, sections: sections} = await binFileUtils.readBinFile(zkeyNameOld, "zkey", 2);
|
||||
const zkey = await zkeyUtils.readHeader(fdOld, sections, "groth16");
|
||||
|
||||
const curve = getCurve(zkey.q);
|
||||
await curve.loadEngine();
|
||||
|
||||
const mpcParams = await zkeyUtils.readMPCParams(fdOld, curve, sections);
|
||||
|
||||
const fdNew = await binFileUtils.createBinFile(zkeyNameNew, "zkey", 1, 10);
|
||||
|
||||
const rng = await misc.rngFromBeaconParams(beaconHash, numIterationsExp);
|
||||
|
||||
const transcriptHasher = Blake2b(64);
|
||||
transcriptHasher.update(mpcParams.csHash);
|
||||
for (let i=0; i<mpcParams.contributions.length; i++) {
|
||||
utils.hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]);
|
||||
}
|
||||
|
||||
const curContribution = {};
|
||||
curContribution.delta = {};
|
||||
curContribution.delta.prvKey = curve.Fr.fromRng(rng);
|
||||
curContribution.delta.g1_s = curve.G1.affine(curve.G1.fromRng(rng));
|
||||
curContribution.delta.g1_sx = curve.G1.affine(curve.G1.mulScalar(curContribution.delta.g1_s, curContribution.delta.prvKey));
|
||||
utils.hashG1(transcriptHasher, curve, curContribution.delta.g1_s);
|
||||
utils.hashG1(transcriptHasher, curve, curContribution.delta.g1_sx);
|
||||
curContribution.transcript = transcriptHasher.digest();
|
||||
curContribution.delta.g2_sp = hashToG2(curContribution.transcript);
|
||||
curContribution.delta.g2_spx = curve.G2.affine(curve.G2.mulScalar(curContribution.delta.g2_sp, curContribution.delta.prvKey));
|
||||
|
||||
zkey.vk_delta_1 = curve.G1.mulScalar(zkey.vk_delta_1, curContribution.delta.prvKey);
|
||||
zkey.vk_delta_2 = curve.G2.mulScalar(zkey.vk_delta_2, curContribution.delta.prvKey);
|
||||
|
||||
curContribution.deltaAfter = zkey.vk_delta_1;
|
||||
|
||||
curContribution.type = 1;
|
||||
curContribution.numIterationsExp = numIterationsExp;
|
||||
curContribution.beaconHash = beaconHash;
|
||||
|
||||
if (name) curContribution.name = name;
|
||||
|
||||
mpcParams.contributions.push(curContribution);
|
||||
|
||||
await zkeyUtils.writeHeader(fdNew, zkey);
|
||||
|
||||
// IC
|
||||
await binFileUtils.copySection(fdOld, sections, fdNew, 3);
|
||||
|
||||
// Coeffs (Keep original)
|
||||
await binFileUtils.copySection(fdOld, sections, fdNew, 4);
|
||||
|
||||
// A Section
|
||||
await binFileUtils.copySection(fdOld, sections, fdNew, 5);
|
||||
|
||||
// B1 Section
|
||||
await binFileUtils.copySection(fdOld, sections, fdNew, 6);
|
||||
|
||||
// B2 Section
|
||||
await binFileUtils.copySection(fdOld, sections, fdNew, 7);
|
||||
|
||||
const invDelta = curve.Fr.inv(curContribution.delta.prvKey);
|
||||
await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", verbose);
|
||||
await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", verbose);
|
||||
|
||||
await zkeyUtils.writeMPCParams(fdNew, curve, mpcParams);
|
||||
|
||||
await fdOld.close();
|
||||
await fdNew.close();
|
||||
|
||||
const contributionHasher = Blake2b(64);
|
||||
utils.hashPubKey(contributionHasher, curve, curContribution);
|
||||
|
||||
const contribuionHash = contributionHasher.digest();
|
||||
|
||||
console.log("Contribution Hash: ");
|
||||
console.log(misc.formatHash(contribuionHash));
|
||||
|
||||
return true;
|
||||
};
|
||||
|
181
src/zkey_challangecontribute.js
Normal file
181
src/zkey_challangecontribute.js
Normal file
@ -0,0 +1,181 @@
|
||||
// Format of the output
|
||||
// Hash of the last contribution 64 Bytes
|
||||
// 2^N*2-1 TauG1 Points (compressed)
|
||||
// 2^N TauG2 Points (compressed)
|
||||
// 2^N AlphaTauG1 Points (compressed)
|
||||
// 2^N BetaTauG1 Points (compressed)
|
||||
// Public Key
|
||||
// BetaG2 (compressed)
|
||||
// G1*s (compressed)
|
||||
// G1*s*tau (compressed)
|
||||
// G1*t (compressed)
|
||||
// G1*t*alpha (compressed)
|
||||
// G1*u (compressed)
|
||||
// G1*u*beta (compressed)
|
||||
// G2*sp*tau (compressed)
|
||||
// G2*tp*alpha (compressed)
|
||||
// G2*up*beta (compressed)
|
||||
|
||||
const fastFile = require("fastfile");
|
||||
const Blake2b = require("blake2b-wasm");
|
||||
const utils = require("./zkey_utils");
|
||||
const misc = require("./misc");
|
||||
const { applyKeyToChallangeSection } = require("./mpc_applykey");
|
||||
const {hashPubKey} = require("./zkey_utils");
|
||||
const hashToG2 = require("./keypair").hashToG2;
|
||||
|
||||
async function challangeContribute(curve, challangeFilename, responesFileName, entropy, verbose) {
|
||||
await Blake2b.ready();
|
||||
|
||||
const rng = await misc.getRandomRng(entropy);
|
||||
|
||||
const delta = curve.Fr.fromRng(rng);
|
||||
const invDelta = curve.Fr.inv(delta);
|
||||
|
||||
const sG1 = curve.G1.F.n8*2;
|
||||
const sG2 = curve.G2.F.n8*2;
|
||||
|
||||
const fdFrom = await fastFile.readExisting(challangeFilename);
|
||||
const fdTo = await fastFile.createOverride(responesFileName);
|
||||
|
||||
|
||||
await copy(sG1); // alpha1
|
||||
await copy(sG1); // beta1
|
||||
await copy(sG2); // beta2
|
||||
await copy(sG2); // gamma2
|
||||
const oldDelta1 = await readG1();
|
||||
const delta1 = curve.G1.mulScalar(oldDelta1, delta);
|
||||
await writeG1(delta1);
|
||||
const oldDelta2 = await readG2();
|
||||
const delta2 = curve.G2.mulScalar(oldDelta2, delta);
|
||||
await writeG2(delta2);
|
||||
|
||||
// IC
|
||||
const nIC = await fdFrom.readUBE32();
|
||||
await fdTo.writeUBE32(nIC);
|
||||
await copy(nIC*sG1);
|
||||
|
||||
// H
|
||||
const nH = await fdFrom.readUBE32();
|
||||
await fdTo.writeUBE32(nH);
|
||||
await applyKeyToChallangeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", verbose);
|
||||
|
||||
// L
|
||||
const nL = await fdFrom.readUBE32();
|
||||
await fdTo.writeUBE32(nL);
|
||||
await applyKeyToChallangeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", verbose);
|
||||
|
||||
// A
|
||||
const nA = await fdFrom.readUBE32();
|
||||
await fdTo.writeUBE32(nA);
|
||||
await copy(nA*sG1);
|
||||
|
||||
// B1
|
||||
const nB1 = await fdFrom.readUBE32();
|
||||
await fdTo.writeUBE32(nB1);
|
||||
await copy(nB1*sG1);
|
||||
|
||||
// B2
|
||||
const nB2 = await fdFrom.readUBE32();
|
||||
await fdTo.writeUBE32(nB2);
|
||||
await copy(nB2*sG2);
|
||||
|
||||
|
||||
//////////
|
||||
/// Read contributions
|
||||
//////////
|
||||
const transcriptHasher = Blake2b(64);
|
||||
|
||||
const mpcParams = {};
|
||||
// csHash
|
||||
mpcParams.csHash = await fdFrom.read(64);
|
||||
transcriptHasher.update(mpcParams.csHash);
|
||||
|
||||
const nConttributions = await fdFrom.readUBE32();
|
||||
mpcParams.contributions = [];
|
||||
for (let i=0; i<nConttributions; i++) {
|
||||
const c = { delta:{} };
|
||||
c.deltaAfter = await readG1();
|
||||
c.delta.g1_s = await readG1();
|
||||
c.delta.g1_sx = await readG1();
|
||||
c.delta.g2_spx = await readG2();
|
||||
c.transcript = await fdFrom.read(64);
|
||||
mpcParams.contributions.push(c);
|
||||
hashPubKey(transcriptHasher, curve, c);
|
||||
}
|
||||
|
||||
const curContribution = {};
|
||||
curContribution.delta = {};
|
||||
curContribution.delta.prvKey = delta;
|
||||
curContribution.delta.g1_s = curve.G1.affine(curve.G1.fromRng(rng));
|
||||
curContribution.delta.g1_sx = curve.G1.affine(curve.G1.mulScalar(curContribution.delta.g1_s, delta));
|
||||
utils.hashG1(transcriptHasher, curve, curContribution.delta.g1_s);
|
||||
utils.hashG1(transcriptHasher, curve, curContribution.delta.g1_sx);
|
||||
curContribution.transcript = transcriptHasher.digest();
|
||||
curContribution.delta.g2_sp = hashToG2(curContribution.transcript);
|
||||
curContribution.delta.g2_spx = curve.G2.affine(curve.G2.mulScalar(curContribution.delta.g2_sp, delta));
|
||||
curContribution.deltaAfter = delta1;
|
||||
curContribution.type = 0;
|
||||
mpcParams.contributions.push(curContribution);
|
||||
|
||||
|
||||
//////////
|
||||
/// Write COntribution
|
||||
//////////
|
||||
|
||||
await fdTo.write(mpcParams.csHash);
|
||||
await fdTo.writeUBE32(mpcParams.contributions.length);
|
||||
|
||||
for (let i=0; i<mpcParams.contributions.length; i++) {
|
||||
const c = mpcParams.contributions[i];
|
||||
await writeG1(c.deltaAfter);
|
||||
await writeG1(c.delta.g1_s);
|
||||
await writeG1(c.delta.g1_sx);
|
||||
await writeG2(c.delta.g2_spx);
|
||||
await fdTo.write(c.transcript);
|
||||
}
|
||||
|
||||
const contributionHasher = Blake2b(64);
|
||||
hashPubKey(contributionHasher, curve, curContribution);
|
||||
|
||||
console.log("Contribution Hash: ");
|
||||
console.log(misc.formatHash(contributionHasher.digest()));
|
||||
|
||||
await fdTo.close();
|
||||
await fdFrom.close();
|
||||
|
||||
async function copy(nBytes) {
|
||||
const CHUNK_SIZE = fdFrom.pageSize*2;
|
||||
for (let i=0; i<nBytes; i+= CHUNK_SIZE) {
|
||||
const n = Math.min(nBytes -i, CHUNK_SIZE);
|
||||
const buff = await fdFrom.read(n);
|
||||
await fdTo.write(buff);
|
||||
}
|
||||
}
|
||||
|
||||
async function readG1() {
|
||||
const buff = await fdFrom.read(curve.G1.F.n8*2);
|
||||
return curve.G1.fromRprUncompressed(buff, 0);
|
||||
}
|
||||
|
||||
async function readG2() {
|
||||
const buff = await fdFrom.read(curve.G2.F.n8*2);
|
||||
return curve.G2.fromRprUncompressed(buff, 0);
|
||||
}
|
||||
|
||||
async function writeG1(P) {
|
||||
const buff = new Uint8Array(sG1);
|
||||
curve.G1.toRprUncompressed(buff, 0, P);
|
||||
await fdTo.write(buff);
|
||||
}
|
||||
|
||||
async function writeG2(P) {
|
||||
const buff = new Uint8Array(sG2);
|
||||
curve.G2.toRprUncompressed(buff, 0, P);
|
||||
await fdTo.write(buff);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = challangeContribute;
|
@ -21,7 +21,6 @@ module.exports = async function phase2contribute(zkeyNameOld, zkeyNameNew, name
|
||||
|
||||
const fdNew = await binFileUtils.createBinFile(zkeyNameNew, "zkey", 1, 10);
|
||||
|
||||
const curContribution = {};
|
||||
|
||||
const rng = await misc.getRandomRng(entropy);
|
||||
|
||||
@ -30,6 +29,7 @@ module.exports = async function phase2contribute(zkeyNameOld, zkeyNameNew, name
|
||||
utils.hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]);
|
||||
}
|
||||
|
||||
const curContribution = {};
|
||||
curContribution.delta = {};
|
||||
curContribution.delta.prvKey = curve.Fr.fromRng(rng);
|
||||
curContribution.delta.g1_s = curve.G1.affine(curve.G1.fromRng(rng));
|
||||
@ -44,11 +44,12 @@ module.exports = async function phase2contribute(zkeyNameOld, zkeyNameNew, name
|
||||
zkey.vk_delta_2 = curve.G2.mulScalar(zkey.vk_delta_2, curContribution.delta.prvKey);
|
||||
|
||||
curContribution.deltaAfter = zkey.vk_delta_1;
|
||||
mpcParams.contributions.push(curContribution);
|
||||
|
||||
curContribution.type = 0;
|
||||
if (name) curContribution.name = name;
|
||||
|
||||
mpcParams.contributions.push(curContribution);
|
||||
|
||||
await zkeyUtils.writeHeader(fdNew, zkey);
|
||||
|
||||
// IC
|
||||
|
@ -14,7 +14,7 @@ module.exports = async function phase2exportMPCParams(zkeyName, mpcparamsName,
|
||||
const sG1 = curve.G1.F.n8*2;
|
||||
const sG2 = curve.G2.F.n8*2;
|
||||
|
||||
const mpcParams = await zkeyUtils.readMPCParams(fdZKey, sectionsZKey);
|
||||
const mpcParams = await zkeyUtils.readMPCParams(fdZKey, curve, sectionsZKey);
|
||||
|
||||
const fdMPCParams = await fastFile.createOverride(mpcparamsName);
|
||||
|
||||
@ -50,7 +50,7 @@ module.exports = async function phase2exportMPCParams(zkeyName, mpcparamsName,
|
||||
await writePointArray("G1", buffBasesH_Tau);
|
||||
|
||||
/////////////////////
|
||||
// C section (l section in some notations)
|
||||
// L section
|
||||
/////////////////////
|
||||
let buffBasesC;
|
||||
buffBasesC = await binFileUtils.readFullSection(fdZKey, sectionsZKey, 8);
|
||||
@ -89,7 +89,7 @@ module.exports = async function phase2exportMPCParams(zkeyName, mpcparamsName,
|
||||
await writeG1(c.deltaAfter);
|
||||
await writeG1(c.delta.g1_s);
|
||||
await writeG1(c.delta.g1_sx);
|
||||
await writeG1(c.delta.g2_spx);
|
||||
await writeG2(c.delta.g2_spx);
|
||||
await fdMPCParams.write(c.transcript);
|
||||
}
|
||||
|
||||
@ -98,13 +98,13 @@ module.exports = async function phase2exportMPCParams(zkeyName, mpcparamsName,
|
||||
|
||||
async function writeG1(P) {
|
||||
const buff = new Uint8Array(sG1);
|
||||
curve.G1.toRprBE(buff, 0, P);
|
||||
curve.G1.toRprUncompressed(buff, 0, P);
|
||||
await fdMPCParams.write(buff);
|
||||
}
|
||||
|
||||
async function writeG2(P) {
|
||||
const buff = new Uint8Array(sG2);
|
||||
curve.G2.toRprBE(buff, 0, P);
|
||||
curve.G2.toRprUncompressed(buff, 0, P);
|
||||
await fdMPCParams.write(buff);
|
||||
}
|
||||
|
||||
|
@ -167,6 +167,7 @@ module.exports = async function phase2importMPCParams(zkeyNameOld, mpcparamsNam
|
||||
return curve.G2.fromRprUncompressed(buff, 0);
|
||||
}
|
||||
|
||||
|
||||
function contributionIsEqual(c1, c2) {
|
||||
if (!curve.G1.eq(c1.deltaAfter , c2.deltaAfter)) return false;
|
||||
if (!curve.G1.eq(c1.delta.g1_s , c2.delta.g1_s)) return false;
|
||||
|
@ -27,7 +27,6 @@ module.exports = async function phase2verify(r1csFileName, pTauFileName, zkeyFi
|
||||
|
||||
const mpcParams = await zkeyUtils.readMPCParams(fd, curve, sections);
|
||||
|
||||
const responses = [];
|
||||
const accumulatedHasher = Blake2b(64);
|
||||
accumulatedHasher.update(mpcParams.csHash);
|
||||
let curDelta = curve.G1.g;
|
||||
@ -57,11 +56,27 @@ module.exports = async function phase2verify(r1csFileName, pTauFileName, zkeyFi
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c.type == 1) {
|
||||
const rng = misc.rngFromBeaconParams(c.beaconHash, c.numIterationsExp);
|
||||
const expected_prvKey = curve.Fr.fromRng(rng);
|
||||
const expected_g1_s = curve.G1.affine(curve.G1.fromRng(rng));
|
||||
const expected_g1_sx = curve.G1.affine(curve.G1.mulScalar(expected_g1_s, expected_prvKey));
|
||||
if (curve.G1.eq(expected_g1_s, c.delta.g1_s) !== true) {
|
||||
console.log(`INVALID(${i}): Key of the beacon does not match. g1_s `);
|
||||
return false;
|
||||
}
|
||||
if (curve.G1.eq(expected_g1_sx, c.delta.g1_sx) !== true) {
|
||||
console.log(`INVALID(${i}): Key of the beacon does not match. g1_sx `);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hashPubKey(accumulatedHasher, curve, c);
|
||||
|
||||
const contributionHasher = Blake2b(64);
|
||||
hashPubKey(contributionHasher, curve, c);
|
||||
responses.push(contributionHasher.digest());
|
||||
|
||||
c.contributionHash = contributionHasher.digest();
|
||||
|
||||
curDelta = c.deltaAfter;
|
||||
}
|
||||
@ -179,6 +194,18 @@ module.exports = async function phase2verify(r1csFileName, pTauFileName, zkeyFi
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i=mpcParams.contributions.length-1; i>=0; i--) {
|
||||
const c = mpcParams.contributions[i];
|
||||
console.log("-------------------------");
|
||||
console.log(`contribution #${i+1}${c.name ? c.name : ""}:`);
|
||||
console.log(misc.formatHash(c.contributionHash));
|
||||
if (c.type == 1) {
|
||||
console.log(`Beacon generator: ${misc.byteArray2hex(c.beaconHash)}`);
|
||||
console.log(`Beacon iterations Exp: ${c.numIterationsExp}`);
|
||||
}
|
||||
}
|
||||
console.log("-------------------------");
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
|
8
src/zksnark.js
Normal file
8
src/zksnark.js
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
module.exports = {
|
||||
groth16: {
|
||||
prover: module.require("./zksnark_groth16_prover"),
|
||||
verifier: module.require("./zksnark_groth16_verifier")
|
||||
}
|
||||
};
|
@ -95,6 +95,9 @@ async function groth16Prover(zkeyFileName, witnessFileName, verbose) {
|
||||
|
||||
proof.protocol = "groth";
|
||||
|
||||
await fdZKey.close();
|
||||
await fdWtns.close();
|
||||
|
||||
return {proof, publicSignals};
|
||||
}
|
||||
|
48
src/zksnark_groth16_verifier.js
Normal file
48
src/zksnark_groth16_verifier.js
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright 2018 0kims association.
|
||||
|
||||
This file is part of snarkjs.
|
||||
|
||||
snarkjs 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.
|
||||
|
||||
snarkjs 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
|
||||
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Implementation of this paper: https://eprint.iacr.org/2016/260.pdf */
|
||||
|
||||
|
||||
const bn128 = require("ffjavascript").bn128;
|
||||
|
||||
const G1 = bn128.G1;
|
||||
|
||||
module.exports = async function isValid(vk_verifier, proof, publicSignals) {
|
||||
/*
|
||||
let cpub = vk_verifier.IC[0];
|
||||
for (let s= 0; s< vk_verifier.nPublic; s++) {
|
||||
cpub = G1.add( cpub, G1.mulScalar( vk_verifier.IC[s+1], publicSignals[s]));
|
||||
}
|
||||
*/
|
||||
|
||||
let cpub = await G1.multiExp(vk_verifier.IC.slice(1), publicSignals);
|
||||
cpub = G1.add(cpub, vk_verifier.IC[0]);
|
||||
|
||||
const res = await bn128.pairingEq(
|
||||
bn128.G1.neg(proof.pi_a) , proof.pi_b,
|
||||
cpub , vk_verifier.vk_gamma_2,
|
||||
proof.pi_c , vk_verifier.vk_delta_2,
|
||||
|
||||
vk_verifier.vk_alpha_1, vk_verifier.vk_beta_2
|
||||
);
|
||||
|
||||
if (! res) return false;
|
||||
return true;
|
||||
};
|
Loading…
Reference in New Issue
Block a user