Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
r1cs_ppzksnark_verifier_gadget.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of interfaces for the the R1CS ppzkSNARK verifier gadget.
5 
6  See r1cs_ppzksnark_verifier_gadget.hpp .
7 
8  *****************************************************************************
9  * @author This file is part of libsnark, developed by SCIPR Lab
10  * and contributors (see AUTHORS).
11  * @copyright MIT license (see LICENSE file)
12  *****************************************************************************/
13 
14 #ifndef R1CS_PPZKSNARK_VERIFIER_GADGET_TCC_
15 #define R1CS_PPZKSNARK_VERIFIER_GADGET_TCC_
16 
17 #include <libsnark/gadgetlib1/constraint_profiling.hpp>
18 
19 namespace libsnark
20 {
21 
22 template<typename ppT>
23 r1cs_ppzksnark_proof_variable<ppT>::r1cs_ppzksnark_proof_variable(
24  protoboard<FieldT> &pb, const std::string &annotation_prefix)
25  : gadget<FieldT>(pb, annotation_prefix)
26 {
27  const size_t num_G1 = 7;
28  const size_t num_G2 = 1;
29 
30  g_A_g.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_A_g")));
31  g_A_h.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_A_h")));
32  g_B_g.reset(new G2_variable<ppT>(pb, FMT(annotation_prefix, " g_B_g")));
33  g_B_h.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_B_h")));
34  g_C_g.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_C_g")));
35  g_C_h.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_C_h")));
36  g_H.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_H")));
37  g_K.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_K")));
38 
39  all_G1_vars = {g_A_g, g_A_h, g_B_h, g_C_g, g_C_h, g_H, g_K};
40  all_G2_vars = {g_B_g};
41 
42  all_G1_checkers.resize(all_G1_vars.size());
43 
44  for (size_t i = 0; i < all_G1_vars.size(); ++i) {
45  all_G1_checkers[i].reset(new G1_checker_gadget<ppT>(
46  pb,
47  *all_G1_vars[i],
48  FMT(annotation_prefix, " all_G1_checkers_%zu", i)));
49  }
50  G2_checker.reset(new G2_checker_gadget<ppT>(
51  pb, *g_B_g, FMT(annotation_prefix, " G2_checker")));
52 
53  assert(all_G1_vars.size() == num_G1);
54  assert(all_G2_vars.size() == num_G2);
55  libff::UNUSED(num_G1);
56  libff::UNUSED(num_G2);
57 }
58 
59 template<typename ppT>
60 void r1cs_ppzksnark_proof_variable<ppT>::generate_r1cs_constraints()
61 {
62  for (auto &G1_checker : all_G1_checkers) {
63  G1_checker->generate_r1cs_constraints();
64  }
65 
66  G2_checker->generate_r1cs_constraints();
67 }
68 
69 template<typename ppT>
70 void r1cs_ppzksnark_proof_variable<ppT>::generate_r1cs_witness(
71  const r1cs_ppzksnark_proof<other_curve<ppT>> &proof)
72 {
73  std::vector<libff::G1<other_curve<ppT>>> G1_elems;
74  std::vector<libff::G2<other_curve<ppT>>> G2_elems;
75 
76  G1_elems = {
77  proof.g_A.g,
78  proof.g_A.h,
79  proof.g_B.h,
80  proof.g_C.g,
81  proof.g_C.h,
82  proof.g_H,
83  proof.g_K};
84  G2_elems = {proof.g_B.g};
85 
86  assert(G1_elems.size() == all_G1_vars.size());
87  assert(G2_elems.size() == all_G2_vars.size());
88 
89  for (size_t i = 0; i < G1_elems.size(); ++i) {
90  all_G1_vars[i]->generate_r1cs_witness(G1_elems[i]);
91  }
92 
93  for (size_t i = 0; i < G2_elems.size(); ++i) {
94  all_G2_vars[i]->generate_r1cs_witness(G2_elems[i]);
95  }
96 
97  for (auto &G1_checker : all_G1_checkers) {
98  G1_checker->generate_r1cs_witness();
99  }
100 
101  G2_checker->generate_r1cs_witness();
102 }
103 
104 template<typename ppT> size_t r1cs_ppzksnark_proof_variable<ppT>::size()
105 {
106  const size_t num_G1 = 7;
107  const size_t num_G2 = 1;
108  return (
109  num_G1 * G1_variable<ppT>::num_field_elems +
110  num_G2 * G2_variable<ppT>::num_field_elems);
111 }
112 
113 template<typename ppT>
114 r1cs_ppzksnark_verification_key_variable<ppT>::
115  r1cs_ppzksnark_verification_key_variable(
116  protoboard<FieldT> &pb,
117  const size_t input_size,
118  const std::string &annotation_prefix)
119  : gadget<FieldT>(pb, annotation_prefix), input_size(input_size)
120 {
121  const size_t num_G1 = 2 + (input_size + 1);
122  const size_t num_G2 = 5;
123  libff::UNUSED(num_G1);
124  libff::UNUSED(num_G2);
125 
126  this->alphaA_g2.reset(
127  new G2_variable<ppT>(pb, FMT(annotation_prefix, " alphaA_g2")));
128  this->alphaB_g1.reset(
129  new G1_variable<ppT>(pb, FMT(annotation_prefix, " alphaB_g1")));
130  this->alphaC_g2.reset(
131  new G2_variable<ppT>(pb, FMT(annotation_prefix, " alphaC_g2")));
132  this->gamma_g2.reset(
133  new G2_variable<ppT>(pb, FMT(annotation_prefix, " gamma_g2")));
134  this->gamma_beta_g1.reset(
135  new G1_variable<ppT>(pb, FMT(annotation_prefix, " gamma_beta_g1")));
136  this->gamma_beta_g2.reset(
137  new G2_variable<ppT>(pb, FMT(annotation_prefix, " gamma_beta_g2")));
138  this->rC_Z_g2.reset(
139  new G2_variable<ppT>(pb, FMT(annotation_prefix, " rC_Z_g2")));
140 
141  all_G1_vars = {this->alphaB_g1, this->gamma_beta_g1};
142  all_G2_vars = {
143  this->alphaA_g2,
144  this->alphaC_g2,
145  this->gamma_g2,
146  this->gamma_beta_g2,
147  this->rC_Z_g2};
148 
149  this->encoded_IC_query.resize(input_size);
150  this->encoded_IC_base.reset(
151  new G1_variable<ppT>(pb, FMT(annotation_prefix, " encoded_IC_base")));
152  this->all_G1_vars.emplace_back(this->encoded_IC_base);
153 
154  for (size_t i = 0; i < input_size; ++i) {
155  this->encoded_IC_query[i].reset(new G1_variable<ppT>(
156  pb, FMT(annotation_prefix, " encoded_IC_query_%zu", i)));
157  all_G1_vars.emplace_back(this->encoded_IC_query[i]);
158  }
159 
160  for (auto &G1_var : all_G1_vars) {
161  all_vars.insert(
162  all_vars.end(), G1_var->all_vars.begin(), G1_var->all_vars.end());
163  }
164 
165  for (auto &G2_var : all_G2_vars) {
166  all_vars.insert(
167  all_vars.end(), G2_var->all_vars.begin(), G2_var->all_vars.end());
168  }
169 
170  assert(all_G1_vars.size() == num_G1);
171  assert(all_G2_vars.size() == num_G2);
172  assert(
173  all_vars.size() == (num_G1 * G1_variable<ppT>::num_variables() +
174  num_G2 * G2_variable<ppT>::num_variables()));
175 }
176 
177 template<typename ppT>
178 void r1cs_ppzksnark_verification_key_variable<ppT>::generate_r1cs_constraints()
179 {
180 }
181 
182 template<typename ppT>
183 void r1cs_ppzksnark_verification_key_variable<ppT>::generate_r1cs_witness(
184  const r1cs_ppzksnark_verification_key<other_curve<ppT>> &vk)
185 {
186  std::vector<libff::G1<other_curve<ppT>>> G1_elems;
187  std::vector<libff::G2<other_curve<ppT>>> G2_elems;
188 
189  G1_elems = {vk.alphaB_g1, vk.gamma_beta_g1};
190  G2_elems = {
191  vk.alphaA_g2, vk.alphaC_g2, vk.gamma_g2, vk.gamma_beta_g2, vk.rC_Z_g2};
192 
193  assert(vk.encoded_IC_query.rest.indices.size() == input_size);
194  G1_elems.emplace_back(vk.encoded_IC_query.first);
195  for (size_t i = 0; i < input_size; ++i) {
196  assert(vk.encoded_IC_query.rest.indices[i] == i);
197  G1_elems.emplace_back(vk.encoded_IC_query.rest.values[i]);
198  }
199 
200  assert(G1_elems.size() == all_G1_vars.size());
201  assert(G2_elems.size() == all_G2_vars.size());
202 
203  for (size_t i = 0; i < G1_elems.size(); ++i) {
204  all_G1_vars[i]->generate_r1cs_witness(G1_elems[i]);
205  }
206 
207  for (size_t i = 0; i < G2_elems.size(); ++i) {
208  all_G2_vars[i]->generate_r1cs_witness(G2_elems[i]);
209  }
210 }
211 
212 template<typename ppT>
213 size_t r1cs_ppzksnark_verification_key_variable<ppT>::num_primary_inputs() const
214 {
215  return input_size;
216 }
217 
218 template<typename ppT>
219 const pb_linear_combination_array<libff::Fr<ppT>>
220  &r1cs_ppzksnark_verification_key_variable<ppT>::get_all_vars() const
221 {
222  return all_vars;
223 }
224 
225 template<typename ppT>
226 std::vector<libff::Fr<ppT>> r1cs_ppzksnark_verification_key_variable<ppT>::
227  get_verification_key_scalars(
228  const r1cs_ppzksnark_verification_key<other_curve<ppT>> &r1cs_vk)
229 {
230  const size_t input_size_in_elts =
231  r1cs_vk.encoded_IC_query.rest.indices.size();
232 
233  protoboard<FieldT> pb;
234  r1cs_ppzksnark_verification_key_variable<ppT> vk(
235  pb, input_size_in_elts, "translation_step_vk");
236  vk.generate_r1cs_witness(r1cs_vk);
237 
238  const size_t num_scalars = vk.all_vars.size();
239  std::vector<FieldT> scalars;
240  scalars.reserve(num_scalars);
241  for (size_t i = 0; i < num_scalars; ++i) {
242  scalars.push_back(pb.lc_val(vk.all_vars[i]));
243  }
244 
245  return scalars;
246 }
247 
248 template<typename ppT>
249 r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable<
250  ppT>::r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable()
251 {
252  // will be allocated outside
253 }
254 
255 template<typename ppT>
256 r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable<ppT>::
257  r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable(
258  protoboard<FieldT> &pb,
259  const r1cs_ppzksnark_verification_key<other_curve<ppT>> &r1cs_vk,
260  const std::string &annotation_prefix)
261 {
262  encoded_IC_base.reset(new G1_variable<ppT>(
263  pb,
264  r1cs_vk.encoded_IC_query.first,
265  FMT(annotation_prefix, " encoded_IC_base")));
266  encoded_IC_query.resize(r1cs_vk.encoded_IC_query.rest.indices.size());
267  for (size_t i = 0; i < r1cs_vk.encoded_IC_query.rest.indices.size(); ++i) {
268  assert(r1cs_vk.encoded_IC_query.rest.indices[i] == i);
269  encoded_IC_query[i].reset(new G1_variable<ppT>(
270  pb,
271  r1cs_vk.encoded_IC_query.rest.values[i],
272  FMT(annotation_prefix, " encoded_IC_query")));
273  }
274 
275  vk_alphaB_g1_precomp.reset(new G1_precomputation<ppT>(
276  pb,
277  r1cs_vk.alphaB_g1,
278  FMT(annotation_prefix, " vk_alphaB_g1_precomp")));
279  vk_gamma_beta_g1_precomp.reset(new G1_precomputation<ppT>(
280  pb,
281  r1cs_vk.gamma_beta_g1,
282  FMT(annotation_prefix, " vk_gamma_beta_g1_precomp")));
283 
284  pp_G2_one_precomp.reset(new G2_precomputation<ppT>(
285  pb,
286  libff::G2<other_curve<ppT>>::one(),
287  FMT(annotation_prefix, " pp_G2_one_precomp")));
288  vk_alphaA_g2_precomp.reset(new G2_precomputation<ppT>(
289  pb,
290  r1cs_vk.alphaA_g2,
291  FMT(annotation_prefix, " vk_alphaA_g2_precomp")));
292  vk_alphaC_g2_precomp.reset(new G2_precomputation<ppT>(
293  pb,
294  r1cs_vk.alphaC_g2,
295  FMT(annotation_prefix, " vk_alphaC_g2_precomp")));
296  vk_gamma_beta_g2_precomp.reset(new G2_precomputation<ppT>(
297  pb,
298  r1cs_vk.gamma_beta_g2,
299  FMT(annotation_prefix, " vk_gamma_beta_g2_precomp")));
300  vk_gamma_g2_precomp.reset(new G2_precomputation<ppT>(
301  pb, r1cs_vk.gamma_g2, FMT(annotation_prefix, " vk_gamma_g2_precomp")));
302  vk_rC_Z_g2_precomp.reset(new G2_precomputation<ppT>(
303  pb, r1cs_vk.rC_Z_g2, FMT(annotation_prefix, " vk_rC_Z_g2_precomp")));
304 }
305 
306 template<typename ppT>
307 r1cs_ppzksnark_verifier_process_vk_gadget<ppT>::
308  r1cs_ppzksnark_verifier_process_vk_gadget(
309  protoboard<FieldT> &pb,
310  const r1cs_ppzksnark_verification_key_variable<ppT> &vk,
311  r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable<
312  ppT> &pvk,
313  const std::string &annotation_prefix)
314  : gadget<FieldT>(pb, annotation_prefix), vk(vk), pvk(pvk)
315 {
316  pvk.encoded_IC_base = vk.encoded_IC_base;
317  pvk.encoded_IC_query = vk.encoded_IC_query;
318 
319  pvk.vk_alphaB_g1_precomp.reset(new G1_precomputation<ppT>());
320  pvk.vk_gamma_beta_g1_precomp.reset(new G1_precomputation<ppT>());
321 
322  pvk.pp_G2_one_precomp.reset(new G2_precomputation<ppT>());
323  pvk.vk_alphaA_g2_precomp.reset(new G2_precomputation<ppT>());
324  pvk.vk_alphaC_g2_precomp.reset(new G2_precomputation<ppT>());
325  pvk.vk_gamma_beta_g2_precomp.reset(new G2_precomputation<ppT>());
326  pvk.vk_gamma_g2_precomp.reset(new G2_precomputation<ppT>());
327  pvk.vk_rC_Z_g2_precomp.reset(new G2_precomputation<ppT>());
328 
329  compute_vk_alphaB_g1_precomp.reset(new precompute_G1_gadget<ppT>(
330  pb,
331  *vk.alphaB_g1,
332  *pvk.vk_alphaB_g1_precomp,
333  FMT(annotation_prefix, " compute_vk_alphaB_g1_precomp")));
334  compute_vk_gamma_beta_g1_precomp.reset(new precompute_G1_gadget<ppT>(
335  pb,
336  *vk.gamma_beta_g1,
337  *pvk.vk_gamma_beta_g1_precomp,
338  FMT(annotation_prefix, " compute_vk_gamma_beta_g1_precomp")));
339 
340  pvk.pp_G2_one_precomp.reset(new G2_precomputation<ppT>(
341  pb,
342  libff::G2<other_curve<ppT>>::one(),
343  FMT(annotation_prefix, " pp_G2_one_precomp")));
344  compute_vk_alphaA_g2_precomp.reset(new precompute_G2_gadget<ppT>(
345  pb,
346  *vk.alphaA_g2,
347  *pvk.vk_alphaA_g2_precomp,
348  FMT(annotation_prefix, " compute_vk_alphaA_g2_precomp")));
349  compute_vk_alphaC_g2_precomp.reset(new precompute_G2_gadget<ppT>(
350  pb,
351  *vk.alphaC_g2,
352  *pvk.vk_alphaC_g2_precomp,
353  FMT(annotation_prefix, " compute_vk_alphaC_g2_precomp")));
354  compute_vk_gamma_beta_g2_precomp.reset(new precompute_G2_gadget<ppT>(
355  pb,
356  *vk.gamma_beta_g2,
357  *pvk.vk_gamma_beta_g2_precomp,
358  FMT(annotation_prefix, " compute_vk_gamma_beta_g2_precomp")));
359  compute_vk_gamma_g2_precomp.reset(new precompute_G2_gadget<ppT>(
360  pb,
361  *vk.gamma_g2,
362  *pvk.vk_gamma_g2_precomp,
363  FMT(annotation_prefix, " compute_vk_gamma_g2_precomp")));
364  compute_vk_rC_Z_g2_precomp.reset(new precompute_G2_gadget<ppT>(
365  pb,
366  *vk.rC_Z_g2,
367  *pvk.vk_rC_Z_g2_precomp,
368  FMT(annotation_prefix, " compute_vk_rC_Z_g2_precomp")));
369 }
370 
371 template<typename ppT>
372 void r1cs_ppzksnark_verifier_process_vk_gadget<ppT>::generate_r1cs_constraints()
373 {
374  compute_vk_alphaB_g1_precomp->generate_r1cs_constraints();
375  compute_vk_gamma_beta_g1_precomp->generate_r1cs_constraints();
376 
377  compute_vk_alphaA_g2_precomp->generate_r1cs_constraints();
378  compute_vk_alphaC_g2_precomp->generate_r1cs_constraints();
379  compute_vk_gamma_beta_g2_precomp->generate_r1cs_constraints();
380  compute_vk_gamma_g2_precomp->generate_r1cs_constraints();
381  compute_vk_rC_Z_g2_precomp->generate_r1cs_constraints();
382 }
383 
384 template<typename ppT>
385 void r1cs_ppzksnark_verifier_process_vk_gadget<ppT>::generate_r1cs_witness()
386 {
387  compute_vk_alphaB_g1_precomp->generate_r1cs_witness();
388  compute_vk_gamma_beta_g1_precomp->generate_r1cs_witness();
389 
390  compute_vk_alphaA_g2_precomp->generate_r1cs_witness();
391  compute_vk_alphaC_g2_precomp->generate_r1cs_witness();
392  compute_vk_gamma_beta_g2_precomp->generate_r1cs_witness();
393  compute_vk_gamma_g2_precomp->generate_r1cs_witness();
394  compute_vk_rC_Z_g2_precomp->generate_r1cs_witness();
395 }
396 
397 template<typename ppT>
398 r1cs_ppzksnark_online_verifier_gadget<ppT>::r1cs_ppzksnark_online_verifier_gadget(
399  protoboard<FieldT> &pb,
400  const r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable<
401  ppT> &pvk,
402  const pb_variable_array<FieldT> &input,
403  const size_t elt_size,
404  const r1cs_ppzksnark_proof_variable<ppT> &proof,
405  const pb_variable<FieldT> &result,
406  const std::string &annotation_prefix)
407  : gadget<FieldT>(pb, annotation_prefix)
408  , pvk(pvk)
409  , input(input)
410  , elt_size(elt_size)
411  , proof(proof)
412  , result(result)
413  , input_len(input.size())
414 {
415  // accumulate input and store base in acc
416  acc.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " acc")));
417  std::vector<G1_variable<ppT>> IC_terms;
418  for (size_t i = 0; i < pvk.encoded_IC_query.size(); ++i) {
419  IC_terms.emplace_back(*(pvk.encoded_IC_query[i]));
420  }
421  accumulate_input.reset(new G1_multiscalar_mul_gadget<ppT>(
422  pb,
423  *(pvk.encoded_IC_base),
424  input,
425  elt_size,
426  IC_terms,
427  *acc,
428  FMT(annotation_prefix, " accumulate_input")));
429 
430  // allocate results for precomputation
431  proof_g_A_h_precomp.reset(new G1_precomputation<ppT>());
432  proof_g_A_g_acc_C_precomp.reset(new G1_precomputation<ppT>());
433  proof_g_A_g_acc_precomp.reset(new G1_precomputation<ppT>());
434  proof_g_A_g_precomp.reset(new G1_precomputation<ppT>());
435  proof_g_B_h_precomp.reset(new G1_precomputation<ppT>());
436  proof_g_C_h_precomp.reset(new G1_precomputation<ppT>());
437  proof_g_C_g_precomp.reset(new G1_precomputation<ppT>());
438  proof_g_K_precomp.reset(new G1_precomputation<ppT>());
439  proof_g_H_precomp.reset(new G1_precomputation<ppT>());
440 
441  proof_g_B_g_precomp.reset(new G2_precomputation<ppT>());
442 
443  // do the necessary precomputations
444  // compute things not available in plain from proof/vk
445  proof_g_A_g_acc.reset(
446  new G1_variable<ppT>(pb, FMT(annotation_prefix, " proof_g_A_g_acc")));
447  compute_proof_g_A_g_acc.reset(new G1_add_gadget<ppT>(
448  pb,
449  *(proof.g_A_g),
450  *acc,
451  *proof_g_A_g_acc,
452  FMT(annotation_prefix, " compute_proof_g_A_g_acc")));
453  proof_g_A_g_acc_C.reset(
454  new G1_variable<ppT>(pb, FMT(annotation_prefix, " proof_g_A_g_acc_C")));
455  compute_proof_g_A_g_acc_C.reset(new G1_add_gadget<ppT>(
456  pb,
457  *proof_g_A_g_acc,
458  *(proof.g_C_g),
459  *proof_g_A_g_acc_C,
460  FMT(annotation_prefix, " compute_proof_g_A_g_acc_C")));
461 
462  compute_proof_g_A_g_acc_precomp.reset(new precompute_G1_gadget<ppT>(
463  pb,
464  *proof_g_A_g_acc,
465  *proof_g_A_g_acc_precomp,
466  FMT(annotation_prefix, " compute_proof_g_A_g_acc_precomp")));
467  compute_proof_g_A_g_acc_C_precomp.reset(new precompute_G1_gadget<ppT>(
468  pb,
469  *proof_g_A_g_acc_C,
470  *proof_g_A_g_acc_C_precomp,
471  FMT(annotation_prefix, " compute_proof_g_A_g_acc_C_precomp")));
472 
473  // do other precomputations
474  compute_proof_g_A_h_precomp.reset(new precompute_G1_gadget<ppT>(
475  pb,
476  *(proof.g_A_h),
477  *proof_g_A_h_precomp,
478  FMT(annotation_prefix, " compute_proof_g_A_h_precomp")));
479  compute_proof_g_A_g_precomp.reset(new precompute_G1_gadget<ppT>(
480  pb,
481  *(proof.g_A_g),
482  *proof_g_A_g_precomp,
483  FMT(annotation_prefix, " compute_proof_g_A_g_precomp")));
484  compute_proof_g_B_h_precomp.reset(new precompute_G1_gadget<ppT>(
485  pb,
486  *(proof.g_B_h),
487  *proof_g_B_h_precomp,
488  FMT(annotation_prefix, " compute_proof_g_B_h_precomp")));
489  compute_proof_g_C_h_precomp.reset(new precompute_G1_gadget<ppT>(
490  pb,
491  *(proof.g_C_h),
492  *proof_g_C_h_precomp,
493  FMT(annotation_prefix, " compute_proof_g_C_h_precomp")));
494  compute_proof_g_C_g_precomp.reset(new precompute_G1_gadget<ppT>(
495  pb,
496  *(proof.g_C_g),
497  *proof_g_C_g_precomp,
498  FMT(annotation_prefix, " compute_proof_g_C_g_precomp")));
499  compute_proof_g_H_precomp.reset(new precompute_G1_gadget<ppT>(
500  pb,
501  *(proof.g_H),
502  *proof_g_H_precomp,
503  FMT(annotation_prefix, " compute_proof_g_H_precomp")));
504  compute_proof_g_K_precomp.reset(new precompute_G1_gadget<ppT>(
505  pb,
506  *(proof.g_K),
507  *proof_g_K_precomp,
508  FMT(annotation_prefix, " compute_proof_g_K_precomp")));
509  compute_proof_g_B_g_precomp.reset(new precompute_G2_gadget<ppT>(
510  pb,
511  *(proof.g_B_g),
512  *proof_g_B_g_precomp,
513  FMT(annotation_prefix, " compute_proof_g_B_g_precomp")));
514 
515  // check validity of A knowledge commitment
516  kc_A_valid.allocate(pb, FMT(annotation_prefix, " kc_A_valid"));
517  check_kc_A_valid.reset(new check_e_equals_e_gadget<ppT>(
518  pb,
519  *proof_g_A_g_precomp,
520  *(pvk.vk_alphaA_g2_precomp),
521  *proof_g_A_h_precomp,
522  *(pvk.pp_G2_one_precomp),
523  kc_A_valid,
524  FMT(annotation_prefix, " check_kc_A_valid")));
525 
526  // check validity of B knowledge commitment
527  kc_B_valid.allocate(pb, FMT(annotation_prefix, " kc_B_valid"));
528  check_kc_B_valid.reset(new check_e_equals_e_gadget<ppT>(
529  pb,
530  *(pvk.vk_alphaB_g1_precomp),
531  *proof_g_B_g_precomp,
532  *proof_g_B_h_precomp,
533  *(pvk.pp_G2_one_precomp),
534  kc_B_valid,
535  FMT(annotation_prefix, " check_kc_B_valid")));
536 
537  // check validity of C knowledge commitment
538  kc_C_valid.allocate(pb, FMT(annotation_prefix, " kc_C_valid"));
539  check_kc_C_valid.reset(new check_e_equals_e_gadget<ppT>(
540  pb,
541  *proof_g_C_g_precomp,
542  *(pvk.vk_alphaC_g2_precomp),
543  *proof_g_C_h_precomp,
544  *(pvk.pp_G2_one_precomp),
545  kc_C_valid,
546  FMT(annotation_prefix, " check_kc_C_valid")));
547 
548  // check QAP divisibility
549  QAP_valid.allocate(pb, FMT(annotation_prefix, " QAP_valid"));
550  check_QAP_valid.reset(new check_e_equals_ee_gadget<ppT>(
551  pb,
552  *proof_g_A_g_acc_precomp,
553  *proof_g_B_g_precomp,
554  *proof_g_H_precomp,
555  *(pvk.vk_rC_Z_g2_precomp),
556  *proof_g_C_g_precomp,
557  *(pvk.pp_G2_one_precomp),
558  QAP_valid,
559  FMT(annotation_prefix, " check_QAP_valid")));
560 
561  // check coefficients
562  CC_valid.allocate(pb, FMT(annotation_prefix, " CC_valid"));
563  check_CC_valid.reset(new check_e_equals_ee_gadget<ppT>(
564  pb,
565  *proof_g_K_precomp,
566  *(pvk.vk_gamma_g2_precomp),
567  *proof_g_A_g_acc_C_precomp,
568  *(pvk.vk_gamma_beta_g2_precomp),
569  *(pvk.vk_gamma_beta_g1_precomp),
570  *proof_g_B_g_precomp,
571  CC_valid,
572  FMT(annotation_prefix, " check_CC_valid")));
573 
574  // final constraint
575  all_test_results.emplace_back(kc_A_valid);
576  all_test_results.emplace_back(kc_B_valid);
577  all_test_results.emplace_back(kc_C_valid);
578  all_test_results.emplace_back(QAP_valid);
579  all_test_results.emplace_back(CC_valid);
580 
581  all_tests_pass.reset(new conjunction_gadget<FieldT>(
582  pb,
583  all_test_results,
584  result,
585  FMT(annotation_prefix, " all_tests_pass")));
586 }
587 
588 template<typename ppT>
589 void r1cs_ppzksnark_online_verifier_gadget<ppT>::generate_r1cs_constraints()
590 {
591  PROFILE_CONSTRAINTS(this->pb, "accumulate verifier input")
592  {
593  libff::print_indent();
594  printf(
595  "* Number of bits as an input to verifier gadget: %zu\n",
596  input.size());
597  accumulate_input->generate_r1cs_constraints();
598  }
599 
600  PROFILE_CONSTRAINTS(this->pb, "rest of the verifier")
601  {
602  compute_proof_g_A_g_acc->generate_r1cs_constraints();
603  compute_proof_g_A_g_acc_C->generate_r1cs_constraints();
604 
605  compute_proof_g_A_g_acc_precomp->generate_r1cs_constraints();
606  compute_proof_g_A_g_acc_C_precomp->generate_r1cs_constraints();
607 
608  compute_proof_g_A_h_precomp->generate_r1cs_constraints();
609  compute_proof_g_A_g_precomp->generate_r1cs_constraints();
610  compute_proof_g_B_h_precomp->generate_r1cs_constraints();
611  compute_proof_g_C_h_precomp->generate_r1cs_constraints();
612  compute_proof_g_C_g_precomp->generate_r1cs_constraints();
613  compute_proof_g_H_precomp->generate_r1cs_constraints();
614  compute_proof_g_K_precomp->generate_r1cs_constraints();
615  compute_proof_g_B_g_precomp->generate_r1cs_constraints();
616 
617  check_kc_A_valid->generate_r1cs_constraints();
618  check_kc_B_valid->generate_r1cs_constraints();
619  check_kc_C_valid->generate_r1cs_constraints();
620  check_QAP_valid->generate_r1cs_constraints();
621  check_CC_valid->generate_r1cs_constraints();
622 
623  all_tests_pass->generate_r1cs_constraints();
624  }
625 }
626 
627 template<typename ppT>
628 void r1cs_ppzksnark_online_verifier_gadget<ppT>::generate_r1cs_witness()
629 {
630  accumulate_input->generate_r1cs_witness();
631 
632  compute_proof_g_A_g_acc->generate_r1cs_witness();
633  compute_proof_g_A_g_acc_C->generate_r1cs_witness();
634 
635  compute_proof_g_A_g_acc_precomp->generate_r1cs_witness();
636  compute_proof_g_A_g_acc_C_precomp->generate_r1cs_witness();
637 
638  compute_proof_g_A_h_precomp->generate_r1cs_witness();
639  compute_proof_g_A_g_precomp->generate_r1cs_witness();
640  compute_proof_g_B_h_precomp->generate_r1cs_witness();
641  compute_proof_g_C_h_precomp->generate_r1cs_witness();
642  compute_proof_g_C_g_precomp->generate_r1cs_witness();
643  compute_proof_g_H_precomp->generate_r1cs_witness();
644  compute_proof_g_K_precomp->generate_r1cs_witness();
645  compute_proof_g_B_g_precomp->generate_r1cs_witness();
646 
647  check_kc_A_valid->generate_r1cs_witness();
648  check_kc_B_valid->generate_r1cs_witness();
649  check_kc_C_valid->generate_r1cs_witness();
650  check_QAP_valid->generate_r1cs_witness();
651  check_CC_valid->generate_r1cs_witness();
652 
653  all_tests_pass->generate_r1cs_witness();
654 }
655 
656 template<typename ppT>
657 r1cs_ppzksnark_verifier_gadget<ppT>::r1cs_ppzksnark_verifier_gadget(
658  protoboard<FieldT> &pb,
659  const r1cs_ppzksnark_verification_key_variable<ppT> &vk,
660  const pb_variable_array<FieldT> &input,
661  const size_t elt_size,
662  const r1cs_ppzksnark_proof_variable<ppT> &proof,
663  const pb_variable<FieldT> &result,
664  const std::string &annotation_prefix)
665  : gadget<FieldT>(pb, annotation_prefix)
666 {
667  pvk.reset(
668  new r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable<
669  ppT>());
670  compute_pvk.reset(new r1cs_ppzksnark_verifier_process_vk_gadget<ppT>(
671  pb, vk, *pvk, FMT(annotation_prefix, " compute_pvk")));
672  online_verifier.reset(new r1cs_ppzksnark_online_verifier_gadget<ppT>(
673  pb,
674  *pvk,
675  input,
676  elt_size,
677  proof,
678  result,
679  FMT(annotation_prefix, " online_verifier")));
680 }
681 
682 template<typename ppT>
683 void r1cs_ppzksnark_verifier_gadget<ppT>::generate_r1cs_constraints()
684 {
685  PROFILE_CONSTRAINTS(this->pb, "precompute pvk")
686  {
687  compute_pvk->generate_r1cs_constraints();
688  }
689 
690  PROFILE_CONSTRAINTS(this->pb, "online verifier")
691  {
692  online_verifier->generate_r1cs_constraints();
693  }
694 }
695 
696 template<typename ppT>
697 void r1cs_ppzksnark_verifier_gadget<ppT>::generate_r1cs_witness()
698 {
699  compute_pvk->generate_r1cs_witness();
700  online_verifier->generate_r1cs_witness();
701 }
702 
703 } // namespace libsnark
704 
705 #endif // R1CS_PPZKSNARK_VERIFIER_GADGET_TCC_