Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
uscs_ppzksnark.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3  Implementation of interfaces for a ppzkSNARK for USCS.
4 
5  See uscs_ppzksnark.hpp .
6  *****************************************************************************
7  * @author This file is part of libsnark, developed by SCIPR Lab
8  * and contributors (see AUTHORS).
9  * @copyright MIT license (see LICENSE file)
10  *****************************************************************************/
11 
12 #ifndef USCS_PPZKSNARK_TCC_
13 #define USCS_PPZKSNARK_TCC_
14 
15 #include <algorithm>
16 #include <cassert>
17 #include <functional>
18 #include <iostream>
19 #include <libff/algebra/scalar_multiplication/multiexp.hpp>
20 #include <libff/common/profiling.hpp>
21 #include <libff/common/utils.hpp>
22 #include <sstream>
23 
24 #ifdef MULTICORE
25 #include <omp.h>
26 #endif
27 
28 #include <libsnark/reductions/uscs_to_ssp/uscs_to_ssp.hpp>
29 #include <libsnark/relations/arithmetic_programs/ssp/ssp.hpp>
30 
31 namespace libsnark
32 {
33 
34 template<typename ppT>
35 bool uscs_ppzksnark_proving_key<ppT>::operator==(
36  const uscs_ppzksnark_proving_key<ppT> &other) const
37 {
38  return (
39  this->V_g1_query == other.V_g1_query &&
40  this->alpha_V_g1_query == other.alpha_V_g1_query &&
41  this->H_g1_query == other.H_g1_query &&
42  this->V_g2_query == other.V_g2_query &&
43  this->constraint_system == other.constraint_system);
44 }
45 
46 template<typename ppT>
47 std::ostream &operator<<(
48  std::ostream &out, const uscs_ppzksnark_proving_key<ppT> &pk)
49 {
50  out << pk.V_g1_query;
51  out << pk.alpha_V_g1_query;
52  out << pk.H_g1_query;
53  out << pk.V_g2_query;
54  out << pk.constraint_system;
55 
56  return out;
57 }
58 
59 template<typename ppT>
60 std::istream &operator>>(std::istream &in, uscs_ppzksnark_proving_key<ppT> &pk)
61 {
62  in >> pk.V_g1_query;
63  in >> pk.alpha_V_g1_query;
64  in >> pk.H_g1_query;
65  in >> pk.V_g2_query;
66  in >> pk.constraint_system;
67 
68  return in;
69 }
70 
71 template<typename ppT>
72 bool uscs_ppzksnark_verification_key<ppT>::operator==(
73  const uscs_ppzksnark_verification_key<ppT> &other) const
74 {
75  return (
76  this->tilde_g2 == other.tilde_g2 &&
77  this->alpha_tilde_g2 == other.alpha_tilde_g2 &&
78  this->Z_g2 == other.Z_g2 &&
79  this->encoded_IC_query == other.encoded_IC_query);
80 }
81 
82 template<typename ppT>
83 std::ostream &operator<<(
84  std::ostream &out, const uscs_ppzksnark_verification_key<ppT> &vk)
85 {
86  out << vk.tilde_g2 << OUTPUT_NEWLINE;
87  out << vk.alpha_tilde_g2 << OUTPUT_NEWLINE;
88  out << vk.Z_g2 << OUTPUT_NEWLINE;
89  out << vk.encoded_IC_query << OUTPUT_NEWLINE;
90 
91  return out;
92 }
93 
94 template<typename ppT>
95 std::istream &operator>>(
96  std::istream &in, uscs_ppzksnark_verification_key<ppT> &vk)
97 {
98  in >> vk.tilde_g2;
99  libff::consume_OUTPUT_NEWLINE(in);
100  in >> vk.alpha_tilde_g2;
101  libff::consume_OUTPUT_NEWLINE(in);
102  in >> vk.Z_g2;
103  libff::consume_OUTPUT_NEWLINE(in);
104  in >> vk.encoded_IC_query;
105  libff::consume_OUTPUT_NEWLINE(in);
106 
107  return in;
108 }
109 
110 template<typename ppT>
111 bool uscs_ppzksnark_processed_verification_key<ppT>::operator==(
112  const uscs_ppzksnark_processed_verification_key<ppT> &other) const
113 {
114  return (
115  this->pp_G1_one_precomp == other.pp_G1_one_precomp &&
116  this->pp_G2_one_precomp == other.pp_G2_one_precomp &&
117  this->vk_tilde_g2_precomp == other.vk_tilde_g2_precomp &&
118  this->vk_alpha_tilde_g2_precomp == other.vk_alpha_tilde_g2_precomp &&
119  this->vk_Z_g2_precomp == other.vk_Z_g2_precomp &&
120  this->pairing_of_g1_and_g2 == other.pairing_of_g1_and_g2 &&
121  this->encoded_IC_query == other.encoded_IC_query);
122 }
123 
124 template<typename ppT>
125 std::ostream &operator<<(
126  std::ostream &out,
127  const uscs_ppzksnark_processed_verification_key<ppT> &pvk)
128 {
129  out << pvk.pp_G1_one_precomp << OUTPUT_NEWLINE;
130  out << pvk.pp_G2_one_precomp << OUTPUT_NEWLINE;
131  out << pvk.vk_tilde_g2_precomp << OUTPUT_NEWLINE;
132  out << pvk.vk_alpha_tilde_g2_precomp << OUTPUT_NEWLINE;
133  out << pvk.vk_Z_g2_precomp << OUTPUT_NEWLINE;
134  out << pvk.pairing_of_g1_and_g2 << OUTPUT_NEWLINE;
135  out << pvk.encoded_IC_query << OUTPUT_NEWLINE;
136 
137  return out;
138 }
139 
140 template<typename ppT>
141 std::istream &operator>>(
142  std::istream &in, uscs_ppzksnark_processed_verification_key<ppT> &pvk)
143 {
144  in >> pvk.pp_G1_one_precomp;
145  libff::consume_OUTPUT_NEWLINE(in);
146  in >> pvk.pp_G2_one_precomp;
147  libff::consume_OUTPUT_NEWLINE(in);
148  in >> pvk.vk_tilde_g2_precomp;
149  libff::consume_OUTPUT_NEWLINE(in);
150  in >> pvk.vk_alpha_tilde_g2_precomp;
151  libff::consume_OUTPUT_NEWLINE(in);
152  in >> pvk.vk_Z_g2_precomp;
153  libff::consume_OUTPUT_NEWLINE(in);
154  in >> pvk.pairing_of_g1_and_g2;
155  libff::consume_OUTPUT_NEWLINE(in);
156  in >> pvk.encoded_IC_query;
157  libff::consume_OUTPUT_NEWLINE(in);
158 
159  return in;
160 }
161 
162 template<typename ppT>
163 bool uscs_ppzksnark_proof<ppT>::operator==(
164  const uscs_ppzksnark_proof<ppT> &other) const
165 {
166  return (
167  this->V_g1 == other.V_g1 && this->alpha_V_g1 == other.alpha_V_g1 &&
168  this->H_g1 == other.H_g1 && this->V_g2 == other.V_g2);
169 }
170 
171 template<typename ppT>
172 std::ostream &operator<<(
173  std::ostream &out, const uscs_ppzksnark_proof<ppT> &proof)
174 {
175  out << proof.V_g1 << OUTPUT_NEWLINE;
176  out << proof.alpha_V_g1 << OUTPUT_NEWLINE;
177  out << proof.H_g1 << OUTPUT_NEWLINE;
178  out << proof.V_g2 << OUTPUT_NEWLINE;
179 
180  return out;
181 }
182 
183 template<typename ppT>
184 std::istream &operator>>(std::istream &in, uscs_ppzksnark_proof<ppT> &proof)
185 {
186  in >> proof.V_g1;
187  libff::consume_OUTPUT_NEWLINE(in);
188  in >> proof.alpha_V_g1;
189  libff::consume_OUTPUT_NEWLINE(in);
190  in >> proof.H_g1;
191  libff::consume_OUTPUT_NEWLINE(in);
192  in >> proof.V_g2;
193  libff::consume_OUTPUT_NEWLINE(in);
194 
195  return in;
196 }
197 
198 template<typename ppT>
199 uscs_ppzksnark_verification_key<ppT> uscs_ppzksnark_verification_key<
200  ppT>::dummy_verification_key(const size_t input_size)
201 {
202  uscs_ppzksnark_verification_key<ppT> result;
203  result.tilde_g2 = libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
204  result.alpha_tilde_g2 =
205  libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
206  result.Z_g2 = libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
207 
208  libff::G1<ppT> base =
209  libff::Fr<ppT>::random_element() * libff::G1<ppT>::one();
210  libff::G1_vector<ppT> v;
211  for (size_t i = 0; i < input_size; ++i) {
212  v.emplace_back(
213  libff::Fr<ppT>::random_element() * libff::G1<ppT>::one());
214  }
215 
216  result.encoded_IC_query = accumulation_vector<libff::G1<ppT>>(v);
217 
218  return result;
219 }
220 
221 template<typename ppT, libff::multi_exp_base_form BaseForm>
222 uscs_ppzksnark_keypair<ppT> uscs_ppzksnark_generator(
223  const uscs_ppzksnark_constraint_system<ppT> &cs)
224 {
225  libff::enter_block("Call to uscs_ppzksnark_generator");
226 
227  /* draw random element at which the SSP is evaluated */
228 
229  const libff::Fr<ppT> t = libff::Fr<ppT>::random_element();
230 
231  /* perform USCS-to-SSP reduction */
232 
233  ssp_instance_evaluation<libff::Fr<ppT>> ssp_inst =
234  uscs_to_ssp_instance_map_with_evaluation(cs, t);
235 
236  libff::print_indent();
237  printf("* SSP number of variables: %zu\n", ssp_inst.num_variables());
238  libff::print_indent();
239  printf("* SSP pre degree: %zu\n", cs.num_constraints());
240  libff::print_indent();
241  printf("* SSP degree: %zu\n", ssp_inst.degree());
242  libff::print_indent();
243  printf("* SSP number of input variables: %zu\n", ssp_inst.num_inputs());
244 
245  /* construct various tables of FieldT elements */
246 
247  libff::Fr_vector<ppT> Vt_table =
248  std::move(ssp_inst.Vt); // ssp_inst.Vt is now in unspecified state, but
249  // we do not use it later
250  libff::Fr_vector<ppT> Ht_table =
251  std::move(ssp_inst.Ht); // ssp_inst.Ht is now in unspecified state, but
252  // we do not use it later
253 
254  Vt_table.emplace_back(ssp_inst.Zt);
255 
256  libff::Fr_vector<ppT> Xt_table = libff::Fr_vector<ppT>(
257  Vt_table.begin(), Vt_table.begin() + ssp_inst.num_inputs() + 1);
258  libff::Fr_vector<ppT> Vt_table_minus_Xt_table = libff::Fr_vector<ppT>(
259  Vt_table.begin() + ssp_inst.num_inputs() + 1, Vt_table.end());
260 
261  /* sanity checks */
262 
263  assert(Vt_table.size() == ssp_inst.num_variables() + 2);
264  printf(
265  "Ht_table.size() = %zu, ssp_inst.degree() + 1 = %zu\n",
266  Ht_table.size(),
267  ssp_inst.degree() + 1);
268  assert(Ht_table.size() == ssp_inst.degree() + 1);
269  assert(Xt_table.size() == ssp_inst.num_inputs() + 1);
270  assert(
271  Vt_table_minus_Xt_table.size() ==
272  ssp_inst.num_variables() + 2 - ssp_inst.num_inputs() - 1);
273  for (size_t i = 0; i < ssp_inst.num_inputs() + 1; ++i) {
274  assert(!Xt_table[i].is_zero());
275  }
276 
277  const libff::Fr<ppT> alpha = libff::Fr<ppT>::random_element();
278 
279  libff::enter_block("Generate USCS proving key");
280 
281  const size_t g1_exp_count =
282  Vt_table.size() + Vt_table_minus_Xt_table.size() + Ht_table.size();
283  const size_t g2_exp_count = Vt_table_minus_Xt_table.size();
284 
285  size_t g1_window = libff::get_exp_window_size<libff::G1<ppT>>(g1_exp_count);
286  size_t g2_window = libff::get_exp_window_size<libff::G2<ppT>>(g2_exp_count);
287 
288  libff::print_indent();
289  printf("* G1 window: %zu\n", g1_window);
290  libff::print_indent();
291  printf("* G2 window: %zu\n", g2_window);
292 
293  libff::enter_block("Generating G1 multiexp table");
294  libff::window_table<libff::G1<ppT>> g1_table = get_window_table(
295  libff::Fr<ppT>::size_in_bits(), g1_window, libff::G1<ppT>::one());
296  libff::leave_block("Generating G1 multiexp table");
297 
298  libff::enter_block("Generating G2 multiexp table");
299  libff::window_table<libff::G2<ppT>> g2_table = get_window_table(
300  libff::Fr<ppT>::size_in_bits(), g2_window, libff::G2<ppT>::one());
301  libff::leave_block("Generating G2 multiexp table");
302 
303  libff::enter_block("Generate proof components");
304 
305  libff::enter_block("Compute the query for V_g1", false);
306  libff::G1_vector<ppT> V_g1_query = batch_exp(
307  libff::Fr<ppT>::size_in_bits(),
308  g1_window,
309  g1_table,
310  Vt_table_minus_Xt_table);
311  if (BaseForm == libff::multi_exp_base_form_special) {
312  libff::batch_to_special<libff::G1<ppT>>(V_g1_query);
313  }
314  libff::leave_block("Compute the query for V_g1", false);
315 
316  libff::enter_block("Compute the query for alpha_V_g1", false);
317  libff::G1_vector<ppT> alpha_V_g1_query = batch_exp_with_coeff(
318  libff::Fr<ppT>::size_in_bits(),
319  g1_window,
320  g1_table,
321  alpha,
322  Vt_table_minus_Xt_table);
323  if (BaseForm == libff::multi_exp_base_form_special) {
324  libff::batch_to_special<libff::G1<ppT>>(alpha_V_g1_query);
325  }
326  libff::leave_block("Compute the query for alpha_V_g1", false);
327 
328  libff::enter_block("Compute the query for H_g1", false);
329  libff::G1_vector<ppT> H_g1_query = batch_exp(
330  libff::Fr<ppT>::size_in_bits(), g1_window, g1_table, Ht_table);
331  if (BaseForm == libff::multi_exp_base_form_special) {
332  libff::batch_to_special<libff::G1<ppT>>(H_g1_query);
333  }
334  libff::leave_block("Compute the query for H_g1", false);
335 
336  libff::enter_block("Compute the query for V_g2", false);
337  libff::G2_vector<ppT> V_g2_query = batch_exp(
338  libff::Fr<ppT>::size_in_bits(), g2_window, g2_table, Vt_table);
339  if (BaseForm == libff::multi_exp_base_form_special) {
340  libff::batch_to_special<libff::G2<ppT>>(V_g2_query);
341  }
342  libff::leave_block("Compute the query for V_g2", false);
343 
344  libff::leave_block("Generate proof components");
345 
346  libff::leave_block("Generate USCS proving key");
347 
348  libff::enter_block("Generate USCS verification key");
349 
350  const libff::Fr<ppT> tilde = libff::Fr<ppT>::random_element();
351  libff::G2<ppT> tilde_g2 = tilde * libff::G2<ppT>::one();
352  libff::G2<ppT> alpha_tilde_g2 = (alpha * tilde) * libff::G2<ppT>::one();
353  libff::G2<ppT> Z_g2 = ssp_inst.Zt * libff::G2<ppT>::one();
354 
355  libff::enter_block("Encode IC query for USCS verification key");
356  libff::G1<ppT> encoded_IC_base = Xt_table[0] * libff::G1<ppT>::one();
357  libff::G1_vector<ppT> encoded_IC_values = batch_exp(
358  libff::Fr<ppT>::size_in_bits(),
359  g1_window,
360  g1_table,
361  libff::Fr_vector<ppT>(Xt_table.begin() + 1, Xt_table.end()));
362  libff::leave_block("Encode IC query for USCS verification key");
363 
364  libff::leave_block("Generate USCS verification key");
365 
366  libff::leave_block("Call to uscs_ppzksnark_generator");
367 
368  accumulation_vector<libff::G1<ppT>> encoded_IC_query(
369  std::move(encoded_IC_base), std::move(encoded_IC_values));
370 
371  uscs_ppzksnark_verification_key<ppT> vk =
372  uscs_ppzksnark_verification_key<ppT>(
373  tilde_g2, alpha_tilde_g2, Z_g2, encoded_IC_query);
374 
375  uscs_ppzksnark_constraint_system<ppT> cs_copy = cs;
376  uscs_ppzksnark_proving_key<ppT> pk = uscs_ppzksnark_proving_key<ppT>(
377  std::move(V_g1_query),
378  std::move(alpha_V_g1_query),
379  std::move(H_g1_query),
380  std::move(V_g2_query),
381  std::move(cs_copy));
382 
383  pk.print_size();
384  vk.print_size();
385 
386  return uscs_ppzksnark_keypair<ppT>(std::move(pk), std::move(vk));
387 }
388 
389 template<
390  typename ppT,
391  libff::multi_exp_method Method,
392  libff::multi_exp_base_form BaseForm>
393 uscs_ppzksnark_proof<ppT> uscs_ppzksnark_prover(
394  const uscs_ppzksnark_proving_key<ppT> &pk,
395  const uscs_ppzksnark_primary_input<ppT> &primary_input,
396  const uscs_ppzksnark_auxiliary_input<ppT> &auxiliary_input)
397 {
398  libff::enter_block("Call to uscs_ppzksnark_prover");
399 
400  const libff::Fr<ppT> d = libff::Fr<ppT>::random_element();
401 
402  libff::enter_block("Compute the polynomial H");
403  const ssp_witness<libff::Fr<ppT>> ssp_wit = uscs_to_ssp_witness_map(
404  pk.constraint_system, primary_input, auxiliary_input, d);
405  libff::leave_block("Compute the polynomial H");
406 
407  /* sanity checks */
408  assert(pk.constraint_system.is_satisfied(primary_input, auxiliary_input));
409  assert(
410  pk.V_g1_query.size() ==
411  ssp_wit.num_variables() + 2 - ssp_wit.num_inputs() - 1);
412  assert(
413  pk.alpha_V_g1_query.size() ==
414  ssp_wit.num_variables() + 2 - ssp_wit.num_inputs() - 1);
415  assert(pk.H_g1_query.size() == ssp_wit.degree() + 1);
416  assert(pk.V_g2_query.size() == ssp_wit.num_variables() + 2);
417 
418 #ifdef DEBUG
419  const libff::Fr<ppT> t = libff::Fr<ppT>::random_element();
420  ssp_instance_evaluation<libff::Fr<ppT>> ssp_inst =
421  uscs_to_ssp_instance_map_with_evaluation(pk.constraint_system, t);
422  assert(ssp_inst.is_satisfied(ssp_wit));
423 #endif
424 
425  libff::G1<ppT> V_g1 = ssp_wit.d * pk.V_g1_query[pk.V_g1_query.size() - 1];
426  libff::G1<ppT> alpha_V_g1 =
427  ssp_wit.d * pk.alpha_V_g1_query[pk.alpha_V_g1_query.size() - 1];
428  libff::G1<ppT> H_g1 = libff::G1<ppT>::zero();
429  libff::G2<ppT> V_g2 =
430  pk.V_g2_query[0] + ssp_wit.d * pk.V_g2_query[pk.V_g2_query.size() - 1];
431 
432 #ifdef MULTICORE
433  const size_t chunks =
434  omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or
435  // call omp_set_num_threads()
436 #else
437  const size_t chunks = 1;
438 #endif
439 
440  // MAYBE LATER: do queries 1,2,4 at once for slightly better speed
441 
442  libff::enter_block("Compute the proof");
443 
444  libff::enter_block("Compute V_g1, the 1st component of the proof", false);
445  V_g1 = V_g1 +
446  libff::multi_exp_filter_one_zero<
447  libff::G1<ppT>,
448  libff::Fr<ppT>,
449  Method,
450  BaseForm>(
451  pk.V_g1_query.begin(),
452  pk.V_g1_query.begin() +
453  (ssp_wit.num_variables() - ssp_wit.num_inputs()),
454  ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_inputs(),
455  ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_variables(),
456  chunks);
457  libff::leave_block("Compute V_g1, the 1st component of the proof", false);
458 
459  libff::enter_block(
460  "Compute alpha_V_g1, the 2nd component of the proof", false);
461  alpha_V_g1 =
462  alpha_V_g1 +
463  libff::multi_exp_filter_one_zero<
464  libff::G1<ppT>,
465  libff::Fr<ppT>,
466  Method,
467  BaseForm>(
468  pk.alpha_V_g1_query.begin(),
469  pk.alpha_V_g1_query.begin() +
470  (ssp_wit.num_variables() - ssp_wit.num_inputs()),
471  ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_inputs(),
472  ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_variables(),
473  chunks);
474  libff::leave_block(
475  "Compute alpha_V_g1, the 2nd component of the proof", false);
476 
477  libff::enter_block("Compute H_g1, the 3rd component of the proof", false);
478  H_g1 = H_g1 +
479  libff::multi_exp<libff::G1<ppT>, libff::Fr<ppT>, Method, BaseForm>(
480  pk.H_g1_query.begin(),
481  pk.H_g1_query.begin() + ssp_wit.degree() + 1,
482  ssp_wit.coefficients_for_H.begin(),
483  ssp_wit.coefficients_for_H.begin() + ssp_wit.degree() + 1,
484  chunks);
485  libff::leave_block("Compute H_g1, the 3rd component of the proof", false);
486 
487  libff::enter_block("Compute V_g2, the 4th component of the proof", false);
488  V_g2 = V_g2 +
489  libff::multi_exp<libff::G2<ppT>, libff::Fr<ppT>, Method, BaseForm>(
490  pk.V_g2_query.begin() + 1,
491  pk.V_g2_query.begin() + ssp_wit.num_variables() + 1,
492  ssp_wit.coefficients_for_Vs.begin(),
493  ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_variables(),
494  chunks);
495  libff::leave_block("Compute V_g2, the 4th component of the proof", false);
496 
497  libff::leave_block("Compute the proof");
498 
499  libff::leave_block("Call to uscs_ppzksnark_prover");
500 
501  uscs_ppzksnark_proof<ppT> proof = uscs_ppzksnark_proof<ppT>(
502  std::move(V_g1),
503  std::move(alpha_V_g1),
504  std::move(H_g1),
505  std::move(V_g2));
506 
507  proof.print_size();
508 
509  return proof;
510 }
511 
512 template<typename ppT>
513 uscs_ppzksnark_processed_verification_key<ppT> uscs_ppzksnark_verifier_process_vk(
514  const uscs_ppzksnark_verification_key<ppT> &vk)
515 {
516  libff::enter_block("Call to uscs_ppzksnark_verifier_process_vk");
517 
518  uscs_ppzksnark_processed_verification_key<ppT> pvk;
519 
520  pvk.pp_G1_one_precomp = ppT::precompute_G1(libff::G1<ppT>::one());
521  pvk.pp_G2_one_precomp = ppT::precompute_G2(libff::G2<ppT>::one());
522 
523  pvk.vk_tilde_g2_precomp = ppT::precompute_G2(vk.tilde_g2);
524  pvk.vk_alpha_tilde_g2_precomp = ppT::precompute_G2(vk.alpha_tilde_g2);
525  pvk.vk_Z_g2_precomp = ppT::precompute_G2(vk.Z_g2);
526 
527  pvk.pairing_of_g1_and_g2 =
528  ppT::miller_loop(pvk.pp_G1_one_precomp, pvk.pp_G2_one_precomp);
529 
530  pvk.encoded_IC_query = vk.encoded_IC_query;
531 
532  libff::leave_block("Call to uscs_ppzksnark_verifier_process_vk");
533 
534  return pvk;
535 }
536 
537 template<typename ppT>
538 bool uscs_ppzksnark_online_verifier_weak_IC(
539  const uscs_ppzksnark_processed_verification_key<ppT> &pvk,
540  const uscs_ppzksnark_primary_input<ppT> &primary_input,
541  const uscs_ppzksnark_proof<ppT> &proof)
542 {
543  libff::enter_block("Call to uscs_ppzksnark_online_verifier_weak_IC");
544  assert(pvk.encoded_IC_query.domain_size() >= primary_input.size());
545 
546  libff::enter_block("Compute input-dependent part of V");
547  const accumulation_vector<libff::G1<ppT>> accumulated_IC =
548  pvk.encoded_IC_query.template accumulate_chunk<libff::Fr<ppT>>(
549  primary_input.begin(), primary_input.end(), 0);
550  assert(accumulated_IC.is_fully_accumulated());
551  const libff::G1<ppT> &acc = accumulated_IC.first;
552  libff::leave_block("Compute input-dependent part of V");
553 
554  bool result = true;
555 
556  libff::enter_block("Check if the proof is well-formed");
557  if (!proof.is_well_formed()) {
558  if (!libff::inhibit_profiling_info) {
559  libff::print_indent();
560  printf(
561  "At least one of the proof components is not well-formed.\n");
562  }
563  result = false;
564  }
565  libff::leave_block("Check if the proof is well-formed");
566 
567  libff::enter_block("Online pairing computations");
568 
569  libff::enter_block("Check knowledge commitment for V is valid");
570  libff::G1_precomp<ppT> proof_V_g1_with_acc_precomp =
571  ppT::precompute_G1(proof.V_g1 + acc);
572  libff::G2_precomp<ppT> proof_V_g2_precomp = ppT::precompute_G2(proof.V_g2);
573  libff::Fqk<ppT> V_1 =
574  ppT::miller_loop(proof_V_g1_with_acc_precomp, pvk.pp_G2_one_precomp);
575  libff::Fqk<ppT> V_2 =
576  ppT::miller_loop(pvk.pp_G1_one_precomp, proof_V_g2_precomp);
577  libff::GT<ppT> V = ppT::final_exponentiation(V_1 * V_2.unitary_inverse());
578  if (V != libff::GT<ppT>::one()) {
579  if (!libff::inhibit_profiling_info) {
580  libff::print_indent();
581  printf("Knowledge commitment for V invalid.\n");
582  }
583  result = false;
584  }
585  libff::leave_block("Check knowledge commitment for V is valid");
586 
587  libff::enter_block("Check SSP divisibility"); // i.e., check that V^2=H*Z+1
588  libff::G1_precomp<ppT> proof_H_g1_precomp = ppT::precompute_G1(proof.H_g1);
589  libff::Fqk<ppT> SSP_1 =
590  ppT::miller_loop(proof_V_g1_with_acc_precomp, proof_V_g2_precomp);
591  libff::Fqk<ppT> SSP_2 =
592  ppT::miller_loop(proof_H_g1_precomp, pvk.vk_Z_g2_precomp);
593  libff::GT<ppT> SSP = ppT::final_exponentiation(
594  SSP_1.unitary_inverse() * SSP_2 * pvk.pairing_of_g1_and_g2);
595  if (SSP != libff::GT<ppT>::one()) {
596  if (!libff::inhibit_profiling_info) {
597  libff::print_indent();
598  printf("SSP divisibility check failed.\n");
599  }
600  result = false;
601  }
602  libff::leave_block("Check SSP divisibility");
603 
604  libff::enter_block("Check same coefficients were used");
605  libff::G1_precomp<ppT> proof_V_g1_precomp = ppT::precompute_G1(proof.V_g1);
606  libff::G1_precomp<ppT> proof_alpha_V_g1_precomp =
607  ppT::precompute_G1(proof.alpha_V_g1);
608  libff::Fqk<ppT> alpha_V_1 =
609  ppT::miller_loop(proof_V_g1_precomp, pvk.vk_alpha_tilde_g2_precomp);
610  libff::Fqk<ppT> alpha_V_2 =
611  ppT::miller_loop(proof_alpha_V_g1_precomp, pvk.vk_tilde_g2_precomp);
612  libff::GT<ppT> alpha_V =
613  ppT::final_exponentiation(alpha_V_1 * alpha_V_2.unitary_inverse());
614  if (alpha_V != libff::GT<ppT>::one()) {
615  if (!libff::inhibit_profiling_info) {
616  libff::print_indent();
617  printf("Same-coefficient check failed.\n");
618  }
619  result = false;
620  }
621  libff::leave_block("Check same coefficients were used");
622 
623  libff::leave_block("Online pairing computations");
624 
625  libff::leave_block("Call to uscs_ppzksnark_online_verifier_weak_IC");
626 
627  return result;
628 }
629 
630 template<typename ppT>
631 bool uscs_ppzksnark_verifier_weak_IC(
632  const uscs_ppzksnark_verification_key<ppT> &vk,
633  const uscs_ppzksnark_primary_input<ppT> &primary_input,
634  const uscs_ppzksnark_proof<ppT> &proof)
635 {
636  libff::enter_block("Call to uscs_ppzksnark_verifier_weak_IC");
637  uscs_ppzksnark_processed_verification_key<ppT> pvk =
638  uscs_ppzksnark_verifier_process_vk<ppT>(vk);
639  bool result =
640  uscs_ppzksnark_online_verifier_weak_IC<ppT>(pvk, primary_input, proof);
641  libff::leave_block("Call to uscs_ppzksnark_verifier_weak_IC");
642  return result;
643 }
644 
645 template<typename ppT>
646 bool uscs_ppzksnark_online_verifier_strong_IC(
647  const uscs_ppzksnark_processed_verification_key<ppT> &pvk,
648  const uscs_ppzksnark_primary_input<ppT> &primary_input,
649  const uscs_ppzksnark_proof<ppT> &proof)
650 {
651  bool result = true;
652  libff::enter_block("Call to uscs_ppzksnark_online_verifier_strong_IC");
653 
654  if (pvk.encoded_IC_query.domain_size() != primary_input.size()) {
655  libff::print_indent();
656  printf(
657  "Input length differs from expected (got %zu, expected %zu).\n",
658  primary_input.size(),
659  pvk.encoded_IC_query.domain_size());
660  result = false;
661  } else {
662  result =
663  uscs_ppzksnark_online_verifier_weak_IC(pvk, primary_input, proof);
664  }
665 
666  libff::leave_block("Call to uscs_ppzksnark_online_verifier_strong_IC");
667  return result;
668 }
669 
670 template<typename ppT>
671 bool uscs_ppzksnark_verifier_strong_IC(
672  const uscs_ppzksnark_verification_key<ppT> &vk,
673  const uscs_ppzksnark_primary_input<ppT> &primary_input,
674  const uscs_ppzksnark_proof<ppT> &proof)
675 {
676  libff::enter_block("Call to uscs_ppzksnark_verifier_strong_IC");
677  uscs_ppzksnark_processed_verification_key<ppT> pvk =
678  uscs_ppzksnark_verifier_process_vk<ppT>(vk);
679  bool result = uscs_ppzksnark_online_verifier_strong_IC<ppT>(
680  pvk, primary_input, proof);
681  libff::leave_block("Call to uscs_ppzksnark_verifier_strong_IC");
682  return result;
683 }
684 
685 } // namespace libsnark
686 
687 #endif // USCS_PPZKSNARK_TCC_