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 snarkjs.
  5
  6    snarkjs is a free software: you can redistribute it and/or
  7    modify it under the terms of the GNU General Public License as published by the
  8    Free Software Foundation, either version 3 of the License, or (at your option)
  9    any later version.
 10
 11    snarkjs is distributed in the hope that it will be useful,
 12    but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 13    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 14    more details.
 15
 16    You should have received a copy of the GNU General Public License along with
 17    snarkjs. 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");
 25
 26const bn128 = new BN128();
 27const G1 = bn128.G1;
 28const G2 = bn128.G2;
 29const PolF = new PolField(new ZqField(bn128.r));
 30const F = new ZqField(bn128.r);
 31
 32module.exports = function setup(circuit) {
 33    const setup = {
 34        vk_proof : {
 35            nVars: circuit.nVars,
 36            nPublic: circuit.nPubInputs + circuit.nOutputs
 37        },
 38        vk_verifier: {
 39            nPublic: circuit.nPubInputs + circuit.nOutputs
 40        },
 41        toxic: {}
 42    };
 43
 44
 45    setup.vk_proof.domainBits = PolF.log2(circuit.nConstraints + circuit.nPubInputs + circuit.nOutputs +1 -1) +1;
 46    setup.vk_proof.domainSize = 1 << setup.vk_proof.domainBits;
 47
 48    calculatePolinomials(setup, circuit);
 49    setup.toxic.t = F.random();
 50    calculateEncriptedValuesAtT(setup, circuit);
 51    calculateHexps(setup, circuit);
 52
 53    return setup;
 54};
 55
 56
 57function calculatePolinomials(setup, circuit) {
 58
 59    setup.vk_proof.polsA = new Array(circuit.nVars);
 60    setup.vk_proof.polsB = new Array(circuit.nVars);
 61    setup.vk_proof.polsC = new Array(circuit.nVars);
 62    for (let i=0; i<circuit.nVars; i++) {
 63        setup.vk_proof.polsA[i] = {};
 64        setup.vk_proof.polsB[i] = {};
 65        setup.vk_proof.polsC[i] = {};
 66    }
 67    for (let c=0; c<circuit.nConstraints; c++) {
 68
 69        for (let s in circuit.constraints[c][0]) {
 70            setup.vk_proof.polsA[s][c] = bigInt(circuit.constraints[c][0][s]);
 71        }
 72        for (let s in circuit.constraints[c][1]) {
 73            setup.vk_proof.polsB[s][c] = bigInt(circuit.constraints[c][1][s]);
 74        }
 75        for (let s in circuit.constraints[c][2]) {
 76            setup.vk_proof.polsC[s][c] = bigInt(circuit.constraints[c][2][s]);
 77        }
 78    }
 79
 80    /**
 81     * add and process the constraints
 82     *     input_i * 0 = 0
 83     * to ensure soundness of input consistency
 84     */
 85    for (let i = 0; i < circuit.nPubInputs + circuit.nOutputs + 1; ++i)
 86    {
 87        setup.vk_proof.polsA[i][circuit.nConstraints + i] = F.one;
 88    }
 89}
 90
 91function calculateValuesAtT(setup, circuit) {
 92    const z_t = PolF.computeVanishingPolinomial(setup.vk_proof.domainBits, setup.toxic.t);
 93    const u = PolF.evaluateLagrangePolynomials(setup.vk_proof.domainBits, setup.toxic.t);
 94
 95    const a_t = new Array(circuit.nVars).fill(F.zero);
 96    const b_t = new Array(circuit.nVars).fill(F.zero);
 97    const c_t = new Array(circuit.nVars).fill(F.zero);
 98
 99    // TODO: substitute setup.polsA for coeficients
100    for (let s=0; s<circuit.nVars; s++) {
101        for (let c in setup.vk_proof.polsA[s]) {
102            a_t[s] = F.add(a_t[s], F.mul(u[c], setup.vk_proof.polsA[s][c]));
103        }
104        for (let c in setup.vk_proof.polsB[s]) {
105            b_t[s] = F.add(b_t[s], F.mul(u[c], setup.vk_proof.polsB[s][c]));
106        }
107        for (let c in setup.vk_proof.polsC[s]) {
108            c_t[s] = F.add(c_t[s], F.mul(u[c], setup.vk_proof.polsC[s][c]));
109        }
110    }
111
112    return {a_t, b_t, c_t, z_t};
113
114}
115
116
117
118
119function calculateEncriptedValuesAtT(setup, circuit) {
120
121    const v = calculateValuesAtT(setup, circuit);
122    setup.vk_proof.A = new Array(circuit.nVars+1);
123    setup.vk_proof.B = new Array(circuit.nVars+1);
124    setup.vk_proof.C = new Array(circuit.nVars+1);
125    setup.vk_proof.Ap = new Array(circuit.nVars+1);
126    setup.vk_proof.Bp = new Array(circuit.nVars+1);
127    setup.vk_proof.Cp = new Array(circuit.nVars+1);
128    setup.vk_proof.Kp = new Array(circuit.nVars+3);
129    setup.vk_verifier.A = new Array(circuit.nPublic);
130
131    setup.toxic.ka = F.random();
132    setup.toxic.kb = F.random();
133    setup.toxic.kc = F.random();
134    setup.toxic.ra = F.random();
135    setup.toxic.rb = F.random();
136    setup.toxic.rc = F.mul(setup.toxic.ra, setup.toxic.rb);
137    setup.toxic.kbeta = F.random();
138    setup.toxic.kgamma = F.random();
139
140    const gb = F.mul(setup.toxic.kbeta, setup.toxic.kgamma);
141
142    setup.vk_verifier.vk_a = G2.affine(G2.mulScalar( G2.g, setup.toxic.ka));
143    setup.vk_verifier.vk_b = G1.affine(G1.mulScalar( G1.g, setup.toxic.kb));
144    setup.vk_verifier.vk_c = G2.affine(G2.mulScalar( G2.g, setup.toxic.kc));
145    setup.vk_verifier.vk_gb_1 = G1.affine(G1.mulScalar( G1.g, gb));
146    setup.vk_verifier.vk_gb_2 = G2.affine(G2.mulScalar( G2.g, gb));
147    setup.vk_verifier.vk_g = G2.affine(G2.mulScalar( G2.g, setup.toxic.kgamma));
148
149    for (let s=0; s<circuit.nVars; s++) {
150
151        // A[i] = G1 * polA(t)
152        const raat = F.mul(setup.toxic.ra, v.a_t[s]);
153        const A = G1.affine(G1.mulScalar(G1.g, raat));
154
155        setup.vk_proof.A[s] = A;
156
157        if (s <= setup.vk_proof.nPublic) {
158            setup.vk_verifier.A[s]=A;
159        }
160
161
162        // B1[i] = G1 * polB(t)
163        const rbbt = F.mul(setup.toxic.rb, v.b_t[s]);
164        const B1 = G1.affine(G1.mulScalar(G1.g, rbbt));
165
166        // B2[i] = G2 * polB(t)
167        const B2 = G2.affine(G2.mulScalar(G2.g, rbbt));
168
169        setup.vk_proof.B[s]=B2;
170
171        // C[i] = G1 * polC(t)
172        const rcct = F.mul(setup.toxic.rc, v.c_t[s]);
173        const C = G1.affine(G1.mulScalar( G1.g, rcct));
174        setup.vk_proof.C[s] =C;
175
176        // K = G1 * (A+B+C)
177
178        const kt = F.affine(F.add(F.add(raat, rbbt), rcct));
179        const K = G1.affine(G1.mulScalar( G1.g, kt));
180
181        /*
182        // Comment this lines to improve the process
183                const Ktest = G1.affine(G1.add(G1.add(A, B1), C));
184
185                if (!G1.equals(K, Ktest)) {
186                    console.log ("=====FAIL======");
187                }
188        */
189
190
191        setup.vk_proof.Ap[s] = G1.affine(G1.mulScalar(A, setup.toxic.ka));
192        setup.vk_proof.Bp[s] = G1.affine(G1.mulScalar(B1, setup.toxic.kb));
193        setup.vk_proof.Cp[s] = G1.affine(G1.mulScalar(C, setup.toxic.kc));
194        setup.vk_proof.Kp[s] = G1.affine(G1.mulScalar(K, setup.toxic.kbeta));
195    }
196
197    // Extra coeficients
198    const A = G1.mulScalar( G1.g, F.mul(setup.toxic.ra, v.z_t));
199    setup.vk_proof.A[circuit.nVars] = G1.affine(A);
200    setup.vk_proof.Ap[circuit.nVars] = G1.affine(G1.mulScalar(A, setup.toxic.ka));
201
202    const B1 = G1.mulScalar( G1.g, F.mul(setup.toxic.rb, v.z_t));
203    const B2 = G2.mulScalar( G2.g, F.mul(setup.toxic.rb, v.z_t));
204    setup.vk_proof.B[circuit.nVars] = G2.affine(B2);
205    setup.vk_proof.Bp[circuit.nVars] = G1.affine(G1.mulScalar(B1, setup.toxic.kb));
206
207    const C = G1.mulScalar( G1.g, F.mul(setup.toxic.rc, v.z_t));
208    setup.vk_proof.C[circuit.nVars] = G1.affine(C);
209    setup.vk_proof.Cp[circuit.nVars] = G1.affine(G1.mulScalar(C, setup.toxic.kc));
210
211    setup.vk_proof.Kp[circuit.nVars  ] = G1.affine(G1.mulScalar(A, setup.toxic.kbeta));
212    setup.vk_proof.Kp[circuit.nVars+1] = G1.affine(G1.mulScalar(B1, setup.toxic.kbeta));
213    setup.vk_proof.Kp[circuit.nVars+2] = G1.affine(G1.mulScalar(C, setup.toxic.kbeta));
214
215//    setup.vk_verifier.A[0] = G1.affine(G1.add(setup.vk_verifier.A[0], setup.vk_proof.A[circuit.nVars]));
216
217    // vk_z
218    setup.vk_verifier.vk_z = G2.affine(G2.mulScalar(
219        G2.g,
220        F.mul(setup.toxic.rc, v.z_t)));
221}
222
223function calculateHexps(setup) {
224
225    const maxH = setup.vk_proof.domainSize+1;
226
227    setup.vk_proof.hExps = new Array(maxH);
228    setup.vk_proof.hExps[0] = G1.g;
229    let eT = setup.toxic.t;
230    for (let i=1; i<maxH; i++) {
231        setup.vk_proof.hExps[i] = G1.affine(G1.mulScalar(G1.g, eT));
232        eT = F.mul(eT, setup.toxic.t);
233    }
234}
235