snarkjs/src/prover.js
src/prover.jsRaw
1/*
2 Copyright 2018 0kims association.
3
4 This file is part of zksnark JavaScript library.
5
6 zksnark JavaScript library 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 zksnark JavaScript library 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 zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
18*/
19
20const BN128 = require("./bn128.js");
21const PolField = require("./polfield.js");
22const ZqField = require("./zqfield.js");
23
24const bn128 = new BN128();
25const PolF = new PolField(new ZqField(bn128.r));
26const G1 = bn128.G1;
27const G2 = bn128.G2;
28
29module.exports = function genProof(vk_proof, witness) {
30
31 const proof = {};
32
33
34 const d1 = PolF.F.random();
35 const d2 = PolF.F.random();
36 const d3 = PolF.F.random();
37
38 proof.pi_a = G1.zero;
39 proof.pi_ap = G1.zero;
40 proof.pi_b = G2.zero;
41 proof.pi_bp = G1.zero;
42 proof.pi_c = G1.zero;
43 proof.pi_cp = G1.zero;
44 proof.pi_kp = G1.zero;
45 proof.pi_h = G1.zero;
46
47
48 // Skip public entries and the "1" signal that are forced by the verifier
49 for (let s= vk_proof.nPublic+1; s< vk_proof.nVars; s++) {
50
51 // pi_a = pi_a + A[s] * witness[s];
52 proof.pi_a = G1.add( proof.pi_a, G1.mulScalar( vk_proof.A[s], witness[s]));
53
54 // pi_ap = pi_ap + Ap[s] * witness[s];
55 proof.pi_ap = G1.add( proof.pi_ap, G1.mulScalar( vk_proof.Ap[s], witness[s]));
56 }
57
58 for (let s= 0; s< vk_proof.nVars; s++) {
59 // pi_a = pi_a + A[s] * witness[s];
60 proof.pi_b = G2.add( proof.pi_b, G2.mulScalar( vk_proof.B[s], witness[s]));
61
62 // pi_ap = pi_ap + Ap[s] * witness[s];
63 proof.pi_bp = G1.add( proof.pi_bp, G1.mulScalar( vk_proof.Bp[s], witness[s]));
64
65 // pi_a = pi_a + A[s] * witness[s];
66 proof.pi_c = G1.add( proof.pi_c, G1.mulScalar( vk_proof.C[s], witness[s]));
67
68 // pi_ap = pi_ap + Ap[s] * witness[s];
69 proof.pi_cp = G1.add( proof.pi_cp, G1.mulScalar( vk_proof.Cp[s], witness[s]));
70
71 // pi_ap = pi_ap + Ap[s] * witness[s];
72 proof.pi_kp = G1.add( proof.pi_kp, G1.mulScalar( vk_proof.Kp[s], witness[s]));
73 }
74
75 proof.pi_a = G1.add( proof.pi_a, G1.mulScalar( vk_proof.A[vk_proof.nVars], d1));
76 proof.pi_ap = G1.add( proof.pi_ap, G1.mulScalar( vk_proof.Ap[vk_proof.nVars], d1));
77
78 proof.pi_b = G2.add( proof.pi_b, G2.mulScalar( vk_proof.B[vk_proof.nVars], d2));
79 proof.pi_bp = G1.add( proof.pi_bp, G1.mulScalar( vk_proof.Bp[vk_proof.nVars], d2));
80
81 proof.pi_c = G1.add( proof.pi_c, G1.mulScalar( vk_proof.C[vk_proof.nVars], d3));
82 proof.pi_cp = G1.add( proof.pi_cp, G1.mulScalar( vk_proof.Cp[vk_proof.nVars], d3));
83
84 proof.pi_kp = G1.add( proof.pi_kp, G1.mulScalar( vk_proof.Kp[vk_proof.nVars ], d1));
85 proof.pi_kp = G1.add( proof.pi_kp, G1.mulScalar( vk_proof.Kp[vk_proof.nVars+1], d2));
86 proof.pi_kp = G1.add( proof.pi_kp, G1.mulScalar( vk_proof.Kp[vk_proof.nVars+2], d3));
87
88/*
89 let polA = [];
90 let polB = [];
91 let polC = [];
92
93 for (let s= 0; s< vk_proof.nVars; s++) {
94 polA = PolF.add(
95 polA,
96 PolF.mul(
97 vk_proof.polsA[s],
98 [witness[s]] ));
99
100 polB = PolF.add(
101 polB,
102 PolF.mul(
103 vk_proof.polsB[s],
104 [witness[s]] ));
105
106 polC = PolF.add(
107 polC,
108 PolF.mul(
109 vk_proof.polsC[s],
110 [witness[s]] ));
111 }
112
113
114 let polFull = PolF.sub(PolF.mul( polA, polB), polC);
115
116 const h = PolF.div(polFull, vk_proof.polZ );
117*/
118
119 const h = calculateH(vk_proof, witness, d1, d2, d3);
120
121// console.log(h.length + "/" + vk_proof.hExps.length);
122
123 for (let i = 0; i < h.length; i++) {
124 proof.pi_h = G1.add( proof.pi_h, G1.mulScalar( vk_proof.hExps[i], h[i]));
125 }
126
127 proof.pi_a = G1.affine(proof.pi_a);
128 proof.pi_b = G2.affine(proof.pi_b);
129 proof.pi_c = G1.affine(proof.pi_c);
130 proof.pi_ap = G1.affine(proof.pi_ap);
131 proof.pi_bp = G1.affine(proof.pi_bp);
132 proof.pi_cp = G1.affine(proof.pi_cp);
133 proof.pi_kp = G1.affine(proof.pi_kp);
134 proof.pi_h = G1.affine(proof.pi_h);
135
136// proof.h=h;
137
138 const publicSignals = witness.slice(1, vk_proof.nPublic+1);
139
140 return {proof, publicSignals};
141};
142
143
144function calculateH(vk_proof, witness, d1, d2, d3) {
145
146 const F = PolF.F;
147 const m = vk_proof.domainSize;
148 const polA_T = new Array(m).fill(PolF.F.zero);
149 const polB_T = new Array(m).fill(PolF.F.zero);
150 const polC_T = new Array(m).fill(PolF.F.zero);
151
152 for (let s=0; s<vk_proof.nVars; s++) {
153 for (let c in vk_proof.polsA[s]) {
154 polA_T[c] = F.add(polA_T[c], F.mul(witness[s], vk_proof.polsA[s][c]));
155 }
156 for (let c in vk_proof.polsB[s]) {
157 polB_T[c] = F.add(polB_T[c], F.mul(witness[s], vk_proof.polsB[s][c]));
158 }
159 for (let c in vk_proof.polsC[s]) {
160 polC_T[c] = F.add(polC_T[c], F.mul(witness[s], vk_proof.polsC[s][c]));
161 }
162 }
163
164 const polA_S = PolF.ifft(polA_T);
165 const polB_S = PolF.ifft(polB_T);
166
167 const polAB_S = PolF.mul(polA_S, polB_S);
168
169 const polC_S = PolF.ifft(polC_T);
170
171 const polABC_S = PolF.sub(polAB_S, polC_S);
172
173 const polZ_S = new Array(m+1).fill(F.zero);
174 polZ_S[m] = F.one;
175 polZ_S[0] = F.neg(F.one);
176
177 let H_S = PolF.div(polABC_S, polZ_S);
178/*
179 const H2S = PolF.mul(H_S, polZ_S);
180
181 if (PolF.equals(H2S, polABC_S)) {
182 console.log("Is Divisible!");
183 } else {
184 console.log("ERROR: Not divisible!");
185 }
186*/
187
188 /* add coefficients of the polynomial (d2*A + d1*B - d3) + d1*d2*Z */
189
190 H_S = PolF.extend(H_S, m+1);
191
192 for (let i=0; i<m; i++) {
193 const d2A = PolF.F.mul(d2, polA_S[i]);
194 const d1B = PolF.F.mul(d1, polB_S[i]);
195 H_S[i] = PolF.F.add(H_S[i], PolF.F.add(d2A, d1B));
196 }
197
198 H_S[0] = PolF.F.sub(H_S[0], d3);
199
200 // Z = x^m -1
201 const d1d2 = PolF.F.mul(d1, d2);
202 H_S[m] = PolF.F.add(H_S[m], d1d2);
203 H_S[0] = PolF.F.sub(H_S[0], d1d2);
204
205 H_S = PolF.reduce(PolF.affine(H_S));
206
207 return H_S;
208}