snarkjs/src/prover_groth.js

142 lines
4.2 KiB
JavaScript
Raw Permalink Normal View History

2018-09-05 04:56:49 +02:00
/*
2018-09-10 11:53:09 +02:00
Copyright 2018 0kims association.
2018-09-05 04:56:49 +02:00
2018-10-21 19:41:44 +02:00
This file is part of snarkjs.
2018-09-05 04:56:49 +02:00
2018-10-21 19:41:44 +02:00
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)
2018-09-10 11:53:09 +02:00
any later version.
2018-09-05 04:56:49 +02:00
2018-10-21 19:41:44 +02:00
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
2018-09-10 11:53:09 +02:00
more details.
2018-09-05 04:56:49 +02:00
You should have received a copy of the GNU General Public License along with
2018-10-21 19:41:44 +02:00
snarkjs. If not, see <https://www.gnu.org/licenses/>.
2018-09-05 04:56:49 +02:00
*/
2018-11-10 14:43:37 +01:00
/* Implementation of this paper: https://eprint.iacr.org/2016/260.pdf */
2018-09-09 14:07:28 +02:00
const BN128 = require("./bn128.js");
2018-08-09 15:31:16 +02:00
const PolField = require("./polfield.js");
2018-08-25 00:16:12 +02:00
const ZqField = require("./zqfield.js");
2018-08-09 15:31:16 +02:00
2018-08-25 00:16:12 +02:00
const bn128 = new BN128();
const PolF = new PolField(new ZqField(bn128.r));
const G1 = bn128.G1;
const G2 = bn128.G2;
2018-08-09 08:16:34 +02:00
module.exports = function genProof(vk_proof, witness) {
2018-08-09 15:31:16 +02:00
const proof = {};
2018-11-10 14:43:37 +01:00
const r = PolF.F.random();
const s = PolF.F.random();
2018-09-24 12:32:33 +02:00
2019-06-16 00:12:50 +02:00
/* Uncomment to generate a deterministic proof to debug
const r = PolF.F.zero;
const s = PolF.F.zero;
*/
2018-08-25 00:16:12 +02:00
proof.pi_a = G1.zero;
proof.pi_b = G2.zero;
proof.pi_c = G1.zero;
2018-11-10 14:43:37 +01:00
let pib1 = G1.zero;
2018-08-09 15:31:16 +02:00
2018-08-09 18:59:39 +02:00
// Skip public entries and the "1" signal that are forced by the verifier
2018-08-09 15:31:16 +02:00
2018-11-10 14:43:37 +01:00
for (let s= 0; s< vk_proof.nVars; s++) {
// pi_a = pi_a + A[s] * witness[s];
proof.pi_a = G1.add( proof.pi_a, G1.mulScalar( vk_proof.A[s], witness[s]));
2018-08-09 15:31:16 +02:00
2018-11-10 14:43:37 +01:00
// pi_b = pi_b + B[s] * witness[s];
proof.pi_b = G2.add( proof.pi_b, G2.mulScalar( vk_proof.B2[s], witness[s]));
2018-08-09 15:31:16 +02:00
2018-11-10 14:43:37 +01:00
pib1 = G1.add( pib1, G1.mulScalar( vk_proof.B1[s], witness[s]));
}
2018-08-09 15:31:16 +02:00
2018-11-10 14:43:37 +01:00
for (let s= vk_proof.nPublic+1; s< vk_proof.nVars; s++) {
2018-08-09 15:31:16 +02:00
// pi_a = pi_a + A[s] * witness[s];
2018-08-25 00:16:12 +02:00
proof.pi_c = G1.add( proof.pi_c, G1.mulScalar( vk_proof.C[s], witness[s]));
2018-08-09 15:31:16 +02:00
}
2018-11-10 14:43:37 +01:00
proof.pi_a = G1.add( proof.pi_a, vk_proof.vk_alfa_1 );
proof.pi_a = G1.add( proof.pi_a, G1.mulScalar( vk_proof.vk_delta_1, r ));
2018-09-24 12:32:33 +02:00
2018-11-10 14:43:37 +01:00
proof.pi_b = G2.add( proof.pi_b, vk_proof.vk_beta_2 );
proof.pi_b = G2.add( proof.pi_b, G2.mulScalar( vk_proof.vk_delta_2, s ));
2018-09-24 12:32:33 +02:00
2018-11-10 14:43:37 +01:00
pib1 = G1.add( pib1, vk_proof.vk_beta_1 );
pib1 = G1.add( pib1, G1.mulScalar( vk_proof.vk_delta_1, s ));
2018-09-24 12:32:33 +02:00
2019-04-09 14:55:59 +02:00
const h = calculateH(vk_proof, witness);
2018-08-09 15:31:16 +02:00
2019-06-16 00:12:50 +02:00
// proof.pi_c = G1.affine(proof.pi_c);
// console.log("pi_onlyc", proof.pi_c);
2018-11-10 14:43:37 +01:00
for (let i = 0; i < h.length; i++) {
2019-06-16 00:12:50 +02:00
// console.log(i + "->" + h[i].toString());
2018-11-10 14:43:37 +01:00
proof.pi_c = G1.add( proof.pi_c, G1.mulScalar( vk_proof.hExps[i], h[i]));
2018-08-09 15:31:16 +02:00
}
2019-06-16 00:12:50 +02:00
// proof.pi_c = G1.affine(proof.pi_c);
// console.log("pi_candh", proof.pi_c);
2018-11-10 14:43:37 +01:00
proof.pi_c = G1.add( proof.pi_c, G1.mulScalar( proof.pi_a, s ));
proof.pi_c = G1.add( proof.pi_c, G1.mulScalar( pib1, r ));
proof.pi_c = G1.add( proof.pi_c, G1.mulScalar( vk_proof.vk_delta_1, PolF.F.affine(PolF.F.neg(PolF.F.mul(r,s) ))));
2018-08-09 15:31:16 +02:00
2018-11-10 14:43:37 +01:00
const publicSignals = witness.slice(1, vk_proof.nPublic+1);
2018-08-09 15:31:16 +02:00
2018-08-25 00:16:12 +02:00
proof.pi_a = G1.affine(proof.pi_a);
proof.pi_b = G2.affine(proof.pi_b);
proof.pi_c = G1.affine(proof.pi_c);
2018-11-10 14:43:37 +01:00
proof.protocol = "groth";
2018-08-25 00:16:12 +02:00
return {proof, publicSignals};
2019-04-09 14:55:59 +02:00
2018-08-09 15:31:16 +02:00
};
2019-04-09 14:55:59 +02:00
function calculateH(vk_proof, witness) {
const F = PolF.F;
const m = vk_proof.domainSize;
const polA_T = new Array(m).fill(PolF.F.zero);
const polB_T = new Array(m).fill(PolF.F.zero);
const polC_T = new Array(m).fill(PolF.F.zero);
for (let s=0; s<vk_proof.nVars; s++) {
for (let c in vk_proof.polsA[s]) {
polA_T[c] = F.add(polA_T[c], F.mul(witness[s], vk_proof.polsA[s][c]));
}
for (let c in vk_proof.polsB[s]) {
polB_T[c] = F.add(polB_T[c], F.mul(witness[s], vk_proof.polsB[s][c]));
}
for (let c in vk_proof.polsC[s]) {
polC_T[c] = F.add(polC_T[c], F.mul(witness[s], vk_proof.polsC[s][c]));
}
}
const polA_S = PolF.ifft(polA_T);
const polB_S = PolF.ifft(polB_T);
const polAB_S = PolF.mul(polA_S, polB_S);
const polC_S = PolF.ifft(polC_T);
const polABC_S = PolF.sub(polAB_S, polC_S);
2019-04-09 14:55:59 +02:00
const H_S = polABC_S.slice(m);
2018-09-24 12:32:33 +02:00
return H_S;
}