Important optimization for the trusted setup
This commit is contained in:
parent
3343981187
commit
16ff407765
189
src/polfield.js
189
src/polfield.js
@ -3,28 +3,29 @@
|
|||||||
|
|
||||||
This file is part of zksnark JavaScript library.
|
This file is part of zksnark JavaScript library.
|
||||||
|
|
||||||
zksnark JavaScript library is a free software: you can redistribute it and/or
|
zksnark JavaScript library 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
|
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)
|
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
zksnark JavaScript library is distributed in the hope that it will be useful,
|
zksnark JavaScript library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
more details.
|
more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This library does operations on polynomials with coefficients in a field F.
|
This library does operations on polynomials with coefficients in a field F.
|
||||||
|
|
||||||
A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented
|
A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented
|
||||||
by the array [ p0, p1, p2, ... , pn ].
|
by the array [ p0, p1, p2, ... , pn ].
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const bigInt = require("./bigint.js");
|
const bigInt = require("./bigint.js");
|
||||||
|
const assert = require("assert");
|
||||||
|
|
||||||
class PolField {
|
class PolField {
|
||||||
constructor (F) {
|
constructor (F) {
|
||||||
@ -52,6 +53,35 @@ class PolField {
|
|||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.roots = [];
|
||||||
|
/* for (let i=0; i<16; i++) {
|
||||||
|
let r = this.F.one;
|
||||||
|
n = 1 << i;
|
||||||
|
const rootsi = new Array(n);
|
||||||
|
for (let j=0; j<n; j++) {
|
||||||
|
rootsi[j] = r;
|
||||||
|
r = this.F.mul(r, this.w[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.roots.push(rootsi);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
this._setRoots(15);
|
||||||
|
}
|
||||||
|
|
||||||
|
_setRoots(n) {
|
||||||
|
for (let i=n; (i>=0) && (!this.roots[i]); i--) {
|
||||||
|
let r = this.F.one;
|
||||||
|
const nroots = 1 << i;
|
||||||
|
const rootsi = new Array(nroots);
|
||||||
|
for (let j=0; j<nroots; j++) {
|
||||||
|
rootsi[j] = r;
|
||||||
|
r = this.F.mul(r, this.w[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.roots[i] = rootsi;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add(a, b) {
|
add(a, b) {
|
||||||
@ -117,12 +147,14 @@ class PolField {
|
|||||||
mulFFT(a,b) {
|
mulFFT(a,b) {
|
||||||
const longestN = Math.max(a.length, b.length);
|
const longestN = Math.max(a.length, b.length);
|
||||||
const bitsResult = log2(longestN-1)+2;
|
const bitsResult = log2(longestN-1)+2;
|
||||||
|
this._setRoots(bitsResult);
|
||||||
|
|
||||||
const m = 1 << bitsResult;
|
const m = 1 << bitsResult;
|
||||||
const ea = this.extend(a,m);
|
const ea = this.extend(a,m);
|
||||||
const eb = this.extend(b,m);
|
const eb = this.extend(b,m);
|
||||||
|
|
||||||
const ta = this._fft(ea, bitsResult, 0, 1, false);
|
const ta = __fft(this, ea, bitsResult, 0, 1, false);
|
||||||
const tb = this._fft(eb, bitsResult, 0, 1, false);
|
const tb = __fft(this, eb, bitsResult, 0, 1, false);
|
||||||
|
|
||||||
const tres = new Array(m);
|
const tres = new Array(m);
|
||||||
|
|
||||||
@ -130,7 +162,7 @@ class PolField {
|
|||||||
tres[i] = this.F.mul(ta[i], tb[i]);
|
tres[i] = this.F.mul(ta[i], tb[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = this._fft(tres, bitsResult, 0, 1, true);
|
const res = __fft(this, tres, bitsResult, 0, 1, true);
|
||||||
|
|
||||||
const twoinvm = this.F.inverse( this.F.mulScalar(this.F.one, m) );
|
const twoinvm = this.F.inverse( this.F.mulScalar(this.F.one, m) );
|
||||||
const resn = new Array(m);
|
const resn = new Array(m);
|
||||||
@ -159,7 +191,7 @@ class PolField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eval(p, x) {
|
eval2(p, x) {
|
||||||
let v = this.F.zero;
|
let v = this.F.zero;
|
||||||
let ix = this.F.one;
|
let ix = this.F.one;
|
||||||
for (let i=0; i<p.length; i++) {
|
for (let i=0; i<p.length; i++) {
|
||||||
@ -169,6 +201,26 @@ class PolField {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eval(p,x) {
|
||||||
|
const F = this.F;
|
||||||
|
if (p.length == 0) return F.zero;
|
||||||
|
const m = this._next2Power(p.length);
|
||||||
|
const ep = this.extend(p, m);
|
||||||
|
|
||||||
|
return _eval(ep, x, 0, 1, m);
|
||||||
|
|
||||||
|
function _eval(p, x, offset, step, n) {
|
||||||
|
if (n==1) return p[offset];
|
||||||
|
const newX = F.square(x);
|
||||||
|
const res= F.add(
|
||||||
|
_eval(p, newX, offset, step << 1, n >> 1),
|
||||||
|
F.mul(
|
||||||
|
x,
|
||||||
|
_eval(p, newX, offset+step , step << 1, n >> 1)));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lagrange(points) {
|
lagrange(points) {
|
||||||
let roots = [this.F.one];
|
let roots = [this.F.one];
|
||||||
for (let i=0; i<points.length; i++) {
|
for (let i=0; i<points.length; i++) {
|
||||||
@ -188,6 +240,38 @@ class PolField {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fft(p) {
|
||||||
|
if (p.length <= 1) return p;
|
||||||
|
const bits = log2(p.length-1)+1;
|
||||||
|
this._setRoots(bits);
|
||||||
|
|
||||||
|
const m = 1 << bits;
|
||||||
|
const ep = this.extend(p, m);
|
||||||
|
const res = __fft(this, ep, bits, 0, 1);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifft(p) {
|
||||||
|
|
||||||
|
if (p.length <= 1) return p;
|
||||||
|
const bits = log2(p.length-1)+1;
|
||||||
|
this._setRoots(bits);
|
||||||
|
const m = 1 << bits;
|
||||||
|
const ep = this.extend(p, m);
|
||||||
|
const res = __fft(this, ep, bits, 0, 1);
|
||||||
|
|
||||||
|
const twoinvm = this.F.inverse( this.F.mulScalar(this.F.one, m) );
|
||||||
|
const resn = new Array(m);
|
||||||
|
for (let i=0; i<m; i++) {
|
||||||
|
resn[i] = this.F.mul(res[(m-i)%m], twoinvm);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resn;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_fft(pall, bits, offset, step) {
|
_fft(pall, bits, offset, step) {
|
||||||
|
|
||||||
const n = 1 << bits;
|
const n = 1 << bits;
|
||||||
@ -354,6 +438,62 @@ class PolField {
|
|||||||
|
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns the ith nth-root of one
|
||||||
|
oneRoot(n, i) {
|
||||||
|
let nbits = log2(n-1)+1;
|
||||||
|
let res = this.F.one;
|
||||||
|
let r = i;
|
||||||
|
|
||||||
|
assert(i<n);
|
||||||
|
assert(1<<nbits === n);
|
||||||
|
|
||||||
|
while (r>0) {
|
||||||
|
if (r & 1 == 1) {
|
||||||
|
res = this.F.mul(res, this.w[nbits]);
|
||||||
|
}
|
||||||
|
r = r >> 1;
|
||||||
|
nbits --;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeVanishingPolinomial(bits, t) {
|
||||||
|
const m = 1 << bits;
|
||||||
|
return this.F.sub(this.F.exp(t, bigInt(m)), this.F.one);
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluateLagrangePolynomials(bits, t) {
|
||||||
|
const m= 1 << bits;
|
||||||
|
const tm = this.F.exp(t, bigInt(m));
|
||||||
|
const u= new Array(m).fill(this.F.zero);
|
||||||
|
this._setRoots(bits);
|
||||||
|
const omega = this.w[bits];
|
||||||
|
|
||||||
|
if (this.F.equals(tm, this.F.one)) {
|
||||||
|
for (let i = 0; i < m; i++) {
|
||||||
|
if (this.F.equals(this.roots[bits][0],t)) { // i.e., t equals omega^i
|
||||||
|
u[i] = this.F.one;
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const z = this.F.sub(tm, this.F.one);
|
||||||
|
// let l = this.F.mul(z, this.F.exp(this.F.twoinv, m));
|
||||||
|
let l = this.F.mul(z, this.F.inverse(bigInt(m)));
|
||||||
|
for (let i = 0; i < m; i++) {
|
||||||
|
u[i] = this.F.mul(l, this.F.inverse(this.F.sub(t,this.roots[bits][i])));
|
||||||
|
l = this.F.mul(l, omega);
|
||||||
|
}
|
||||||
|
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
log2(V) {
|
||||||
|
return log2(V);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function log2( V )
|
function log2( V )
|
||||||
@ -361,4 +501,31 @@ function log2( V )
|
|||||||
return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
|
return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function __fft(PF, pall, bits, offset, step) {
|
||||||
|
|
||||||
|
const n = 1 << bits;
|
||||||
|
if (n==1) {
|
||||||
|
return [ pall[offset] ];
|
||||||
|
} else if (n==2) {
|
||||||
|
return [
|
||||||
|
PF.F.add(pall[offset], pall[offset + step]),
|
||||||
|
PF.F.sub(pall[offset], pall[offset + step])];
|
||||||
|
}
|
||||||
|
|
||||||
|
const ndiv2 = n >> 1;
|
||||||
|
const p1 = __fft(PF, pall, bits-1, offset, step*2);
|
||||||
|
const p2 = __fft(PF, pall, bits-1, offset+step, step*2);
|
||||||
|
|
||||||
|
const out = new Array(n);
|
||||||
|
|
||||||
|
for (let i=0; i<ndiv2; i++) {
|
||||||
|
out[i] = PF.F.add(p1[i], PF.F.mul(PF.roots[bits][i], p2[i]));
|
||||||
|
out[i+ndiv2] = PF.F.sub(p1[i], PF.F.mul(PF.roots[bits][i], p2[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = PolField;
|
module.exports = PolField;
|
||||||
|
@ -3,17 +3,17 @@
|
|||||||
|
|
||||||
This file is part of zksnark JavaScript library.
|
This file is part of zksnark JavaScript library.
|
||||||
|
|
||||||
zksnark JavaScript library is a free software: you can redistribute it and/or
|
zksnark JavaScript library 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
|
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)
|
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
zksnark JavaScript library is distributed in the hope that it will be useful,
|
zksnark JavaScript library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
more details.
|
more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -67,6 +67,7 @@ module.exports = function genProof(vk_proof, witness) {
|
|||||||
proof.pi_kp = G1.add( proof.pi_kp, G1.mulScalar( vk_proof.Kp[s], witness[s]));
|
proof.pi_kp = G1.add( proof.pi_kp, G1.mulScalar( vk_proof.Kp[s], witness[s]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
let polA = [];
|
let polA = [];
|
||||||
let polB = [];
|
let polB = [];
|
||||||
let polC = [];
|
let polC = [];
|
||||||
@ -91,11 +92,15 @@ module.exports = function genProof(vk_proof, witness) {
|
|||||||
[witness[s]] ));
|
[witness[s]] ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let polFull = PolF.sub(PolF.mul( polA, polB), polC);
|
let polFull = PolF.sub(PolF.mul( polA, polB), polC);
|
||||||
|
|
||||||
const h = PolF.div(polFull, vk_proof.polZ );
|
const h = PolF.div(polFull, vk_proof.polZ );
|
||||||
|
*/
|
||||||
|
|
||||||
// console.log(h.length + "/" + vk_proof.hExps.length);
|
const h = calculateH(vk_proof, witness);
|
||||||
|
|
||||||
|
console.log(h.length + "/" + vk_proof.hExps.length);
|
||||||
|
|
||||||
for (let i = 0; i < h.length; i++) {
|
for (let i = 0; i < h.length; i++) {
|
||||||
proof.pi_h = G1.add( proof.pi_h, G1.mulScalar( vk_proof.hExps[i], h[i]));
|
proof.pi_h = G1.add( proof.pi_h, G1.mulScalar( vk_proof.hExps[i], h[i]));
|
||||||
@ -110,7 +115,56 @@ module.exports = function genProof(vk_proof, witness) {
|
|||||||
proof.pi_kp = G1.affine(proof.pi_kp);
|
proof.pi_kp = G1.affine(proof.pi_kp);
|
||||||
proof.pi_h = G1.affine(proof.pi_h);
|
proof.pi_h = G1.affine(proof.pi_h);
|
||||||
|
|
||||||
|
proof.h=h;
|
||||||
|
|
||||||
const publicSignals = witness.slice(1, vk_proof.nPublic+1);
|
const publicSignals = witness.slice(1, vk_proof.nPublic+1);
|
||||||
|
|
||||||
return {proof, publicSignals};
|
return {proof, publicSignals};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
const polZ_S = new Array(m+1).fill(F.zero);
|
||||||
|
polZ_S[m] = F.one;
|
||||||
|
polZ_S[0] = F.neg(F.one);
|
||||||
|
|
||||||
|
const H_S = PolF.div(polABC_S, polZ_S);
|
||||||
|
/*
|
||||||
|
const H2S = PolF.mul(H_S, polZ_S);
|
||||||
|
|
||||||
|
if (PolF.equals(H2S, polABC_S)) {
|
||||||
|
console.log("Is Divisible!");
|
||||||
|
} else {
|
||||||
|
console.log("ERROR: Not divisible!");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return H_S;
|
||||||
|
}
|
||||||
|
247
src/setup.js
247
src/setup.js
@ -3,17 +3,17 @@
|
|||||||
|
|
||||||
This file is part of zksnark JavaScript library.
|
This file is part of zksnark JavaScript library.
|
||||||
|
|
||||||
zksnark JavaScript library is a free software: you can redistribute it and/or
|
zksnark JavaScript library 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
|
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)
|
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
zksnark JavaScript library is distributed in the hope that it will be useful,
|
zksnark JavaScript library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
more details.
|
more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -43,7 +43,11 @@ module.exports = function setup(circuit) {
|
|||||||
toxic: {}
|
toxic: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
calculatePolynomials(setup, circuit);
|
|
||||||
|
setup.vk_proof.domainBits = PolF.log2(circuit.nConstraints + circuit.nPubInputs + circuit.nOutputs +1 -1) +1;
|
||||||
|
setup.vk_proof.domainSize = 1 << setup.vk_proof.domainBits;
|
||||||
|
|
||||||
|
calculatePolinomials(setup, circuit);
|
||||||
setup.toxic.t = F.random();
|
setup.toxic.t = F.random();
|
||||||
calculateEncriptedValuesAtT(setup, circuit);
|
calculateEncriptedValuesAtT(setup, circuit);
|
||||||
calculateHexps(setup, circuit);
|
calculateHexps(setup, circuit);
|
||||||
@ -51,128 +55,80 @@ module.exports = function setup(circuit) {
|
|||||||
return setup;
|
return setup;
|
||||||
};
|
};
|
||||||
|
|
||||||
function calculatePolynomials(setup, circuit) {
|
|
||||||
// Calculate the points that must cross each polynomial
|
|
||||||
|
|
||||||
/*
|
function calculatePolinomials(setup, circuit) {
|
||||||
setup.toxic.aExtra = [];
|
|
||||||
setup.toxic.bExtra = [];
|
setup.vk_proof.polsA = new Array(circuit.nVars);
|
||||||
setup.toxic.cExtra = [];
|
setup.vk_proof.polsB = new Array(circuit.nVars);
|
||||||
const aPoints = [];
|
setup.vk_proof.polsC = new Array(circuit.nVars);
|
||||||
const bPoints = [];
|
for (let i=0; i<circuit.nVars; i++) {
|
||||||
const cPoints = [];
|
setup.vk_proof.polsA[i] = {};
|
||||||
for (let s = 0; s<circuit.nVars; s++) {
|
setup.vk_proof.polsB[i] = {};
|
||||||
aPoints[s] = [];
|
setup.vk_proof.polsC[i] = {};
|
||||||
bPoints[s] = [];
|
|
||||||
cPoints[s] = [];
|
|
||||||
for (let c=0; c<circuit.nConstraints; c++) {
|
|
||||||
aPoints[s].push([[bigInt(c), F.one], [circuit.a(c, s), F.one]]);
|
|
||||||
bPoints[s].push([[bigInt(c), F.one], [circuit.b(c, s), F.one]]);
|
|
||||||
cPoints[s].push([[bigInt(c), F.one], [circuit.c(c, s), F.one]]);
|
|
||||||
}
|
|
||||||
// Add an extra point to avoid constant polinolials.
|
|
||||||
setup.toxic.aExtra[s] = F.random();
|
|
||||||
setup.toxic.bExtra[s] = F.random();
|
|
||||||
setup.toxic.cExtra[s] = F.random();
|
|
||||||
aPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.aExtra[s], F.one]]);
|
|
||||||
bPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.bExtra[s], F.one]]);
|
|
||||||
cPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.cExtra[s], F.one]]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the polynomials using Lagrange
|
|
||||||
setup.vk_proof.polsA = [];
|
|
||||||
setup.vk_proof.polsB = [];
|
|
||||||
setup.vk_proof.polsC = [];
|
|
||||||
for (let s=0; s<circuit.nVars; s++) {
|
|
||||||
// console.log(`Caclcualte Pol ${s}/${circuit.nVars}`);
|
|
||||||
const pA = RatPolF.lagrange( aPoints[s] );
|
|
||||||
const pB = RatPolF.lagrange( bPoints[s] );
|
|
||||||
const pC = RatPolF.lagrange( cPoints[s] );
|
|
||||||
|
|
||||||
setup.vk_proof.polsA.push( unrat(pA) );
|
|
||||||
setup.vk_proof.polsB.push( unrat(pB) );
|
|
||||||
setup.vk_proof.polsC.push( unrat(pC) );
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
setup.toxic.aExtra = [];
|
|
||||||
setup.toxic.bExtra = [];
|
|
||||||
setup.toxic.cExtra = [];
|
|
||||||
|
|
||||||
let allZerosPol = [bigInt(1)];
|
|
||||||
|
|
||||||
for (let c=0; c<=circuit.nConstraints; c++) {
|
|
||||||
allZerosPol = PolF.mul(allZerosPol, [F.neg(bigInt(c)), F.one]);
|
|
||||||
}
|
|
||||||
|
|
||||||
setup.vk_proof.polsA = [];
|
|
||||||
setup.vk_proof.polsB = [];
|
|
||||||
setup.vk_proof.polsC = [];
|
|
||||||
for (let s = 0; s<circuit.nVars; s++) {
|
|
||||||
setup.vk_proof.polsA.push([]);
|
|
||||||
setup.vk_proof.polsB.push([]);
|
|
||||||
setup.vk_proof.polsC.push([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let c=0; c<circuit.nConstraints; c++) {
|
for (let c=0; c<circuit.nConstraints; c++) {
|
||||||
const mpol = PolF.ruffini(allZerosPol, bigInt(c));
|
|
||||||
const normalizer = PolF.F.inverse(PolF.eval(mpol, bigInt(c)));
|
|
||||||
for (let s = 0; s<circuit.nVars; s++) {
|
|
||||||
const factorA = PolF.F.mul(normalizer, circuit.a(c, s));
|
|
||||||
const spolA = PolF.mulScalar(mpol, factorA);
|
|
||||||
setup.vk_proof.polsA[s] = PolF.add(setup.vk_proof.polsA[s], spolA);
|
|
||||||
|
|
||||||
const factorB = PolF.F.mul(normalizer, circuit.b(c, s));
|
for (let s in circuit.constraints[c][0]) {
|
||||||
const spolB = PolF.mulScalar(mpol, factorB);
|
setup.vk_proof.polsA[s][c] = bigInt(circuit.constraints[c][0][s]);
|
||||||
setup.vk_proof.polsB[s] = PolF.add(setup.vk_proof.polsB[s], spolB);
|
}
|
||||||
|
for (let s in circuit.constraints[c][1]) {
|
||||||
const factorC = PolF.F.mul(normalizer, circuit.c(c, s));
|
setup.vk_proof.polsB[s][c] = bigInt(circuit.constraints[c][1][s]);
|
||||||
const spolC = PolF.mulScalar(mpol, factorC);
|
}
|
||||||
setup.vk_proof.polsC[s] = PolF.add(setup.vk_proof.polsC[s], spolC);
|
for (let s in circuit.constraints[c][2]) {
|
||||||
|
setup.vk_proof.polsC[s][c] = bigInt(circuit.constraints[c][2][s]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const mpol = PolF.ruffini(allZerosPol, bigInt(circuit.nConstraints));
|
|
||||||
const normalizer = PolF.F.inverse(PolF.eval(mpol, bigInt(circuit.nConstraints)));
|
|
||||||
for (let s = 0; s<circuit.nVars; s++) {
|
|
||||||
setup.toxic.aExtra[s] = F.random();
|
|
||||||
const factorA = PolF.F.mul(normalizer, setup.toxic.aExtra[s]);
|
|
||||||
const spolA = PolF.mulScalar(mpol, factorA);
|
|
||||||
setup.vk_proof.polsA[s] = PolF.add(setup.vk_proof.polsA[s], spolA);
|
|
||||||
|
|
||||||
setup.toxic.bExtra[s] = F.random();
|
/**
|
||||||
const factorB = PolF.F.mul(normalizer, setup.toxic.bExtra[s]);
|
* add and process the constraints
|
||||||
const spolB = PolF.mulScalar(mpol, factorB);
|
* input_i * 0 = 0
|
||||||
setup.vk_proof.polsB[s] = PolF.add(setup.vk_proof.polsB[s], spolB);
|
* to ensure soundness of input consistency
|
||||||
|
*/
|
||||||
setup.toxic.cExtra[s] = F.random();
|
for (let i = 0; i < circuit.nPubInputs + circuit.nOutputs + 1; ++i)
|
||||||
const factorC = PolF.F.mul(normalizer, setup.toxic.cExtra[s]);
|
{
|
||||||
const spolC = PolF.mulScalar(mpol, factorC);
|
setup.vk_proof.polsA[i][circuit.nConstraints + i] = F.one;
|
||||||
setup.vk_proof.polsC[s] = PolF.add(setup.vk_proof.polsC[s], spolC);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate Z polynomial
|
|
||||||
// Z = 1
|
|
||||||
setup.vk_proof.polZ = [bigInt(1)];
|
|
||||||
for (let c=0; c<circuit.nConstraints; c++) {
|
|
||||||
// Z = Z * (x - p_c)
|
|
||||||
setup.vk_proof.polZ = PolF.mul(
|
|
||||||
setup.vk_proof.polZ,
|
|
||||||
[F.neg(bigInt(c)), bigInt(1)] );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateValuesAtT(setup, circuit) {
|
||||||
|
const z_t = PolF.computeVanishingPolinomial(setup.vk_proof.domainBits, setup.toxic.t);
|
||||||
|
const u = PolF.evaluateLagrangePolynomials(setup.vk_proof.domainBits, setup.toxic.t);
|
||||||
|
|
||||||
|
const a_t = new Array(circuit.nVars).fill(F.zero);
|
||||||
|
const b_t = new Array(circuit.nVars).fill(F.zero);
|
||||||
|
const c_t = new Array(circuit.nVars).fill(F.zero);
|
||||||
|
|
||||||
|
// TODO: substitute setup.polsA for coeficients
|
||||||
|
for (let s=0; s<circuit.nVars; s++) {
|
||||||
|
for (let c in setup.vk_proof.polsA[s]) {
|
||||||
|
a_t[s] = F.add(a_t[s], F.mul(u[c], setup.vk_proof.polsA[s][c]));
|
||||||
|
}
|
||||||
|
for (let c in setup.vk_proof.polsB[s]) {
|
||||||
|
b_t[s] = F.add(b_t[s], F.mul(u[c], setup.vk_proof.polsB[s][c]));
|
||||||
|
}
|
||||||
|
for (let c in setup.vk_proof.polsC[s]) {
|
||||||
|
c_t[s] = F.add(c_t[s], F.mul(u[c], setup.vk_proof.polsC[s][c]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {a_t, b_t, c_t, z_t};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function calculateEncriptedValuesAtT(setup, circuit) {
|
function calculateEncriptedValuesAtT(setup, circuit) {
|
||||||
setup.vk_proof.A = [];
|
|
||||||
setup.vk_proof.B = [];
|
const v = calculateValuesAtT(setup, circuit);
|
||||||
setup.vk_proof.C = [];
|
setup.vk_proof.A = new Array(circuit.nVars);
|
||||||
setup.vk_proof.Ap = [];
|
setup.vk_proof.B = new Array(circuit.nVars);
|
||||||
setup.vk_proof.Bp = [];
|
setup.vk_proof.C = new Array(circuit.nVars);
|
||||||
setup.vk_proof.Cp = [];
|
setup.vk_proof.Ap = new Array(circuit.nVars);
|
||||||
setup.vk_proof.Kp = [];
|
setup.vk_proof.Bp = new Array(circuit.nVars);
|
||||||
setup.vk_verifier.A = [];
|
setup.vk_proof.Cp = new Array(circuit.nVars);
|
||||||
|
setup.vk_proof.Kp = new Array(circuit.nVars);
|
||||||
|
setup.vk_verifier.A = new Array(circuit.nVars);
|
||||||
|
|
||||||
setup.toxic.ka = F.random();
|
setup.toxic.ka = F.random();
|
||||||
setup.toxic.kb = F.random();
|
setup.toxic.kb = F.random();
|
||||||
@ -192,37 +148,34 @@ function calculateEncriptedValuesAtT(setup, circuit) {
|
|||||||
for (let s=0; s<circuit.nVars; s++) {
|
for (let s=0; s<circuit.nVars; s++) {
|
||||||
|
|
||||||
// A[i] = G1 * polA(t)
|
// A[i] = G1 * polA(t)
|
||||||
const at = F.affine(PolF.eval(setup.vk_proof.polsA[s], setup.toxic.t));
|
const A = G1.affine(G1.mulScalar(G1.g, v.a_t[s]));
|
||||||
const A = G1.affine(G1.mulScalar(G1.g, at));
|
|
||||||
|
|
||||||
setup.vk_proof.A.push(A);
|
setup.vk_proof.A[s] = A;
|
||||||
|
|
||||||
if (s <= setup.vk_proof.nPublic) {
|
if (s <= setup.vk_proof.nPublic) {
|
||||||
setup.vk_verifier.A.push(A);
|
setup.vk_verifier.A[s]=A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// B1[i] = G1 * polB(t)
|
// B1[i] = G1 * polB(t)
|
||||||
const bt = F.affine(PolF.eval(setup.vk_proof.polsB[s], setup.toxic.t));
|
const B1 = G1.affine(G1.mulScalar(G1.g, v.b_t[s]));
|
||||||
const B1 = G1.affine(G1.mulScalar(G1.g, bt));
|
|
||||||
|
|
||||||
// B2[i] = G2 * polB(t)
|
// B2[i] = G2 * polB(t)
|
||||||
const B2 = G2.affine(G2.mulScalar(G2.g, bt));
|
const B2 = G2.affine(G2.mulScalar(G2.g, v.b_t[s]));
|
||||||
|
|
||||||
setup.vk_proof.B.push(B2);
|
setup.vk_proof.B[s]=B2;
|
||||||
|
|
||||||
// C[i] = G1 * polC(t)
|
// C[i] = G1 * polC(t)
|
||||||
const ct = F.affine(PolF.eval(setup.vk_proof.polsC[s], setup.toxic.t));
|
const C = G1.affine(G1.mulScalar( G1.g, v.c_t[s]));
|
||||||
const C = G1.affine(G1.mulScalar( G1.g, ct));
|
setup.vk_proof.C[s] =C;
|
||||||
setup.vk_proof.C.push (C);
|
|
||||||
|
|
||||||
// K = G1 * (A+B+C)
|
// K = G1 * (A+B+C)
|
||||||
|
|
||||||
const kt = F.affine(F.add(F.add(at, bt), ct));
|
const kt = F.affine(F.add(F.add(v.a_t[s], v.b_t[s]), v.c_t[s]));
|
||||||
const K = G1.affine(G1.mulScalar( G1.g, kt));
|
const K = G1.affine(G1.mulScalar( G1.g, kt));
|
||||||
|
|
||||||
|
|
||||||
|
// Comment this lines to improve the process
|
||||||
const Ktest = G1.affine(G1.add(G1.add(A, B1), C));
|
const Ktest = G1.affine(G1.add(G1.add(A, B1), C));
|
||||||
|
|
||||||
if (!G1.equals(K, Ktest)) {
|
if (!G1.equals(K, Ktest)) {
|
||||||
@ -231,30 +184,20 @@ function calculateEncriptedValuesAtT(setup, circuit) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
setup.vk_proof.Ap.push(G1.affine(G1.mulScalar(A, setup.toxic.ka)));
|
setup.vk_proof.Ap[s] = G1.affine(G1.mulScalar(A, setup.toxic.ka));
|
||||||
setup.vk_proof.Bp.push(G1.affine(G1.mulScalar(B1, setup.toxic.kb)));
|
setup.vk_proof.Bp[s] = G1.affine(G1.mulScalar(B1, setup.toxic.kb));
|
||||||
setup.vk_proof.Cp.push(G1.affine(G1.mulScalar(C, setup.toxic.kc)));
|
setup.vk_proof.Cp[s] = G1.affine(G1.mulScalar(C, setup.toxic.kc));
|
||||||
setup.vk_proof.Kp.push(G1.affine(G1.mulScalar(K, setup.toxic.kbeta)));
|
setup.vk_proof.Kp[s] = G1.affine(G1.mulScalar(K, setup.toxic.kbeta));
|
||||||
}
|
}
|
||||||
|
|
||||||
setup.vk_verifier.vk_z = G2.affine(G2.mulScalar(
|
setup.vk_verifier.vk_z = G2.affine(G2.mulScalar(
|
||||||
G2.g,
|
G2.g,
|
||||||
PolF.eval(setup.vk_proof.polZ, setup.toxic.t)));
|
v.z_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateHexps(setup, circuit) {
|
function calculateHexps(setup, circuit) {
|
||||||
let maxA = 0;
|
|
||||||
let maxB = 0;
|
|
||||||
let maxC = 0;
|
|
||||||
for (let s=0; s<circuit.nVars; s++) {
|
|
||||||
maxA = Math.max(maxA, setup.vk_proof.polsA[s].length);
|
|
||||||
maxB = Math.max(maxB, setup.vk_proof.polsB[s].length);
|
|
||||||
maxC = Math.max(maxC, setup.vk_proof.polsC[s].length);
|
|
||||||
}
|
|
||||||
|
|
||||||
let maxFull = Math.max(maxA + maxB - 1, maxC);
|
const maxH = setup.vk_proof.domainSize;
|
||||||
|
|
||||||
const maxH = maxFull - setup.vk_proof.polZ.length + 1;
|
|
||||||
|
|
||||||
setup.vk_proof.hExps = new Array(maxH);
|
setup.vk_proof.hExps = new Array(maxH);
|
||||||
setup.vk_proof.hExps[0] = G1.g;
|
setup.vk_proof.hExps[0] = G1.g;
|
||||||
@ -264,12 +207,4 @@ function calculateHexps(setup, circuit) {
|
|||||||
eT = F.mul(eT, setup.toxic.t);
|
eT = F.mul(eT, setup.toxic.t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
function unrat(p) {
|
|
||||||
const res = new Array(p.length);
|
|
||||||
for (let i=0; i<p.length; i++) {
|
|
||||||
res[i] = RatPolF.F.toF(p[i]);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
353
src/setup_old.js
Normal file
353
src/setup_old.js
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 0kims association.
|
||||||
|
|
||||||
|
This file is part of zksnark JavaScript library.
|
||||||
|
|
||||||
|
zksnark JavaScript library 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.
|
||||||
|
|
||||||
|
zksnark JavaScript library 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
|
||||||
|
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const bigInt = require("./bigint.js");
|
||||||
|
|
||||||
|
const BN128 = require("./bn128.js");
|
||||||
|
const PolField = require("./polfield.js");
|
||||||
|
const ZqField = require("./zqfield.js");
|
||||||
|
const RatField = require("./ratfield.js");
|
||||||
|
|
||||||
|
const bn128 = new BN128();
|
||||||
|
const G1 = bn128.G1;
|
||||||
|
const G2 = bn128.G2;
|
||||||
|
const PolF = new PolField(new ZqField(bn128.r));
|
||||||
|
const RatPolF = new PolField(new RatField(new ZqField(bn128.r)));
|
||||||
|
const F = new ZqField(bn128.r);
|
||||||
|
|
||||||
|
module.exports = function setup(circuit) {
|
||||||
|
const setup = {
|
||||||
|
vk_proof : {
|
||||||
|
nVars: circuit.nVars,
|
||||||
|
nPublic: circuit.nPubInputs + circuit.nOutputs
|
||||||
|
},
|
||||||
|
vk_verifier: {
|
||||||
|
nPublic: circuit.nPubInputs + circuit.nOutputs
|
||||||
|
},
|
||||||
|
toxic: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
calculatePolynomials2(setup, circuit);
|
||||||
|
setup.toxic.t = F.random();
|
||||||
|
calculateEncriptedValuesAtT(setup, circuit);
|
||||||
|
calculateHexps(setup, circuit);
|
||||||
|
|
||||||
|
return setup;
|
||||||
|
};
|
||||||
|
|
||||||
|
function calculatePolynomials(setup, circuit) {
|
||||||
|
// Calculate the points that must cross each polynomial
|
||||||
|
|
||||||
|
/*
|
||||||
|
setup.toxic.aExtra = [];
|
||||||
|
setup.toxic.bExtra = [];
|
||||||
|
setup.toxic.cExtra = [];
|
||||||
|
const aPoints = [];
|
||||||
|
const bPoints = [];
|
||||||
|
const cPoints = [];
|
||||||
|
for (let s = 0; s<circuit.nVars; s++) {
|
||||||
|
aPoints[s] = [];
|
||||||
|
bPoints[s] = [];
|
||||||
|
cPoints[s] = [];
|
||||||
|
for (let c=0; c<circuit.nConstraints; c++) {
|
||||||
|
aPoints[s].push([[bigInt(c), F.one], [circuit.a(c, s), F.one]]);
|
||||||
|
bPoints[s].push([[bigInt(c), F.one], [circuit.b(c, s), F.one]]);
|
||||||
|
cPoints[s].push([[bigInt(c), F.one], [circuit.c(c, s), F.one]]);
|
||||||
|
}
|
||||||
|
// Add an extra point to avoid constant polinolials.
|
||||||
|
setup.toxic.aExtra[s] = F.random();
|
||||||
|
setup.toxic.bExtra[s] = F.random();
|
||||||
|
setup.toxic.cExtra[s] = F.random();
|
||||||
|
aPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.aExtra[s], F.one]]);
|
||||||
|
bPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.bExtra[s], F.one]]);
|
||||||
|
cPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.cExtra[s], F.one]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the polynomials using Lagrange
|
||||||
|
setup.vk_proof.polsA = [];
|
||||||
|
setup.vk_proof.polsB = [];
|
||||||
|
setup.vk_proof.polsC = [];
|
||||||
|
for (let s=0; s<circuit.nVars; s++) {
|
||||||
|
// console.log(`Caclcualte Pol ${s}/${circuit.nVars}`);
|
||||||
|
const pA = RatPolF.lagrange( aPoints[s] );
|
||||||
|
const pB = RatPolF.lagrange( bPoints[s] );
|
||||||
|
const pC = RatPolF.lagrange( cPoints[s] );
|
||||||
|
|
||||||
|
setup.vk_proof.polsA.push( unrat(pA) );
|
||||||
|
setup.vk_proof.polsB.push( unrat(pB) );
|
||||||
|
setup.vk_proof.polsC.push( unrat(pC) );
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
setup.toxic.aExtra = [];
|
||||||
|
setup.toxic.bExtra = [];
|
||||||
|
setup.toxic.cExtra = [];
|
||||||
|
|
||||||
|
let allZerosPol = [bigInt(1)];
|
||||||
|
|
||||||
|
for (let c=0; c<=circuit.nConstraints; c++) {
|
||||||
|
allZerosPol = PolF.mul(allZerosPol, [F.neg(bigInt(c)), F.one]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.vk_proof.polsA = [];
|
||||||
|
setup.vk_proof.polsB = [];
|
||||||
|
setup.vk_proof.polsC = [];
|
||||||
|
for (let s = 0; s<circuit.nVars; s++) {
|
||||||
|
setup.vk_proof.polsA.push([]);
|
||||||
|
setup.vk_proof.polsB.push([]);
|
||||||
|
setup.vk_proof.polsC.push([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let c=0; c<circuit.nConstraints; c++) {
|
||||||
|
console.log("Pol: "+ c);
|
||||||
|
const mpol = PolF.ruffini(allZerosPol, bigInt(c));
|
||||||
|
const normalizer = PolF.F.inverse(PolF.eval(mpol, bigInt(c)));
|
||||||
|
for (let s = 0; s<circuit.nVars; s++) {
|
||||||
|
if (!circuit.a(c, s).isZero()) {
|
||||||
|
const factorA = PolF.F.mul(normalizer, circuit.a(c, s));
|
||||||
|
const spolA = PolF.mulScalar(mpol, factorA);
|
||||||
|
setup.vk_proof.polsA[s] = PolF.add(setup.vk_proof.polsA[s], spolA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!circuit.b(c, s).isZero()) {
|
||||||
|
const factorB = PolF.F.mul(normalizer, circuit.b(c, s));
|
||||||
|
const spolB = PolF.mulScalar(mpol, factorB);
|
||||||
|
setup.vk_proof.polsB[s] = PolF.add(setup.vk_proof.polsB[s], spolB);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!circuit.c(c, s).isZero()) {
|
||||||
|
const factorC = PolF.F.mul(normalizer, circuit.c(c, s));
|
||||||
|
const spolC = PolF.mulScalar(mpol, factorC);
|
||||||
|
setup.vk_proof.polsC[s] = PolF.add(setup.vk_proof.polsC[s], spolC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (global.gc) {
|
||||||
|
if (c%100 == 0) global.gc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mpol = PolF.ruffini(allZerosPol, bigInt(circuit.nConstraints));
|
||||||
|
const normalizer = PolF.F.inverse(PolF.eval(mpol, bigInt(circuit.nConstraints)));
|
||||||
|
for (let s = 0; s<circuit.nVars; s++) {
|
||||||
|
setup.toxic.aExtra[s] = F.random();
|
||||||
|
const factorA = PolF.F.mul(normalizer, setup.toxic.aExtra[s]);
|
||||||
|
const spolA = PolF.mulScalar(mpol, factorA);
|
||||||
|
setup.vk_proof.polsA[s] = PolF.add(setup.vk_proof.polsA[s], spolA);
|
||||||
|
|
||||||
|
setup.toxic.bExtra[s] = F.random();
|
||||||
|
const factorB = PolF.F.mul(normalizer, setup.toxic.bExtra[s]);
|
||||||
|
const spolB = PolF.mulScalar(mpol, factorB);
|
||||||
|
setup.vk_proof.polsB[s] = PolF.add(setup.vk_proof.polsB[s], spolB);
|
||||||
|
|
||||||
|
setup.toxic.cExtra[s] = F.random();
|
||||||
|
const factorC = PolF.F.mul(normalizer, setup.toxic.cExtra[s]);
|
||||||
|
const spolC = PolF.mulScalar(mpol, factorC);
|
||||||
|
setup.vk_proof.polsC[s] = PolF.add(setup.vk_proof.polsC[s], spolC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate Z polynomial
|
||||||
|
// Z = 1
|
||||||
|
setup.vk_proof.polZ = [bigInt(1)];
|
||||||
|
for (let c=0; c<circuit.nConstraints; c++) {
|
||||||
|
// Z = Z * (x - p_c)
|
||||||
|
setup.vk_proof.polZ = PolF.mul(
|
||||||
|
setup.vk_proof.polZ,
|
||||||
|
[F.neg(bigInt(c)), bigInt(1)] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculatePolynomials2(setup, circuit) {
|
||||||
|
setup.toxic.aExtra = [];
|
||||||
|
setup.toxic.bExtra = [];
|
||||||
|
setup.toxic.cExtra = [];
|
||||||
|
setup.vk_proof.polsA = [];
|
||||||
|
setup.vk_proof.polsB = [];
|
||||||
|
setup.vk_proof.polsC = [];
|
||||||
|
const aPoints = new Array(circuit.nConstraints+1);
|
||||||
|
const bPoints = new Array(circuit.nConstraints+1);
|
||||||
|
const cPoints = new Array(circuit.nConstraints+1);
|
||||||
|
|
||||||
|
for (let s = 0; s<circuit.nVars; s++) {
|
||||||
|
for (let c=0; c<circuit.nConstraints; c++) {
|
||||||
|
aPoints[c] = circuit.a(c, s);
|
||||||
|
bPoints[c] = circuit.b(c, s);
|
||||||
|
cPoints[c] = circuit.c(c, s);
|
||||||
|
}
|
||||||
|
// Add an extra point to avoid constant polinolials.
|
||||||
|
setup.toxic.aExtra[s] = F.random();
|
||||||
|
setup.toxic.bExtra[s] = F.random();
|
||||||
|
setup.toxic.cExtra[s] = F.random();
|
||||||
|
aPoints[circuit.nConstraints] = setup.toxic.aExtra[s];
|
||||||
|
bPoints[circuit.nConstraints] = setup.toxic.bExtra[s];
|
||||||
|
cPoints[circuit.nConstraints] = setup.toxic.cExtra[s];
|
||||||
|
|
||||||
|
const pA = PolF.ifft( aPoints );
|
||||||
|
const pB = PolF.ifft( bPoints );
|
||||||
|
const pC = PolF.ifft( cPoints );
|
||||||
|
|
||||||
|
setup.vk_proof.polsA.push( PolF.affine(pA) );
|
||||||
|
setup.vk_proof.polsB.push( PolF.affine(pB) );
|
||||||
|
setup.vk_proof.polsC.push( PolF.affine(pC) );
|
||||||
|
|
||||||
|
console.log(s);
|
||||||
|
|
||||||
|
if (global.gc) {
|
||||||
|
if (s%100 == 0) global.gc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.polsLen=PolF._next2Power(circuit.nConstraints+1);
|
||||||
|
|
||||||
|
// Calculate Z polynomial
|
||||||
|
// Z = 1
|
||||||
|
|
||||||
|
|
||||||
|
const bits= log2(circuit.nConstraints)+1;
|
||||||
|
const rt1 = PolF.w[bits];
|
||||||
|
|
||||||
|
let rt = bigInt(1);
|
||||||
|
setup.vk_proof.polZ = [F.one];
|
||||||
|
for (let c=0; c<circuit.nConstraints; c++) {
|
||||||
|
// Z = Z * (x - p_c)
|
||||||
|
setup.vk_proof.polZ = PolF.mul(
|
||||||
|
setup.vk_proof.polZ,
|
||||||
|
[F.neg(rt), F.one] );
|
||||||
|
|
||||||
|
rt = F.mul(rt, rt1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.vk_proof.polZ = PolF.affine(setup.vk_proof.polZ);
|
||||||
|
|
||||||
|
function log2( V )
|
||||||
|
{
|
||||||
|
return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateEncriptedValuesAtT(setup, circuit) {
|
||||||
|
setup.vk_proof.A = [];
|
||||||
|
setup.vk_proof.B = [];
|
||||||
|
setup.vk_proof.C = [];
|
||||||
|
setup.vk_proof.Ap = [];
|
||||||
|
setup.vk_proof.Bp = [];
|
||||||
|
setup.vk_proof.Cp = [];
|
||||||
|
setup.vk_proof.Kp = [];
|
||||||
|
setup.vk_verifier.A = [];
|
||||||
|
|
||||||
|
setup.toxic.ka = F.random();
|
||||||
|
setup.toxic.kb = F.random();
|
||||||
|
setup.toxic.kc = F.random();
|
||||||
|
setup.toxic.kbeta = F.random();
|
||||||
|
setup.toxic.kgamma = F.random();
|
||||||
|
|
||||||
|
const gb = F.mul(setup.toxic.kbeta, setup.toxic.kgamma);
|
||||||
|
|
||||||
|
setup.vk_verifier.vk_a = G2.affine(G2.mulScalar( G2.g, setup.toxic.ka));
|
||||||
|
setup.vk_verifier.vk_b = G1.affine(G1.mulScalar( G1.g, setup.toxic.kb));
|
||||||
|
setup.vk_verifier.vk_c = G2.affine(G2.mulScalar( G2.g, setup.toxic.kc));
|
||||||
|
setup.vk_verifier.vk_gb_1 = G1.affine(G1.mulScalar( G1.g, gb));
|
||||||
|
setup.vk_verifier.vk_gb_2 = G2.affine(G2.mulScalar( G2.g, gb));
|
||||||
|
setup.vk_verifier.vk_g = G2.affine(G2.mulScalar( G2.g, setup.toxic.kgamma));
|
||||||
|
|
||||||
|
for (let s=0; s<circuit.nVars; s++) {
|
||||||
|
|
||||||
|
// A[i] = G1 * polA(t)
|
||||||
|
const at = F.affine(PolF.eval(setup.vk_proof.polsA[s], setup.toxic.t));
|
||||||
|
const A = G1.affine(G1.mulScalar(G1.g, at));
|
||||||
|
|
||||||
|
setup.vk_proof.A.push(A);
|
||||||
|
|
||||||
|
if (s <= setup.vk_proof.nPublic) {
|
||||||
|
setup.vk_verifier.A.push(A);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// B1[i] = G1 * polB(t)
|
||||||
|
const bt = F.affine(PolF.eval(setup.vk_proof.polsB[s], setup.toxic.t));
|
||||||
|
const B1 = G1.affine(G1.mulScalar(G1.g, bt));
|
||||||
|
|
||||||
|
// B2[i] = G2 * polB(t)
|
||||||
|
const B2 = G2.affine(G2.mulScalar(G2.g, bt));
|
||||||
|
|
||||||
|
setup.vk_proof.B.push(B2);
|
||||||
|
|
||||||
|
// C[i] = G1 * polC(t)
|
||||||
|
const ct = F.affine(PolF.eval(setup.vk_proof.polsC[s], setup.toxic.t));
|
||||||
|
const C = G1.affine(G1.mulScalar( G1.g, ct));
|
||||||
|
setup.vk_proof.C.push (C);
|
||||||
|
|
||||||
|
// K = G1 * (A+B+C)
|
||||||
|
|
||||||
|
const kt = F.affine(F.add(F.add(at, bt), ct));
|
||||||
|
const K = G1.affine(G1.mulScalar( G1.g, kt));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const Ktest = G1.affine(G1.add(G1.add(A, B1), C));
|
||||||
|
|
||||||
|
if (!G1.equals(K, Ktest)) {
|
||||||
|
console.log ("=====FAIL======");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setup.vk_proof.Ap.push(G1.affine(G1.mulScalar(A, setup.toxic.ka)));
|
||||||
|
setup.vk_proof.Bp.push(G1.affine(G1.mulScalar(B1, setup.toxic.kb)));
|
||||||
|
setup.vk_proof.Cp.push(G1.affine(G1.mulScalar(C, setup.toxic.kc)));
|
||||||
|
setup.vk_proof.Kp.push(G1.affine(G1.mulScalar(K, setup.toxic.kbeta)));
|
||||||
|
}
|
||||||
|
|
||||||
|
setup.vk_verifier.vk_z = G2.affine(G2.mulScalar(
|
||||||
|
G2.g,
|
||||||
|
PolF.eval(setup.vk_proof.polZ, setup.toxic.t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateHexps(setup, circuit) {
|
||||||
|
let maxA = 0;
|
||||||
|
let maxB = 0;
|
||||||
|
let maxC = 0;
|
||||||
|
for (let s=0; s<circuit.nVars; s++) {
|
||||||
|
maxA = Math.max(maxA, setup.vk_proof.polsA[s].length);
|
||||||
|
maxB = Math.max(maxB, setup.vk_proof.polsB[s].length);
|
||||||
|
maxC = Math.max(maxC, setup.vk_proof.polsC[s].length);
|
||||||
|
}
|
||||||
|
|
||||||
|
let maxFull = Math.max(maxA + maxB - 1, maxC);
|
||||||
|
|
||||||
|
const maxH = maxFull - setup.vk_proof.polZ.length + 1;
|
||||||
|
|
||||||
|
setup.vk_proof.hExps = new Array(maxH);
|
||||||
|
setup.vk_proof.hExps[0] = G1.g;
|
||||||
|
let eT = setup.toxic.t;
|
||||||
|
for (let i=1; i<maxH; i++) {
|
||||||
|
setup.vk_proof.hExps[i] = G1.affine(G1.mulScalar(G1.g, eT));
|
||||||
|
eT = F.mul(eT, setup.toxic.t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
function unrat(p) {
|
||||||
|
const res = new Array(p.length);
|
||||||
|
for (let i=0; i<p.length; i++) {
|
||||||
|
res[i] = RatPolF.F.toF(p[i]);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
*/
|
@ -3,17 +3,17 @@
|
|||||||
|
|
||||||
This file is part of zksnark JavaScript library.
|
This file is part of zksnark JavaScript library.
|
||||||
|
|
||||||
zksnark JavaScript library is a free software: you can redistribute it and/or
|
zksnark JavaScript library 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
|
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)
|
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
zksnark JavaScript library is distributed in the hope that it will be useful,
|
zksnark JavaScript library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
more details.
|
more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -49,14 +49,6 @@ module.exports = function isValid(vk_verifier, proof, publicSignals) {
|
|||||||
bn128.pairing( proof.pi_cp , G2.g )))
|
bn128.pairing( proof.pi_cp , G2.g )))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (! bn128.F12.equals(
|
|
||||||
bn128.pairing( full_pi_a , proof.pi_b ),
|
|
||||||
bn128.F12.mul(
|
|
||||||
bn128.pairing( proof.pi_h , vk_verifier.vk_z ),
|
|
||||||
bn128.pairing( proof.pi_c , G2.g ),
|
|
||||||
)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (! bn128.F12.equals(
|
if (! bn128.F12.equals(
|
||||||
bn128.F12.mul(
|
bn128.F12.mul(
|
||||||
bn128.pairing( G1.add(full_pi_a, proof.pi_c) , vk_verifier.vk_gb_2 ),
|
bn128.pairing( G1.add(full_pi_a, proof.pi_c) , vk_verifier.vk_gb_2 ),
|
||||||
@ -65,6 +57,15 @@ module.exports = function isValid(vk_verifier, proof, publicSignals) {
|
|||||||
bn128.pairing( proof.pi_kp , vk_verifier.vk_g )))
|
bn128.pairing( proof.pi_kp , vk_verifier.vk_g )))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (! bn128.F12.equals(
|
||||||
|
bn128.pairing( full_pi_a , proof.pi_b ),
|
||||||
|
bn128.F12.mul(
|
||||||
|
bn128.pairing( proof.pi_h , vk_verifier.vk_z ),
|
||||||
|
bn128.pairing( proof.pi_c , G2.g ),
|
||||||
|
)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
1161222
test/circuit/sha256_2.json
Normal file
1161222
test/circuit/sha256_2.json
Normal file
File diff suppressed because one or more lines are too long
57
test/pols.js
57
test/pols.js
@ -3,17 +3,17 @@
|
|||||||
|
|
||||||
This file is part of zksnark JavaScript library.
|
This file is part of zksnark JavaScript library.
|
||||||
|
|
||||||
zksnark JavaScript library is a free software: you can redistribute it and/or
|
zksnark JavaScript library 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
|
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)
|
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
zksnark JavaScript library is distributed in the hope that it will be useful,
|
zksnark JavaScript library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
more details.
|
more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -128,6 +128,12 @@ describe("Polynomial field", () => {
|
|||||||
const v = PF.eval(p, bigInt(2));
|
const v = PF.eval(p, bigInt(2));
|
||||||
assert(PF.F.equals(v, bigInt(0)));
|
assert(PF.F.equals(v, bigInt(0)));
|
||||||
});
|
});
|
||||||
|
it("Should evaluate bigger number", () => {
|
||||||
|
const PF = new PolField(new ZqField(r));
|
||||||
|
const p = [bigInt(1), bigInt(2), bigInt(3)];
|
||||||
|
const v = PF.eval(p, bigInt(2));
|
||||||
|
assert(PF.F.equals(v, bigInt(17)));
|
||||||
|
});
|
||||||
it("Should create lagrange polynomial minmal", () => {
|
it("Should create lagrange polynomial minmal", () => {
|
||||||
const PF = new PolField(new ZqField(r));
|
const PF = new PolField(new ZqField(r));
|
||||||
|
|
||||||
@ -168,5 +174,44 @@ describe("Polynomial field", () => {
|
|||||||
|
|
||||||
assert(PF.equals(a, c));
|
assert(PF.equals(a, c));
|
||||||
});
|
});
|
||||||
|
it("Should test roots", () => {
|
||||||
|
const PF = new PolField(new ZqField(r));
|
||||||
|
let rt;
|
||||||
|
|
||||||
|
|
||||||
|
rt = PF.oneRoot(256, 16);
|
||||||
|
for (let i=0; i<8; i++) {
|
||||||
|
rt = PF.F.mul(rt, rt);
|
||||||
|
}
|
||||||
|
assert(rt.equals(PF.F.one));
|
||||||
|
|
||||||
|
rt = PF.oneRoot(256, 15);
|
||||||
|
for (let i=0; i<8; i++) {
|
||||||
|
rt = PF.F.mul(rt, rt);
|
||||||
|
}
|
||||||
|
assert(rt.equals(PF.F.one));
|
||||||
|
|
||||||
|
rt = PF.oneRoot(8, 3);
|
||||||
|
for (let i=0; i<3; i++) {
|
||||||
|
rt = PF.F.mul(rt, rt);
|
||||||
|
}
|
||||||
|
assert(rt.equals(PF.F.one));
|
||||||
|
|
||||||
|
rt = PF.oneRoot(8, 0);
|
||||||
|
assert(rt.equals(PF.F.one));
|
||||||
|
|
||||||
|
});
|
||||||
|
it("Should create a polynomial with values at roots with fft", () => {
|
||||||
|
const PF = new PolField(new ZqField(r));
|
||||||
|
const a = [bigInt(1), bigInt(2), bigInt(3), bigInt(4), bigInt(5),bigInt(6), bigInt(7)];
|
||||||
|
|
||||||
|
const p = PF.ifft(a);
|
||||||
|
|
||||||
|
for (let i=0; i<a.length; i++) {
|
||||||
|
const s = PF.F.affine(PF.eval(p, PF.oneRoot(8,i)));
|
||||||
|
assert(s.equals(a[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
153
test/zksnark.js
153
test/zksnark.js
@ -3,17 +3,17 @@
|
|||||||
|
|
||||||
This file is part of zksnark JavaScript library.
|
This file is part of zksnark JavaScript library.
|
||||||
|
|
||||||
zksnark JavaScript library is a free software: you can redistribute it and/or
|
zksnark JavaScript library 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
|
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)
|
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
zksnark JavaScript library is distributed in the hope that it will be useful,
|
zksnark JavaScript library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
more details.
|
more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -24,6 +24,13 @@ const bigInt = require("../src/bigint.js");
|
|||||||
|
|
||||||
const Circuit = require("../src/circuit.js");
|
const Circuit = require("../src/circuit.js");
|
||||||
const zkSnark = require("../index.js");
|
const zkSnark = require("../index.js");
|
||||||
|
const BN128 = require("../src/bn128.js");
|
||||||
|
const PolField = require("../src/polfield.js");
|
||||||
|
const ZqField = require("../src/zqfield.js");
|
||||||
|
const bn128 = new BN128();
|
||||||
|
const PolF = new PolField(new ZqField(bn128.r));
|
||||||
|
const G1 = bn128.G1;
|
||||||
|
const G2 = bn128.G2;
|
||||||
|
|
||||||
const assert = chai.assert;
|
const assert = chai.assert;
|
||||||
|
|
||||||
@ -60,9 +67,11 @@ function unstringifyBigInts(o) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
describe("zkSnark", () => {
|
describe("zkSnark", () => {
|
||||||
it("Load a circuit, create trusted setup, create a proof and validate it", () => {
|
it("Load a circuit, create trusted setup, create a proof and validate it", () => {
|
||||||
|
|
||||||
|
|
||||||
const cirDef = JSON.parse(fs.readFileSync(path.join(__dirname, "circuit", "sum.json"), "utf8"));
|
const cirDef = JSON.parse(fs.readFileSync(path.join(__dirname, "circuit", "sum.json"), "utf8"));
|
||||||
const cir = new Circuit(cirDef);
|
const cir = new Circuit(cirDef);
|
||||||
|
|
||||||
@ -71,17 +80,145 @@ describe("zkSnark", () => {
|
|||||||
fs.writeFileSync("vk_proof.json", JSON.stringify(strSetup.vk_proof), "utf-8");
|
fs.writeFileSync("vk_proof.json", JSON.stringify(strSetup.vk_proof), "utf-8");
|
||||||
fs.writeFileSync("vk_verifier.json", JSON.stringify(strSetup.vk_verifier), "utf-8");
|
fs.writeFileSync("vk_verifier.json", JSON.stringify(strSetup.vk_verifier), "utf-8");
|
||||||
|
|
||||||
|
|
||||||
|
function polT2S(p) {
|
||||||
|
const p_T = new Array(setup.vk_proof.domainSize).fill(bigInt(0));
|
||||||
|
|
||||||
|
for (let c in p) {
|
||||||
|
p_T[c] = p[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
return PolF.ifft(p_T);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
const setup = {};
|
||||||
|
setup.vk_proof = unstringifyBigInts(JSON.parse(fs.readFileSync("vk_proof.json", "utf8")));
|
||||||
|
setup.vk_verifier = unstringifyBigInts(JSON.parse(fs.readFileSync("vk_verifier.json", "utf8")));
|
||||||
|
*/
|
||||||
|
const witness = cir.calculateWitness({"a": "33", "b": "34"});
|
||||||
|
|
||||||
|
const {proof, publicSignals} = zkSnark.genProof(setup.vk_proof, witness);
|
||||||
|
|
||||||
|
/*
|
||||||
|
const polA = new Array(cir.nVars);
|
||||||
|
const polB = new Array(cir.nVars);
|
||||||
|
const polC = new Array(cir.nVars);
|
||||||
|
for (let i=0; i<cir.nVars; i++) {
|
||||||
|
polA[i] = polT2S(setup.vk_proof.polsA[i]);
|
||||||
|
polB[i] = polT2S(setup.vk_proof.polsB[i]);
|
||||||
|
polC[i] = polT2S(setup.vk_proof.polsC[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
PolF._setRoots(setup.vk_proof.domainBits);
|
||||||
|
for (let c=0; c<setup.vk_proof.domainSize; c++) {
|
||||||
|
let A = bigInt(0);
|
||||||
|
let B = bigInt(0);
|
||||||
|
let C = bigInt(0);
|
||||||
|
for (let s=0; s<cir.nVars; s++) {
|
||||||
|
A = PolF.F.add(A, PolF.F.mul(PolF.eval(polA[s], PolF.roots[setup.vk_proof.domainBits][c]), witness[s]));
|
||||||
|
B = PolF.F.add(B, PolF.F.mul(PolF.eval(polB[s], PolF.roots[setup.vk_proof.domainBits][c]), witness[s]));
|
||||||
|
C = PolF.F.add(C, PolF.F.mul(PolF.eval(polC[s], PolF.roots[setup.vk_proof.domainBits][c]), witness[s]));
|
||||||
|
}
|
||||||
|
assert(PolF.F.equals(PolF.F.mul(A,B), C));
|
||||||
|
}
|
||||||
|
|
||||||
|
let A = bigInt(0);
|
||||||
|
let B = bigInt(0);
|
||||||
|
let C = bigInt(0);
|
||||||
|
for (let s=0; s<cir.nVars; s++) {
|
||||||
|
A = PolF.F.add(A, PolF.F.mul(PolF.eval(polA[s], setup.toxic.t), witness[s]));
|
||||||
|
B = PolF.F.add(B, PolF.F.mul(PolF.eval(polB[s], setup.toxic.t), witness[s]));
|
||||||
|
C = PolF.F.add(C, PolF.F.mul(PolF.eval(polC[s], setup.toxic.t), witness[s]));
|
||||||
|
}
|
||||||
|
|
||||||
|
let A2 = bigInt(0);
|
||||||
|
let B2 = bigInt(0);
|
||||||
|
let C2 = bigInt(0);
|
||||||
|
const u = PolF.evaluateLagrangePolynomials(setup.vk_proof.domainBits, setup.toxic.t);
|
||||||
|
for (let s=0; s<cir.nVars; s++) {
|
||||||
|
let at = PolF.F.zero;
|
||||||
|
for (let c in setup.vk_proof.polsA[s]) {
|
||||||
|
at = PolF.F.add(at, PolF.F.mul(u[c], setup.vk_proof.polsA[s][c]));
|
||||||
|
}
|
||||||
|
A2 = PolF.F.add(A2, PolF.F.mul(at, witness[s]));
|
||||||
|
|
||||||
|
let bt = PolF.F.zero;
|
||||||
|
for (let c in setup.vk_proof.polsB[s]) {
|
||||||
|
bt = PolF.F.add(bt, PolF.F.mul(u[c], setup.vk_proof.polsB[s][c]));
|
||||||
|
}
|
||||||
|
B2 = PolF.F.add(B2, PolF.F.mul(bt, witness[s]));
|
||||||
|
|
||||||
|
let ct = PolF.F.zero;
|
||||||
|
for (let c in setup.vk_proof.polsC[s]) {
|
||||||
|
ct = PolF.F.add(ct, PolF.F.mul(u[c], setup.vk_proof.polsC[s][c]));
|
||||||
|
}
|
||||||
|
C2 = PolF.F.add(C2, PolF.F.mul(ct, witness[s]));
|
||||||
|
}
|
||||||
|
|
||||||
|
A=PolF.F.affine(A);
|
||||||
|
B=PolF.F.affine(B);
|
||||||
|
C=PolF.F.affine(C);
|
||||||
|
A2=PolF.F.affine(A2);
|
||||||
|
B2=PolF.F.affine(B2);
|
||||||
|
C2=PolF.F.affine(C2);
|
||||||
|
|
||||||
|
assert(PolF.F.equals(C,C2));
|
||||||
|
assert(PolF.F.equals(B,B2));
|
||||||
|
assert(PolF.F.equals(A,A2));
|
||||||
|
const ABC = PolF.F.affine(PolF.F.sub(PolF.F.mul(A,B), C));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assert.equal(witness[cir.getSignalIdx("main.out")].toString(), "67");
|
||||||
|
|
||||||
|
const H = PolF.eval(proof.h, setup.toxic.t).affine();
|
||||||
|
|
||||||
|
const Z = PolF.F.sub(PolF.F.exp(setup.toxic.t, setup.vk_proof.domainSize), bigInt(1));
|
||||||
|
|
||||||
|
const HZ = PolF.F.affine(PolF.F.mul(H,Z));
|
||||||
|
assert(PolF.F.equals(ABC, HZ));
|
||||||
|
|
||||||
|
|
||||||
|
const gH = G1.affine(G1.mulScalar( G1.g, H));
|
||||||
|
const gZ = G2.affine(G2.mulScalar( G2.g, Z));
|
||||||
|
const gA = G1.affine(G1.mulScalar( G1.g, A));
|
||||||
|
const gB = G2.affine(G2.mulScalar( G2.g, B));
|
||||||
|
const gC = G1.affine(G1.mulScalar( G1.g, C));
|
||||||
|
|
||||||
|
assert(G1.equals(gH, proof.pi_h));
|
||||||
|
assert(G2.equals(gZ, setup.vk_verifier.vk_z));
|
||||||
|
assert(G2.equals(gB, proof.pi_b));
|
||||||
|
assert(G1.equals(gC, proof.pi_c));
|
||||||
|
// assert(G1.equals(gA, proof.pi_a));
|
||||||
|
*/
|
||||||
|
assert( zkSnark.isValid(setup.vk_verifier, proof, publicSignals));
|
||||||
|
}).timeout(10000000);
|
||||||
|
|
||||||
|
it("validate sha256_2", () => {
|
||||||
|
|
||||||
|
const cirDef = JSON.parse(fs.readFileSync(path.join(__dirname, "circuit", "sha256_2.json"), "utf8"));
|
||||||
|
const cir = new Circuit(cirDef);
|
||||||
|
|
||||||
|
console.log("Start setup: "+Date().toString());
|
||||||
|
const setup = zkSnark.setup(cir);
|
||||||
|
const strSetup = stringifyBigInts(setup);
|
||||||
|
fs.writeFileSync("vk_proof.json", JSON.stringify(strSetup.vk_proof), "utf-8");
|
||||||
|
fs.writeFileSync("vk_verifier.json", JSON.stringify(strSetup.vk_verifier), "utf-8");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
const setup = {};
|
const setup = {};
|
||||||
setup.vk_proof = unstringifyBigInts(JSON.parse(fs.readFileSync("vk_proof.json", "utf8")));
|
setup.vk_proof = unstringifyBigInts(JSON.parse(fs.readFileSync("vk_proof.json", "utf8")));
|
||||||
setup.vk_verifier = unstringifyBigInts(JSON.parse(fs.readFileSync("vk_verifier.json", "utf8")));
|
setup.vk_verifier = unstringifyBigInts(JSON.parse(fs.readFileSync("vk_verifier.json", "utf8")));
|
||||||
*/
|
*/
|
||||||
const witness = cir.calculateWitness({"a": "33", "b": "34"});
|
const witness = cir.calculateWitness({"a": "1", "b": "2"});
|
||||||
|
|
||||||
assert.equal(witness[cir.getSignalIdx("main.out")].toString(), "67");
|
// assert.equal(witness[cir.getSignalIdx("main.out")].toString(), "67");
|
||||||
|
|
||||||
|
console.log("Start calculating the proof: "+Date().toString());
|
||||||
const {proof, publicSignals} = zkSnark.genProof(setup.vk_proof, witness);
|
const {proof, publicSignals} = zkSnark.genProof(setup.vk_proof, witness);
|
||||||
|
|
||||||
|
console.log("Start verifiying: "+ Date().toString());
|
||||||
assert( zkSnark.isValid(setup.vk_verifier, proof, publicSignals));
|
assert( zkSnark.isValid(setup.vk_verifier, proof, publicSignals));
|
||||||
}).timeout(10000000);
|
}).timeout(10000000);
|
||||||
});
|
});
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user