plonk prover random numbers works

This commit is contained in:
Jordi Baylina 2021-05-24 07:17:07 +02:00
parent 7ed350002d
commit 1e89672bec
No known key found for this signature in database
GPG Key ID: 7480C80C1BE43112
6 changed files with 353 additions and 252 deletions

@ -63,10 +63,9 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
await calculateAdditions();
let A,B,C,Z;
let A4, B4, C4, Z4;
let pol_a,pol_b,pol_c, pol_z, pol_t, pol_r;
let proof = {};
if (logger) logger.debug("Reading L Points");
const lagrangeBases = await binFileUtils.readSection(fdZKey, sectionsZKey, 14);
const sigmaBuff = new BigBuffer(zkey.domainSize*n8r*4*3);
let o = sectionsZKey[12][0].p + zkey.domainSize*n8r;
@ -82,12 +81,10 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
const pol_s2 = new BigBuffer(zkey.domainSize*n8r);
await fdZKey.readToBuffer(pol_s2, 0 , zkey.domainSize*n8r, sectionsZKey[12][0].p + 5*zkey.domainSize*n8r);
const PTau = await binFileUtils.readSection(fdZKey, sectionsZKey, 15);
const PTau = await binFileUtils.readSection(fdZKey, sectionsZKey, 14);
let alpha, beta, gamma, xi;
let xim;
const b=[];
const ch = {};
await round1();
await round2();
@ -112,14 +109,14 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
publicSignals.push(Scalar.fromRprLE(pub));
}
proof.A = G1.toObject(G1.toAffine(proof.A));
proof.B = G1.toObject(G1.toAffine(proof.B));
proof.C = G1.toObject(G1.toAffine(proof.C));
proof.Z = G1.toObject(G1.toAffine(proof.Z));
proof.A = G1.toObject(proof.A);
proof.B = G1.toObject(proof.B);
proof.C = G1.toObject(proof.C);
proof.Z = G1.toObject(proof.Z);
proof.T1 = G1.toObject(G1.toAffine(proof.T1));
proof.T2 = G1.toObject(G1.toAffine(proof.T2));
proof.T3 = G1.toObject(G1.toAffine(proof.T3));
proof.T1 = G1.toObject(proof.T1);
proof.T2 = G1.toObject(proof.T2);
proof.T3 = G1.toObject(proof.T3);
proof.eval_a = Fr.toObject(proof.eval_a);
proof.eval_b = Fr.toObject(proof.eval_b);
@ -130,8 +127,8 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
proof.eval_t = Fr.toObject(proof.eval_t);
proof.eval_r = Fr.toObject(proof.eval_r);
proof.Wxi = G1.toObject(G1.toAffine(proof.Wxi));
proof.Wxiw = G1.toObject(G1.toAffine(proof.Wxiw));
proof.Wxi = G1.toObject(proof.Wxi);
proof.Wxiw = G1.toObject(proof.Wxiw);
proof = stringifyBigInts(proof);
publicSignals = stringifyBigInts(publicSignals);
@ -161,9 +158,9 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
}
async function buildABC() {
const A = new BigBuffer(zkey.domainSize * n8r);
const B = new BigBuffer(zkey.domainSize * n8r);
const C = new BigBuffer(zkey.domainSize * n8r);
let A = new BigBuffer(zkey.domainSize * n8r);
let B = new BigBuffer(zkey.domainSize * n8r);
let C = new BigBuffer(zkey.domainSize * n8r);
const aMap = await binFileUtils.readSection(fdZKey, sectionsZKey, 4);
const bMap = await binFileUtils.readSection(fdZKey, sectionsZKey, 5);
@ -178,6 +175,10 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
C.set(getWitness(iC), i*n8r);
}
A = await Fr.batchToMontgomery(A);
B = await Fr.batchToMontgomery(B);
C = await Fr.batchToMontgomery(C);
return [A,B,C];
}
@ -198,32 +199,21 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
}
async function round1() {
ch.b = [];
for (let i=1; i<=9; i++) {
b[i] = curve.Fr.random();
b[i] = curve.Fr.e(i);
// b[i] = curve.Fr.zero;
ch.b[i] = curve.Fr.random();
}
[A, B, C] = await buildABC();
proof.A = await curve.G1.multiExpAffine(lagrangeBases, A, logger, "multiexp A");
proof.B = await curve.G1.multiExpAffine(lagrangeBases, B, logger, "multiexp B");
proof.C = await curve.G1.multiExpAffine(lagrangeBases, C, logger, "multiexp C");
[pol_a, A4] = await to4T(A, [ch.b[2], ch.b[1]]);
[pol_b, B4] = await to4T(B, [ch.b[4], ch.b[3]]);
[pol_c, C4] = await to4T(C, [ch.b[6], ch.b[5]]);
proof.A = G1.add(proof.A, G1.timesFr(zkey.XtoMplus1, b[1]));
proof.A = G1.sub(proof.A, G1.timesFr(zkey.X, b[1]));
proof.A = G1.add(proof.A, G1.timesFr(zkey.XtoM, b[2]));
proof.A = G1.sub(proof.A, G1.timesFr(G1.one, b[2]));
proof.B = G1.add(proof.B, G1.timesFr(zkey.XtoMplus1, b[3]));
proof.B = G1.sub(proof.B, G1.timesFr(zkey.X, b[3]));
proof.B = G1.add(proof.B, G1.timesFr(zkey.XtoM, b[4]));
proof.B = G1.sub(proof.B, G1.timesFr(G1.one, b[4]));
proof.C = G1.add(proof.C, G1.timesFr(zkey.XtoMplus1, b[5]));
proof.C = G1.sub(proof.C, G1.timesFr(zkey.X, b[5]));
proof.C = G1.add(proof.C, G1.timesFr(zkey.XtoM, b[6]));
proof.C = G1.sub(proof.C, G1.timesFr(G1.one, b[6]));
proof.A = await expTau(pol_a, "multiexp A");
proof.B = await expTau(pol_b, "multiexp B");
proof.C = await expTau(pol_c, "multiexp C");
}
async function round2() {
@ -233,17 +223,13 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
G1.toRprUncompressed(transcript1, G1.F.n8*2, proof.B);
G1.toRprUncompressed(transcript1, G1.F.n8*4, proof.C);
beta = hashToFr(transcript1);
if (logger) logger.debug("beta: " + Fr.toString(beta));
ch.beta = hashToFr(transcript1);
if (logger) logger.debug("beta: " + Fr.toString(ch.beta));
const transcript2 = new Uint8Array(n8r);
Fr.toRprBE(transcript2, 0, beta);
gamma = hashToFr(transcript2);
if (logger) logger.debug("gamma: " + Fr.toString(gamma));
A = await Fr.batchToMontgomery(A);
B = await Fr.batchToMontgomery(B);
C = await Fr.batchToMontgomery(C);
Fr.toRprBE(transcript2, 0, ch.beta);
ch.gamma = hashToFr(transcript2);
if (logger) logger.debug("gamma: " + Fr.toString(ch.gamma));
let numArr = new BigBuffer(Fr.n8*zkey.domainSize);
let denArr = new BigBuffer(Fr.n8*zkey.domainSize);
@ -254,30 +240,30 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
let w = Fr.one;
for (let i=0; i<zkey.domainSize; i++) {
let n1 = A.slice(i*n8r, (i+1)*n8r);
n1 = Fr.add( n1, Fr.mul(beta, w) );
n1 = Fr.add( n1, gamma );
n1 = Fr.add( n1, Fr.mul(ch.beta, w) );
n1 = Fr.add( n1, ch.gamma );
let n2 = B.slice(i*n8r, (i+1)*n8r);
n2 = Fr.add( n2, Fr.mul(zkey.k1, Fr.mul(beta, w) ));
n2 = Fr.add( n2, gamma );
n2 = Fr.add( n2, Fr.mul(zkey.k1, Fr.mul(ch.beta, w) ));
n2 = Fr.add( n2, ch.gamma );
let n3 = C.slice(i*n8r, (i+1)*n8r);
n3 = Fr.add( n3, Fr.mul(zkey.k2, Fr.mul(beta, w) ));
n3 = Fr.add( n3, gamma );
n3 = Fr.add( n3, Fr.mul(zkey.k2, Fr.mul(ch.beta, w) ));
n3 = Fr.add( n3, ch.gamma );
const num = Fr.mul(n1, Fr.mul(n2, n3));
let d1 = A.slice(i*n8r, (i+1)*n8r);
d1 = Fr.add(d1, Fr.mul( sigmaBuff.slice(i*n8r*4, i*n8r*4 + n8r) , beta));
d1 = Fr.add(d1, gamma);
d1 = Fr.add(d1, Fr.mul( sigmaBuff.slice(i*n8r*4, i*n8r*4 + n8r) , ch.beta));
d1 = Fr.add(d1, ch.gamma);
let d2 = B.slice(i*n8r, (i+1)*n8r);
d2 = Fr.add(d2, Fr.mul( sigmaBuff.slice((zkey.domainSize + i)*4*n8r, (zkey.domainSize + i)*4*n8r+n8r) , beta));
d2 = Fr.add(d2, gamma);
d2 = Fr.add(d2, Fr.mul( sigmaBuff.slice((zkey.domainSize + i)*4*n8r, (zkey.domainSize + i)*4*n8r+n8r) , ch.beta));
d2 = Fr.add(d2, ch.gamma);
let d3 = C.slice(i*n8r, (i+1)*n8r);
d3 = Fr.add(d3, Fr.mul( sigmaBuff.slice((zkey.domainSize*2 + i)*4*n8r, (zkey.domainSize*2 + i)*4*n8r + n8r) , beta));
d3 = Fr.add(d3, gamma);
d3 = Fr.add(d3, Fr.mul( sigmaBuff.slice((zkey.domainSize*2 + i)*4*n8r, (zkey.domainSize*2 + i)*4*n8r + n8r) , ch.beta));
d3 = Fr.add(d3, ch.gamma);
const den = Fr.mul(d1, Fr.mul(d2, d3));
@ -311,27 +297,23 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
throw new Error("Copy constraints does not match");
}
Z = numArr.slice(0, zkey.domainSize*n8r);
numArr = await Fr.batchFromMontgomery(numArr);
Z = numArr;
proof.Z = await curve.G1.multiExpAffine(lagrangeBases, numArr, logger, "multiexp Z");
[pol_z, Z4] = await to4T(Z, [ch.b[9], ch.b[8], ch.b[7]]);
proof.Z = G1.add(proof.Z, G1.timesFr(zkey.XtoMplus2, b[7]));
proof.Z = G1.sub(proof.Z, G1.timesFr(zkey.Xto2, b[7]));
proof.Z = G1.add(proof.Z, G1.timesFr(zkey.XtoMplus1, b[8]));
proof.Z = G1.sub(proof.Z, G1.timesFr(zkey.X, b[8]));
proof.Z = G1.add(proof.Z, G1.timesFr(zkey.XtoM, b[9]));
proof.Z = G1.sub(proof.Z, G1.timesFr(G1.one, b[9]));
proof.Z = await expTau( pol_z, "multiexp Z");
}
async function round3() {
/*
async function checkDegree(P) {
const p = await curve.Fr.ifft(P);
let deg = (P.byteLength/n8r)-1;
while ((deg>0)&&(Fr.isZero(p.slice(deg*n8r, deg*n8r+n8r)))) deg--;
return deg;
}
*/
function printPol(P) {
const n=(P.byteLength/n8r);
@ -362,14 +344,31 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
const transcript3 = new Uint8Array(G1.F.n8*2);
G1.toRprUncompressed(transcript3, 0, proof.Z);
alpha = hashToFr(transcript3);
ch.alpha = hashToFr(transcript3);
if (logger) logger.debug("alpha: " + Fr.toString(alpha));
if (logger) logger.debug("alpha: " + Fr.toString(ch.alpha));
let A4; [pol_a, A4] = await to4T(A);
let B4; [pol_b, B4] = await to4T(B);
let C4; [pol_c, C4] = await to4T(C);
let Z4; [pol_z, Z4] = await to4T(Z);
const Z1 = [
Fr.zero,
Fr.add(Fr.e(-1), Fr.w[2]),
Fr.e(-2),
Fr.sub(Fr.e(-1), Fr.w[2]),
];
const Z2 = [
Fr.zero,
Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])),
Fr.e(4),
Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])),
];
const Z3 = [
Fr.zero,
Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])),
Fr.e(-8),
Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])),
];
/*
const Zw = new BigBuffer(zkey.domainSize*4*n8r);
@ -385,6 +384,7 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
console.log("degZw: " + degZw);
*/
const T = new BigBuffer(zkey.domainSize*4*n8r);
const Tz = new BigBuffer(zkey.domainSize*4*n8r);
let w = Fr.one;
for (let i=0; i<zkey.domainSize*4; i++) {
@ -401,6 +401,14 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
const s1 = sigmaBuff.slice(i*n8r, i*n8r+n8r);
const s2 = sigmaBuff.slice((i+zkey.domainSize*4)*n8r, (i+zkey.domainSize*4)*n8r+n8r);
const s3 = sigmaBuff.slice((i+zkey.domainSize*8)*n8r, (i+zkey.domainSize*8)*n8r+n8r);
const ap = Fr.add(ch.b[2], Fr.mul(ch.b[1], w));
const bp = Fr.add(ch.b[4], Fr.mul(ch.b[3], w));
const cp = Fr.add(ch.b[6], Fr.mul(ch.b[5], w));
const w2 = Fr.square(w);
const zp = Fr.add(Fr.add(Fr.mul(ch.b[7], w2), Fr.mul(ch.b[8], w)), ch.b[9]);
const wW = Fr.mul(w, Fr.w[zkey.power]);
const wW2 = Fr.square(wW);
const zWp = Fr.add(Fr.add(Fr.mul(ch.b[7], wW2), Fr.mul(ch.b[8], wW)), ch.b[9]);
let pl = Fr.zero;
for (let j=0; j<zkey.nPublic; j++) {
@ -410,53 +418,71 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
));
}
let e1 = Fr.mul(Fr.mul(a, b), qm);
let [e1, e1z] = mul2(a, b, ap, bp, i%4);
e1 = Fr.mul(e1, qm);
e1z = Fr.mul(e1z, qm);
e1 = Fr.add(e1, Fr.mul(a, ql));
e1z = Fr.add(e1z, Fr.mul(ap, ql));
e1 = Fr.add(e1, Fr.mul(b, qr));
e1z = Fr.add(e1z, Fr.mul(bp, qr));
e1 = Fr.add(e1, Fr.mul(c, qo));
e1z = Fr.add(e1z, Fr.mul(cp, qo));
e1 = Fr.add(e1, pl);
e1 = Fr.add(e1, qc);
const betaw = Fr.mul(beta, w);
const betaw = Fr.mul(ch.beta, w);
let e2a =a;
e2a = Fr.add(e2a, betaw);
e2a = Fr.add(e2a, gamma);
e2a = Fr.add(e2a, ch.gamma);
let e2b =b;
e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1));
e2b = Fr.add(e2b, gamma);
e2b = Fr.add(e2b, ch.gamma);
let e2c =c;
e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2));
e2c = Fr.add(e2c, gamma);
e2c = Fr.add(e2c, ch.gamma);
let e2 = Fr.mul(Fr.mul(e2a, e2b), e2c);
e2 = Fr.mul(e2, z);
e2 = Fr.mul(e2, alpha);
let e2d = z;
let [e2, e2z] = mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i%4);
e2 = Fr.mul(e2, ch.alpha);
e2z = Fr.mul(e2z, ch.alpha);
let e3a = a;
e3a = Fr.add(e3a, Fr.mul(beta, s1));
e3a = Fr.add(e3a, gamma);
e3a = Fr.add(e3a, Fr.mul(ch.beta, s1));
e3a = Fr.add(e3a, ch.gamma);
let e3b = b;
e3b = Fr.add(e3b, Fr.mul(beta,s2));
e3b = Fr.add(e3b, gamma);
e3b = Fr.add(e3b, Fr.mul(ch.beta,s2));
e3b = Fr.add(e3b, ch.gamma);
let e3c = c;
e3c = Fr.add(e3c, Fr.mul(beta,s3));
e3c = Fr.add(e3c, gamma);
e3c = Fr.add(e3c, Fr.mul(ch.beta,s3));
e3c = Fr.add(e3c, ch.gamma);
let e3 = Fr.mul(Fr.mul(e3a, e3b), e3c);
e3 = Fr.mul(e3, zw);
e3 = Fr.mul(e3, alpha);
let e3d = zw;
let [e3, e3z] = mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i%4);
e3 = Fr.mul(e3, ch.alpha);
e3z = Fr.mul(e3z, ch.alpha);
let e4 = Fr.sub(z, Fr.one);
e4 = Fr.mul(e4, lPols.slice( (zkey.domainSize + i)*n8r, (zkey.domainSize+i+1)*n8r));
e4 = Fr.mul(e4, Fr.mul(alpha, alpha));
e4 = Fr.mul(e4, Fr.mul(ch.alpha, ch.alpha));
let e4z = Fr.mul(zp, lPols.slice( (zkey.domainSize + i)*n8r, (zkey.domainSize+i+1)*n8r));
e4z = Fr.mul(e4z, Fr.mul(ch.alpha, ch.alpha));
let e = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4);
let ez = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z);
T.set(e, i*n8r);
Tz.set(ez, i*n8r);
w = Fr.mul(w, Fr.w[zkey.power+2]);
}
@ -482,21 +508,97 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
}
}
pol_t = t.slice(0, (zkey.domainSize*3)*n8r);
const tz = await Fr.ifft(Tz);
printPol(tz);
for (let i=0; i<zkey.domainSize*4; i++) {
const a = tz.slice(i*n8r, (i+1)*n8r);
if (i > (zkey.domainSize*3 +5) ) {
if (!Fr.isZero(a)) {
throw new Error("Tz Polynomial is not well calculated");
}
} else {
t.set(
Fr.add(
t.slice(i*n8r, (i+1)*n8r),
a
),
i*n8r
);
}
}
t = await Fr.batchFromMontgomery(t);
pol_t = t.slice(0, (zkey.domainSize*3+6)*n8r);
proof.T1 = await curve.G1.multiExpAffine(PTau, t.slice(0, zkey.domainSize*n8r), logger, "multiexp T1");
proof.T2 = await curve.G1.multiExpAffine(PTau, t.slice(zkey.domainSize*n8r, zkey.domainSize*2*n8r), logger, "multiexp T2");
proof.T3 = await curve.G1.multiExpAffine(PTau, t.slice(zkey.domainSize*2*n8r, (zkey.domainSize*3)*n8r), logger, "multiexp T3");
proof.T1 = await expTau( t.slice(0, zkey.domainSize*n8r) , "multiexp T1");
proof.T2 = await expTau( t.slice(zkey.domainSize*n8r, zkey.domainSize*2*n8r) , "multiexp T2");
proof.T3 = await expTau( t.slice(zkey.domainSize*2*n8r, (zkey.domainSize*3+6)*n8r) , "multiexp T3");
function mul2(a,b, ap, bp, p) {
let r, rz;
async function to4T(A) {
const a = await Fr.ifft(A);
const a4 = new BigBuffer(n8r*zkey.domainSize*4);
a4.set(a, 0);
const A4 = await Fr.fft(a4);
return [a, A4];
const a_b = Fr.mul(a,b);
const a_bp = Fr.mul(a,bp);
const ap_b = Fr.mul(ap,b);
const ap_bp = Fr.mul(ap,bp);
r = a_b;
let a0 = Fr.add(a_bp, ap_b);
let a1 = ap_bp;
rz = a0;
if (p) {
rz = Fr.add(rz, Fr.mul(Z1[p], a1));
}
return [r, rz];
}
function mul4(a,b,c,d, ap, bp, cp, dp, p) {
let r, rz;
const a_b = Fr.mul(a,b);
const a_bp = Fr.mul(a,bp);
const ap_b = Fr.mul(ap,b);
const ap_bp = Fr.mul(ap,bp);
const c_d = Fr.mul(c,d);
const c_dp = Fr.mul(c,dp);
const cp_d = Fr.mul(cp,d);
const cp_dp = Fr.mul(cp,dp);
r = Fr.mul(a_b, c_d);
let a0 = Fr.mul(ap_b, c_d);
a0 = Fr.add(a0, Fr.mul(a_bp, c_d));
a0 = Fr.add(a0, Fr.mul(a_b, cp_d));
a0 = Fr.add(a0, Fr.mul(a_b, c_dp));
let a1 = Fr.mul(ap_bp, c_d);
a1 = Fr.add(a1, Fr.mul(ap_b, cp_d));
a1 = Fr.add(a1, Fr.mul(ap_b, c_dp));
a1 = Fr.add(a1, Fr.mul(a_bp, cp_d));
a1 = Fr.add(a1, Fr.mul(a_bp, c_dp));
a1 = Fr.add(a1, Fr.mul(a_b, cp_dp));
let a2 = Fr.mul(a_bp, cp_dp);
a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp));
a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp));
a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d));
let a3 = Fr.mul(ap_bp, cp_dp);
rz = a0;
if (p) {
rz = Fr.add(rz, Fr.mul(Z1[p], a1));
rz = Fr.add(rz, Fr.mul(Z2[p], a2));
rz = Fr.add(rz, Fr.mul(Z3[p], a3));
}
return [r, rz];
}
}
@ -523,74 +625,76 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
G1.toRprUncompressed(transcript4, 0, proof.T1);
G1.toRprUncompressed(transcript4, G1.F.n8*2, proof.T2);
G1.toRprUncompressed(transcript4, G1.F.n8*4, proof.T3);
xi = hashToFr(transcript4);
ch.xi = hashToFr(transcript4);
if (logger) logger.debug("xi: " + Fr.toString(xi));
if (logger) logger.debug("xi: " + Fr.toString(ch.xi));
proof.eval_a = evalPol(pol_a, xi);
proof.eval_b = evalPol(pol_b, xi);
proof.eval_c = evalPol(pol_c, xi);
proof.eval_s1 = evalPol(pol_s1, xi);
proof.eval_s2 = evalPol(pol_s2, xi);
proof.eval_t = evalPol(pol_t, xi);
proof.eval_zw = evalPol(pol_z, Fr.mul(xi, Fr.w[zkey.power]));
proof.eval_a = evalPol(pol_a, ch.xi);
proof.eval_b = evalPol(pol_b, ch.xi);
proof.eval_c = evalPol(pol_c, ch.xi);
proof.eval_s1 = evalPol(pol_s1, ch.xi);
proof.eval_s2 = evalPol(pol_s2, ch.xi);
proof.eval_t = evalPol(pol_t, ch.xi);
proof.eval_zw = evalPol(pol_z, Fr.mul(ch.xi, Fr.w[zkey.power]));
const coef_ab = Fr.mul(proof.eval_a, proof.eval_b);
let e2a = proof.eval_a;
const betaxi = Fr.mul(beta, xi);
const betaxi = Fr.mul(ch.beta, ch.xi);
e2a = Fr.add( e2a, betaxi);
e2a = Fr.add( e2a, gamma);
e2a = Fr.add( e2a, ch.gamma);
let e2b = proof.eval_b;
e2b = Fr.add( e2b, Fr.mul(betaxi, zkey.k1));
e2b = Fr.add( e2b, gamma);
e2b = Fr.add( e2b, ch.gamma);
let e2c = proof.eval_c;
e2c = Fr.add( e2c, Fr.mul(betaxi, zkey.k2));
e2c = Fr.add( e2c, gamma);
e2c = Fr.add( e2c, ch.gamma);
const e2 = Fr.mul(Fr.mul(Fr.mul(e2a, e2b), e2c), alpha);
const e2 = Fr.mul(Fr.mul(Fr.mul(e2a, e2b), e2c), ch.alpha);
let e3a = proof.eval_a;
e3a = Fr.add( e3a, Fr.mul(beta, proof.eval_s1));
e3a = Fr.add( e3a, gamma);
e3a = Fr.add( e3a, Fr.mul(ch.beta, proof.eval_s1));
e3a = Fr.add( e3a, ch.gamma);
let e3b = proof.eval_b;
e3b = Fr.add( e3b, Fr.mul(beta, proof.eval_s2));
e3b = Fr.add( e3b, gamma);
e3b = Fr.add( e3b, Fr.mul(ch.beta, proof.eval_s2));
e3b = Fr.add( e3b, ch.gamma);
let e3 = Fr.mul(e3a, e3b);
e3 = Fr.mul(e3, beta);
e3 = Fr.mul(e3, ch.beta);
e3 = Fr.mul(e3, proof.eval_zw);
e3 = Fr.mul(e3, alpha);
e3 = Fr.mul(e3, ch.alpha);
xim= xi;
for (let i=0; i<zkey.power; i++) xim = Fr.mul(xim, xim);
ch.xim= ch.xi;
for (let i=0; i<zkey.power; i++) ch.xim = Fr.mul(ch.xim, ch.xim);
const eval_l1 = Fr.div(
Fr.sub(xim, Fr.one),
Fr.mul(Fr.sub(xi, Fr.one), Fr.e(zkey.domainSize))
Fr.sub(ch.xim, Fr.one),
Fr.mul(Fr.sub(ch.xi, Fr.one), Fr.e(zkey.domainSize))
);
const e4 = Fr.mul(eval_l1, Fr.mul(alpha, alpha));
const e4 = Fr.mul(eval_l1, Fr.mul(ch.alpha, ch.alpha));
const coefs3 = e3;
const coefz = Fr.add(e2, e4);
pol_r = new BigBuffer(zkey.domainSize*n8r);
pol_r = new BigBuffer((zkey.domainSize+3)*n8r);
for (let i = 0; i<zkey.domainSize; i++) {
let v = Fr.mul(coef_ab, pol_qm.slice(i*n8r,(i+1)*n8r));
for (let i = 0; i<zkey.domainSize+3; i++) {
let v = Fr.mul(coefz, pol_z.slice(i*n8r,(i+1)*n8r));
if (i<zkey.domainSize) {
v = Fr.add(v, Fr.mul(coef_ab, pol_qm.slice(i*n8r,(i+1)*n8r)));
v = Fr.add(v, Fr.mul(proof.eval_a, pol_ql.slice(i*n8r,(i+1)*n8r)));
v = Fr.add(v, Fr.mul(proof.eval_b, pol_qr.slice(i*n8r,(i+1)*n8r)));
v = Fr.add(v, Fr.mul(proof.eval_c, pol_qo.slice(i*n8r,(i+1)*n8r)));
v = Fr.add(v, pol_qc.slice(i*n8r,(i+1)*n8r));
v = Fr.add(v, Fr.mul(coefz, pol_z.slice(i*n8r,(i+1)*n8r)));
v = Fr.sub(v, Fr.mul(coefs3, pol_s3.slice(i*n8r,(i+1)*n8r)));
}
pol_r.set(v, i*n8r);
}
proof.eval_r = evalPol(pol_r, xi);
proof.eval_r = evalPol(pol_r, ch.xi);
}
async function round5() {
@ -603,55 +707,56 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
Fr.toRprBE(transcript5, n8r*5, proof.eval_zw);
Fr.toRprBE(transcript5, n8r*6, proof.eval_t);
Fr.toRprBE(transcript5, n8r*7, proof.eval_r);
const v = [];
v[1] = hashToFr(transcript5);
if (logger) logger.debug("v: " + Fr.toString(v[1]));
ch.v = [];
ch.v[1] = hashToFr(transcript5);
if (logger) logger.debug("v: " + Fr.toString(ch.v[1]));
for (let i=2; i<=6; i++ ) v[i] = Fr.mul(v[i-1], v[1]);
for (let i=2; i<=6; i++ ) ch.v[i] = Fr.mul(ch.v[i-1], ch.v[1]);
// TODO DELETE
// v[1] = Fr.zero;
// v[2] = Fr.zero;
// v[3] = Fr.zero;
// v[4] = Fr.zero;
// v[5] = Fr.zero;
// v[6] = Fr.zero;
let pol_wxi = new BigBuffer((zkey.domainSize+6)*n8r);
let pol_wxi = new BigBuffer(zkey.domainSize*n8r);
const xi2m = Fr.mul(ch.xim, ch.xim);
const xi2m = Fr.mul(xim, xim);
for (let i=0; i<zkey.domainSize; i++) {
for (let i=0; i<zkey.domainSize+6; i++) {
let w = Fr.zero;
w = Fr.add(w, pol_t.slice(i*n8r, (i+1)*n8r));
w = Fr.add(w, Fr.mul(xim, pol_t.slice( (zkey.domainSize+i)*n8r, (zkey.domainSize+i+1)*n8r )));
w = Fr.add(w, Fr.mul(xi2m, pol_t.slice( (zkey.domainSize*2+i)*n8r, (zkey.domainSize*2+i+1)*n8r )));
w = Fr.add(w, Fr.mul(v[1], pol_r.slice(i*n8r, (i+1)*n8r)));
w = Fr.add(w, Fr.mul(v[2], pol_a.slice(i*n8r, (i+1)*n8r)));
w = Fr.add(w, Fr.mul(v[3], pol_b.slice(i*n8r, (i+1)*n8r)));
w = Fr.add(w, Fr.mul(v[4], pol_c.slice(i*n8r, (i+1)*n8r)));
w = Fr.add(w, Fr.mul(v[5], pol_s1.slice(i*n8r, (i+1)*n8r)));
w = Fr.add(w, Fr.mul(v[6], pol_s2.slice(i*n8r, (i+1)*n8r)));
if (i<zkey.domainSize+3) {
w = Fr.add(w, Fr.mul(ch.v[1], pol_r.slice(i*n8r, (i+1)*n8r)));
}
if (i<zkey.domainSize+2) {
w = Fr.add(w, Fr.mul(ch.v[2], pol_a.slice(i*n8r, (i+1)*n8r)));
w = Fr.add(w, Fr.mul(ch.v[3], pol_b.slice(i*n8r, (i+1)*n8r)));
w = Fr.add(w, Fr.mul(ch.v[4], pol_c.slice(i*n8r, (i+1)*n8r)));
}
if (i<zkey.domainSize) {
w = Fr.add(w, pol_t.slice(i*n8r, (i+1)*n8r));
w = Fr.add(w, Fr.mul(ch.xim, pol_t.slice( (zkey.domainSize+i)*n8r, (zkey.domainSize+i+1)*n8r )));
w = Fr.add(w, Fr.mul(ch.v[5], pol_s1.slice(i*n8r, (i+1)*n8r)));
w = Fr.add(w, Fr.mul(ch.v[6], pol_s2.slice(i*n8r, (i+1)*n8r)));
}
pol_wxi.set(w, i*n8r);
}
let w0 = pol_wxi.slice(0, n8r);
w0 = Fr.sub(w0, proof.eval_t);
w0 = Fr.sub(w0, Fr.mul(v[1], proof.eval_r));
w0 = Fr.sub(w0, Fr.mul(v[2], proof.eval_a));
w0 = Fr.sub(w0, Fr.mul(v[3], proof.eval_b));
w0 = Fr.sub(w0, Fr.mul(v[4], proof.eval_c));
w0 = Fr.sub(w0, Fr.mul(v[5], proof.eval_s1));
w0 = Fr.sub(w0, Fr.mul(v[6], proof.eval_s2));
w0 = Fr.sub(w0, Fr.mul(ch.v[1], proof.eval_r));
w0 = Fr.sub(w0, Fr.mul(ch.v[2], proof.eval_a));
w0 = Fr.sub(w0, Fr.mul(ch.v[3], proof.eval_b));
w0 = Fr.sub(w0, Fr.mul(ch.v[4], proof.eval_c));
w0 = Fr.sub(w0, Fr.mul(ch.v[5], proof.eval_s1));
w0 = Fr.sub(w0, Fr.mul(ch.v[6], proof.eval_s2));
pol_wxi.set(w0, 0);
pol_wxi= divPol1(pol_wxi, xi);
pol_wxi = await Fr.batchFromMontgomery(pol_wxi);
proof.Wxi = await curve.G1.multiExpAffine(PTau, pol_wxi, logger, "multiexp Wxi");
pol_wxi= divPol1(pol_wxi, ch.xi);
let pol_wxiw = new BigBuffer(zkey.domainSize*n8r);
for (let i=0; i<zkey.domainSize; i++) {
proof.Wxi = await expTau(pol_wxi, "multiexp Wxi");
let pol_wxiw = new BigBuffer((zkey.domainSize+3)*n8r);
for (let i=0; i<zkey.domainSize+3; i++) {
const w = pol_z.slice(i*n8r, (i+1)*n8r);
pol_wxiw.set(w, i*n8r);
}
@ -659,11 +764,8 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
w0 = Fr.sub(w0, proof.eval_zw);
pol_wxiw.set(w0, 0);
pol_wxiw= divPol1(pol_wxiw, Fr.mul(xi, Fr.w[zkey.power]));
pol_wxiw = await Fr.batchFromMontgomery(pol_wxiw);
proof.Wxiw = await curve.G1.multiExpAffine(PTau, pol_wxiw, logger, "multiexp Wxiw");
pol_wxiw= divPol1(pol_wxiw, Fr.mul(ch.xi, Fr.w[zkey.power]));
proof.Wxiw = await expTau(pol_wxiw, "multiexp Wxiw");
}
function hashToFr(transcript) {
@ -710,6 +812,46 @@ export default async function plonk16Prove(zkeyFileName, witnessFileName, logger
}
return res;
}
async function expTau(b, name) {
const n = b.byteLength/n8r;
const PTauN = PTau.slice(0, n*curve.G1.F.n8*2);
const bm = await curve.Fr.batchFromMontgomery(b);
let res = await curve.G1.multiExpAffine(PTauN, bm, logger, name);
res = curve.G1.toAffine(res);
return res;
}
async function to4T(A, pz) {
pz = pz || [];
let a = await Fr.ifft(A);
const a4 = new BigBuffer(n8r*zkey.domainSize*4);
a4.set(a, 0);
const a1 = new BigBuffer(n8r*(zkey.domainSize + pz.length));
a1.set(a, 0);
for (let i= 0; i<pz.length; i++) {
a1.set(
Fr.add(
a1.slice((zkey.domainSize+i)*n8r, (zkey.domainSize+i+1)*n8r),
pz[i]
),
(zkey.domainSize+i)*n8r
);
a1.set(
Fr.sub(
a1.slice(i*n8r, (i+1)*n8r),
pz[i]
),
i*n8r
);
}
const A4 = await Fr.fft(a4);
return [a1, A4];
}
}

@ -104,18 +104,12 @@ export default async function plonkSetup(r1csName, ptauName, zkeyName, logger) {
await writeSigma(12, "sigma");
await writeLs(13, "lagrange polynomials");
// Write Lagrange Points Section
///////////
await startWriteSection(fdZKey, 14);
await fdZKey.write(LPoints);
await endWriteSection(fdZKey);
// Write PTau points
////////////
await startWriteSection(fdZKey, 15);
const buffOut = new BigBuffer(domainSize*sG1);
await fdPTau.readToBuffer(buffOut, 0, domainSize*sG1, sectionsPTau[2][0].p);
await startWriteSection(fdZKey, 14);
const buffOut = new BigBuffer((domainSize+6)*sG1);
await fdPTau.readToBuffer(buffOut, 0, (domainSize+6)*sG1, sectionsPTau[2][0].p);
await fdZKey.write(buffOut);
await endWriteSection(fdZKey);
@ -385,26 +379,6 @@ export default async function plonkSetup(r1csName, ptauName, zkeyName, logger) {
await fdZKey.write(k1);
await fdZKey.write(k2);
let bX;
bX = await fdPTau.read(sG1, sectionsPTau[2][0].p + sG1);
await fdZKey.write(bX);
let bX2;
bX2 = await fdPTau.read(sG1, sectionsPTau[2][0].p + sG1*2);
await fdZKey.write(bX2);
let bXtoM;
bXtoM = await fdPTau.read(sG1, sectionsPTau[2][0].p + sG1*domainSize);
await fdZKey.write(bXtoM);
let bXtoMplus1;
bXtoMplus1 = await fdPTau.read(sG1, sectionsPTau[2][0].p + sG1*(domainSize+1));
await fdZKey.write(bXtoMplus1);
let bXtoMplus2;
bXtoMplus2 = await fdPTau.read(sG1, sectionsPTau[2][0].p + sG1*(domainSize+2));
await fdZKey.write(bXtoMplus2);
await fdZKey.write(G1.toAffine(vk.Qm));
await fdZKey.write(G1.toAffine(vk.Ql));
await fdZKey.write(G1.toAffine(vk.Qr));

@ -208,15 +208,6 @@ function calculateChallanges(curve, proof) {
G1.toRprUncompressed(transcript6, G1.F.n8*2, proof.Wxiw);
res.u = hashToFr(curve, transcript6);
// TODO: remove
// res.v[1] = Fr.zero;
// res.v[2] = Fr.zero;
// res.v[3] = Fr.zero;
// res.v[4] = Fr.zero;
// res.v[5] = Fr.zero;
// res.v[6] = Fr.zero;
// res.u = Fr.zero;
return res;
}

@ -268,12 +268,6 @@ async function readHeaderPlonk(fd, sections, protocol, toObject) {
zkey.k1 = await fd.read(n8r);
zkey.k2 = await fd.read(n8r);
zkey.X = await readG1(fd, curve, toObject);
zkey.Xto2 = await readG1(fd, curve, toObject);
zkey.XtoM = await readG1(fd, curve, toObject);
zkey.XtoMplus1 = await readG1(fd, curve, toObject);
zkey.XtoMplus2 = await readG1(fd, curve, toObject);
zkey.Qm = await readG1(fd, curve, toObject);
zkey.Ql = await readG1(fd, curve, toObject);
zkey.Qr = await readG1(fd, curve, toObject);

Binary file not shown.

@ -1,55 +1,55 @@
{
"A": [
"15743209584538732831984522947865045943191698736126835167107429821444692635700",
"15304499734695470270217999401312954213615077608391938626547048969059391815770",
"8839447420316742728199672120007516770398996562499593209826233055164831459834",
"16189635412848654749378322490220441430077839960004046391626438625637726226000",
"1"
],
"B": [
"3011437941647082010337336879820112189520787585056958119182126144516922325699",
"14293021774310121677905381158509930628442641616993815871854561496752240048132",
"17465184056494179801925813691588125272949911271611543454528130157857909913246",
"869328347486379578626658936503731002520626692524913211521742050768236719305",
"1"
],
"C": [
"17023913191405186346489422835812580810015512803033000441904349097055703180515",
"11228876974248468319926028828930973923072635393190630092554386478523728646602",
"19519544555708553879767666138947412440629548042175907283737565586445507479903",
"17669026430269534969805497624294901955270334914625983358714826411609764475804",
"1"
],
"Z": [
"21787485149860139414155053903444419266452989172629957435807448984274998525743",
"2537376736563984101921166856341942675021784850064711527768725712244516210693",
"3346839295724370624732530222814040339873780027932771271059227118623825895313",
"10771064980375572846317420996468711290464809627547728487032820584132296464087",
"1"
],
"T1": [
"9982560943557310174756809994489647193274022193173772342571072376360853826159",
"2193374861650642053413940227444385900509799625539732490553578296834818806014",
"6168675305758589840782279635487697914964888136358086288899584897562377682341",
"1310251258624946189756801650980878849173726360620822836933820834682621444297",
"1"
],
"T2": [
"1935051902238074558682471125149626614935744241552612922092977226651069265819",
"15728245714470497509947599396234528395359156386509927514699449257668858437022",
"16452753478240443931891239628843197353427455171472174094729996434600044435135",
"8929495594150478290096744687495763476858314760863627578988262303134274489344",
"1"
],
"T3": [
"18565050802152066143639524874000298798967497331659460012952465075688981418065",
"18124252316135049195270348857308050282660839058495893905635826459440493046467",
"19819502442073307622314428521645368167900579868696060575639423061202619148825",
"1296256729870262422650485730805825715543370241968740278951378382748106685",
"1"
],
"eval_a": "18560625457154932877354134783576059795528977185011370741206750467310685514420",
"eval_b": "2968882576386486226736180104429680319564132166278962733938101279863400669397",
"eval_c": "14065677607789115870968882944412413440929947283607968973583982627560459103752",
"eval_s1": "17673322793248695230976965373575045530576580704252056363216368719625468122334",
"eval_s2": "831541334231628590558915969572942800627020663197326186193303197959043192699",
"eval_t": "8179926370148644196892921681282394306069033457557483827929857756544255424016",
"eval_zw": "7342206155372820933732681194284651788067168695182187676476085111006912772156",
"eval_r": "11261053049659093980937042550692833529286331232997878682705148472953954402090",
"eval_a": "17308412617343213496686623338374754645623487581648979513260734198232305768219",
"eval_b": "18345454810685357058582137490005137834611428833597017516916268835300742089352",
"eval_c": "16074233345199063790683870465201170590190471729874269213657192492651425327675",
"eval_s1": "14015572845284403142110641193521146039944984657769005309306690365631231445048",
"eval_s2": "7691129033989434863426855513508666093916526662958551024915431222123575206817",
"eval_t": "5852485600510874249119136745640279381547655754620311863376257247975117708663",
"eval_zw": "13923465555995912889009033724768828925333434248874337536329403180953424994345",
"eval_r": "1366062923125011032494175183956831254719864451259174775709441138581956258656",
"Wxi": [
"6125149678611859223282479698302269532216717966631378380250981750098717210374",
"13207465019087327267137821712205429411984497896597119936649478058261276282566",
"338371644772673995306261030076125401282839784249944929895162794096576157571",
"17341033938816793745315773504010937698365013917156300011885252183580989524581",
"1"
],
"Wxiw": [
"13714076431412195084554498803436795524319005402640663193692974043979445012470",
"4405441109329384737176946029242914012963938939164670332792981962524535185412",
"17454198881576966899691410005788764637613831450763965078826728621580498180724",
"5460326051028606573687415138444061925446401900718369209656673120203041901304",
"1"
],
"protocol": "plonk"