arnaucube
arnaucube/snarkjsPublic Self-hosted repository
snarkjs/src/setup.js
src/setup.jsRaw
  1/*
  2    Copyright 2018 0kims association
  3
  4    This file is part of zksnark javascript library.
  5
  6    zksnark javascript library is free software: you can redistribute it and/or modify
  7    it under the terms of the GNU General Public License as published by
  8    the Free Software Foundation, either version 3 of the License, or
  9    (at your option) any later version.
 10
 11    zksnark javascript library is distributed in the hope that it will be useful,
 12    but WITHOUT ANY WARRANTY; without even the implied warranty of
 13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14    GNU General Public License for more details.
 15
 16    You should have received a copy of the GNU General Public License
 17    along with zksnark javascript library.  If not, see <https://www.gnu.org/licenses/>.
 18*/
 19
 20const bigInt = require("./bigint.js");
 21
 22const BN128 = require("./bn128.js");
 23const PolField = require("./polfield.js");
 24const ZqField = require("./zqfield.js");
 25const RatField = require("./ratfield.js");
 26
 27const bn128 = new BN128();
 28const G1 = bn128.G1;
 29const G2 = bn128.G2;
 30const PolF = new PolField(new ZqField(bn128.r));
 31const RatPolF = new PolField(new RatField(new ZqField(bn128.r)));
 32const F = new ZqField(bn128.r);
 33
 34module.exports = function setup(circuit) {
 35    const setup = {
 36        vk_proof : {
 37            nVars: circuit.nVars,
 38            nPublic: circuit.nPubInputs + circuit.nOutputs
 39        },
 40        vk_verifier: {
 41            nPublic: circuit.nPubInputs + circuit.nOutputs
 42        },
 43        toxic: {}
 44    };
 45
 46    calculatePolynomials(setup, circuit);
 47    setup.toxic.t = F.random();
 48    calculateEncriptedValuesAtT(setup, circuit);
 49    calculateHexps(setup, circuit);
 50
 51    return setup;
 52};
 53
 54function calculatePolynomials(setup, circuit) {
 55    // Calculate the points that must cross each polynomial
 56
 57    setup.toxic.aExtra = [];
 58    setup.toxic.bExtra = [];
 59    setup.toxic.cExtra = [];
 60    const aPoints = [];
 61    const bPoints = [];
 62    const cPoints = [];
 63    for (let s = 0; s<circuit.nVars; s++) {
 64        aPoints[s] = [];
 65        bPoints[s] = [];
 66        cPoints[s] = [];
 67        for (let c=0; c<circuit.nConstraints; c++) {
 68            aPoints[s].push([[bigInt(c), F.one], [circuit.a(c, s), F.one]]);
 69            bPoints[s].push([[bigInt(c), F.one], [circuit.b(c, s), F.one]]);
 70            cPoints[s].push([[bigInt(c), F.one], [circuit.c(c, s), F.one]]);
 71        }
 72        // Add an extra point to avoid constant polinolials.
 73        setup.toxic.aExtra[s] = F.random();
 74        setup.toxic.bExtra[s] = F.random();
 75        setup.toxic.cExtra[s] = F.random();
 76        aPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.aExtra[s], F.one]]);
 77        bPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.aExtra[s], F.one]]);
 78        cPoints[s].push([[bigInt(circuit.nConstraints), F.one], [setup.toxic.aExtra[s], F.one]]);
 79    }
 80
 81    // Calculate the polynomials using Lagrange
 82    setup.vk_proof.polsA = [];
 83    setup.vk_proof.polsB = [];
 84    setup.vk_proof.polsC = [];
 85    for (let s=0; s<circuit.nVars; s++) {
 86//        console.log(`Caclcualte Pol ${s}/${circuit.nVars}`);
 87        const pA = RatPolF.lagrange( aPoints[s] );
 88        const pB = RatPolF.lagrange( bPoints[s] );
 89        const pC = RatPolF.lagrange( cPoints[s] );
 90
 91        setup.vk_proof.polsA.push( unrat(pA) );
 92        setup.vk_proof.polsB.push( unrat(pB) );
 93        setup.vk_proof.polsC.push( unrat(pC) );
 94
 95    }
 96
 97    // Calculate Z polynomial
 98    // Z = 1
 99    setup.vk_proof.polZ = [bigInt(1)];
