snarkjs/src/setup.js
src/setup.jsRaw
1const bigInt = require("./bigint.js");
2
3const BN128 = require("./BN128.js");
4const PolField = require("./polfield.js");
5const ZqField = require("./zqfield.js");
6const RatField = require("./ratfield.js");
7
8const bn128 = new BN128();
9const G1 = bn128.G1;
10const G2 = bn128.G2;
11const PolF = new PolField(new ZqField(bn128.r));
12const RatPolF = new PolField(new RatField(new ZqField(bn128.r)));
13const F = new ZqField(bn128.r);
14
15module.exports = function setup(circuit) {
16 const setup = {
17 vk_proof : {
18 nVars: circuit.nVars,
19 nPublic: circuit.nPubInputs + circuit.nOutputs
20 },
21 vk_verifier: {
22 nPublic: circuit.nPubInputs + circuit.nOutputs
23 },
24 toxic: {}
25 };
26
27 calculatePolinomials(setup, circuit);
28 setup.toxic.t = F.random();
29 calculateEncriptedValuesAtT(setup, circuit);
30 calculateHexps(setup, circuit);
31
32 return setup;
33};
34
35function calculatePolinomials(setup, circuit) {
36 // Calculate the points that must cross each polinomial
37 const aPoints = [];
38 const bPoints = [];
39 const cPoints = [];
40 for (let s = 0; s<circuit.nSignals; s++) {
41 aPoints[s] = [];
42 bPoints[s] = [];
43 cPoints[s] = [];
44 for (let c=0; c<circuit.nConstrains; c++) {
45 aPoints[s].push([[bigInt(c), F.one], [circuit.a(c, s), F.one]]);
46 bPoints[s].push([[bigInt(c), F.one], [circuit.b(c, s), F.one]]);
47 cPoints[s].push([[bigInt(c), F.one], [circuit.c(c, s), F.one]]);
48 }
49 }
50
51 // Calculate the polinomials using Lagrange
52 setup.vk_proof.polsA = [];
53 setup.vk_proof.polsB = [];
54 setup.vk_proof.polsC = [];
55 for (let s=0; s<circuit.nSignals; s++) {
56// console.log(`Caclcualte Pol ${s}/${circuit.nSignals}`);
57 const pA = RatPolF.lagrange( aPoints[s] );
58 const pB = RatPolF.lagrange( bPoints[s] );
59 const pC = RatPolF.lagrange( cPoints[s] );
60
61 setup.vk_proof.polsA.push( unrat(pA) );
62 setup.vk_proof.polsB.push( unrat(pB) );
63 setup.vk_proof.polsC.push( unrat(pC) );
64
65 }
66
67 // Calculate Z polinomial
68 // Z = 1
69 setup.vk_proof.polZ = [bigInt(1)];
70 for (let c=0; c<circuit.nConstrains; c++) {
71 // Z = Z * (x - p_c)
72 setup.vk_proof.polZ = PolF.mul(
73 setup.vk_proof.polZ,
74 [F.neg(bigInt(c)), bigInt(1)] );
75 }
76}
77
78function calculateEncriptedValuesAtT(setup, circuit) {
79 setup.vk_proof.A = [];
80 setup.vk_proof.B = [];
81 setup.vk_proof.C = [];
82 setup.vk_proof.Ap = [];
83 setup.vk_proof.Bp = [];
84 setup.vk_proof.Cp = [];
85 setup.vk_proof.Kp = [];
86 setup.vk_verifier.A = [];
87
88 setup.toxic.ka = F.random();
89 setup.toxic.kb = F.random();
90 setup.toxic.kc = F.random();
91 setup.toxic.kbeta = F.random();
92 setup.toxic.kgamma = F.random();
93
94 const gb = F.mul(setup.toxic.kbeta, setup.toxic.kgamma);
95
96 setup.vk_verifier.vk_a = G2.affine(G2.mulScalar( G2.g, setup.toxic.ka));
97 setup.vk_verifier.vk_b = G1.affine(G1.mulScalar( G1.g, setup.toxic.kb));
98 setup.vk_verifier.vk_c = G2.affine(G2.mulScalar( G2.g, setup.toxic.kc));
99 setup.vk_verifier.vk_gb_1 = G1.affine(G1.mulScalar( G1.g, gb));
100 setup.vk_verifier.vk_gb_2 = G2.affine(G2.mulScalar( G2.g, gb));
101 setup.vk_verifier.vk_g = G2.affine(G2.mulScalar( G2.g, setup.toxic.kgamma));
102
103 for (let s=0; s<circuit.nSignals; s++) {
104
105 // A[i] = G1 * polA(t)
106 const at = F.affine(PolF.eval(setup.vk_proof.polsA[s], setup.toxic.t));
107 const A = G1.affine(G1.mulScalar(G1.g, at));
108
109 setup.vk_proof.A.push(A);
110
111 if (s <= setup.vk_proof.nPublic) {
112 setup.vk_verifier.A.push(A);
113 }
114
115
116 // B1[i] = G1 * polB(t)
117 const bt = F.affine(PolF.eval(setup.vk_proof.polsB[s], setup.toxic.t));
118 const B1 = G1.affine(G1.mulScalar(G1.g, bt));
119
120 // B2[i] = G2 * polB(t)
121 const B2 = G2.affine(G2.mulScalar(G2.g, bt));
122
123 setup.vk_proof.B.push(B2);
124
125 // C[i] = G1 * polC(t)
126 const ct = F.affine(PolF.eval(setup.vk_proof.polsC[s], setup.toxic.t));
127 const C = G1.affine(G1.mulScalar( G1.g, ct));
128 setup.vk_proof.C.push (C);
129
130 // K = G1 * (A+B+C)
131
132 const kt = F.affine(F.add(F.add(at, bt), ct));
133 const K = G1.affine(G1.mulScalar( G1.g, kt));
134
135
136
137 const Ktest = G1.affine(G1.add(G1.add(A, B1), C));
138
139 if (!G1.equals(K, Ktest)) {
140 console.log ("=====FAIL======");
141 }
142
143
144
145 setup.vk_proof.Ap.push(G1.affine(G1.mulScalar(A, setup.toxic.ka)));
146 setup.vk_proof.Bp.push(G1.affine(G1.mulScalar(B1, setup.toxic.kb)));
147 setup.vk_proof.Cp.push(G1.affine(G1.mulScalar(C, setup.toxic.kc)));
148 setup.vk_proof.Kp.push(G1.affine(G1.mulScalar(K, setup.toxic.kbeta)));
149 }
150
151 setup.vk_verifier.vk_z = G2.affine(G2.mulScalar(
152 G2.g,
153 PolF.eval(setup.vk_proof.polZ, setup.toxic.t)));
154}
155
156function calculateHexps(setup, circuit) {
157 let maxA = 0;
158 let maxB = 0;
159 let maxC = 0;
160 for (let s=0; s<circuit.nSignals; s++) {
161 maxA = Math.max(maxA, setup.vk_proof.polsA[s].length);
162 maxB = Math.max(maxB, setup.vk_proof.polsB[s].length);
163 maxC = Math.max(maxC, setup.vk_proof.polsC[s].length);
164 }
165
166 let maxFull = Math.max(maxA * maxB - 1, maxC);
167
168 const maxH = maxFull - setup.vk_proof.polZ.length + 1;
169
170 setup.vk_proof.hExps = new Array(maxH);
171 setup.vk_proof.hExps[0] = G1.g;
172 let eT = setup.toxic.t;
173 for (let i=1; i<maxH; i++) {
174 setup.vk_proof.hExps[i] = G1.affine(G1.mulScalar(G1.g, eT));
175 eT = F.mul(eT, setup.toxic.t);
176 }
177}
178
179function unrat(p) {
180 const res = new Array(p.length);
181 for (let i=0; i<p.length; i++) {
182 res[i] = RatPolF.F.toF(p[i]);
183 }
184 return res;
185}
186