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