100    for (let c=0; c<circuit.nConstraints; c++) {
101        // Z = Z * (x - p_c)
102        setup.vk_proof.polZ = PolF.mul(
103            setup.vk_proof.polZ,
104            [F.neg(bigInt(c)), bigInt(1)] );
105    }
106}
107
108function calculateEncriptedValuesAtT(setup, circuit) {
109    setup.vk_proof.A = [];
110    setup.vk_proof.B = [];
111    setup.vk_proof.C = [];
112    setup.vk_proof.Ap = [];
113    setup.vk_proof.Bp = [];
114    setup.vk_proof.Cp = [];
115    setup.vk_proof.Kp = [];
116    setup.vk_verifier.A = [];
117
118    setup.toxic.ka = F.random();
119    setup.toxic.kb = F.random();
120    setup.toxic.kc = F.random();
121    setup.toxic.kbeta = F.random();
122    setup.toxic.kgamma = F.random();
123
124    const gb = F.mul(setup.toxic.kbeta, setup.toxic.kgamma);
125
126    setup.vk_verifier.vk_a = G2.affine(G2.mulScalar( G2.g, setup.toxic.ka));
127    setup.vk_verifier.vk_b = G1.affine(G1.mulScalar( G1.g, setup.toxic.kb));
128    setup.vk_verifier.vk_c = G2.affine(G2.mulScalar( G2.g, setup.toxic.kc));
129    setup.vk_verifier.vk_gb_1 = G1.affine(G1.mulScalar( G1.g, gb));
130    setup.vk_verifier.vk_gb_2 = G2.affine(G2.mulScalar( G2.g, gb));
131    setup.vk_verifier.vk_g = G2.affine(G2.mulScalar( G2.g, setup.toxic.kgamma));
132
133    for (let s=0; s<circuit.nVars; s++) {
134
135        // A[i] = G1 * polA(t)
136        const at = F.affine(PolF.eval(setup.vk_proof.polsA[s], setup.toxic.t));
137        const A = G1.affine(G1.mulScalar(G1.g, at));
138
139        setup.vk_proof.A.push(A);
140
141        if (s <= setup.vk_proof.nPublic) {
142            setup.vk_verifier.A.push(A);
143        }
144
145
146        // B1[i] = G1 * polB(t)
147        const bt = F.affine(PolF.eval(setup.vk_proof.polsB[s], setup.toxic.t));
148        const B1 = G1.affine(G1.mulScalar(G1.g, bt));
149
150        // B2[i] = G2 * polB(t)
151        const B2 = G2.affine(G2.mulScalar(G2.g, bt));
152
153        setup.vk_proof.B.push(B2);
154
155        // C[i] = G1 * polC(t)
156        const ct = F.affine(PolF.eval(setup.vk_proof.polsC[s], setup.toxic.t));
157        const C = G1.affine(G1.mulScalar( G1.g, ct));
158        setup.vk_proof.C.push (C);
159
160        // K = G1 * (A+B+C)
161
162        const kt = F.affine(F.add(F.add(at, bt), ct));
163        const K = G1.affine(G1.mulScalar( G1.g, kt));
164
165
166
167        const Ktest = G1.affine(G1.add(G1.add(A, B1), C));
168
169        if (!G1.equals(K, Ktest)) {
170            console.log ("=====FAIL======");
171        }
172
173
174
175        setup.vk_proof.Ap.push(G1.affine(G1.mulScalar(A, setup.toxic.ka)));
176        setup.vk_proof.Bp.push(G1.affine(G1.mulScalar(B1, setup.toxic.kb)));
177        setup.vk_proof.Cp.push(G1.affine(G1.mulScalar(C, setup.toxic.kc)));
178        setup.vk_proof.Kp.push(G1.affine(G1.mulScalar(K, setup.toxic.kbeta)));
179    }
180
181    setup.vk_verifier.vk_z = G2.affine(G2.mulScalar(
182        G2.g,
183        PolF.eval(setup.vk_proof.polZ, setup.toxic.t)));
184}
185
186function calculateHexps(setup, circuit) {
187    let maxA = 0;
188    let maxB = 0;
189    let maxC = 0;
190    for (let s=0; s<circuit.nVars; s++) {
191        maxA = Math.max(maxA, setup.vk_proof.polsA[s].length);
192        maxB = Math.max(maxB, setup.vk_proof.polsB[s].length);
193        maxC = Math.max(maxC, setup.vk_proof.polsC[s].length);
194    }
195
196    let maxFull = Math.max(maxA * maxB - 1, maxC);
197
198    const maxH = maxFull - setup.vk_proof.polZ.length + 1;
199
200    setup.vk_proof.hExps = new Array(maxH);
201    setup.vk_proof.hExps[0] = G1.g;
202    let eT = setup.toxic.t;
203    for (let i=1; i<maxH; i++) {
204        setup.vk_proof.hExps[i] = G1.affine(G1.mulScalar(G1.g, eT));
205        eT = F.mul(eT, setup.toxic.t);
206    }
207}
208
209function unrat(p) {
210    const res = new Array(p.length);
211    for (let i=0; i<p.length; i++) {
212        res[i] = RatPolF.F.toF(p[i]);
213    }
214    return res;
215}
216