zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
4 // Copyright (c) 2020-2021 Ilias Khairullin <ilias@nil.foundation>
5 //
6 // MIT License
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 //---------------------------------------------------------------------------//
26 
27 #ifndef CRYPTO3_R1CS_GG_PPZKSNARK_IPP2_VERIFY_HPP
28 #define CRYPTO3_R1CS_GG_PPZKSNARK_IPP2_VERIFY_HPP
29 
32 
34 
38 
39 namespace nil {
40  namespace crypto3 {
41  namespace zk {
42  namespace snark {
46  template<typename CurveType>
47  class gipa_tuz {
48  typedef CurveType curve_type;
49  using g1_type = typename curve_type::template g1_type<>;
50 
51  public:
52  typename curve_type::gt_type::value_type tab;
53  typename curve_type::gt_type::value_type uab;
54  typename curve_type::gt_type::value_type zab;
55  typename curve_type::gt_type::value_type tc;
56  typename curve_type::gt_type::value_type uc;
57  typename g1_type::value_type zc;
58 
59  inline gipa_tuz() :
60  tab(curve_type::gt_type::value_type::one()), uab(curve_type::gt_type::value_type::one()),
61  zab(curve_type::gt_type::value_type::one()), tc(curve_type::gt_type::value_type::one()),
62  uc(curve_type::gt_type::value_type::one()), zc(g1_type::value_type::zero()) {
63  }
64 
65  inline gipa_tuz(const typename curve_type::gt_type::value_type &tab,
66  const typename curve_type::gt_type::value_type &uab,
67  const typename curve_type::gt_type::value_type &zab,
68  const typename curve_type::gt_type::value_type &tc,
69  const typename curve_type::gt_type::value_type &uc,
70  const typename g1_type::value_type &zc) :
71  tab(tab),
72  uab(uab), zab(zab), tc(tc), uc(uc), zc(zc) {
73  }
74 
75  inline void merge(const gipa_tuz &other) {
76  tab = tab * other.tab;
77  uab = uab * other.uab;
78  zab = zab * other.zab;
79  tc = tc * other.tc;
80  uc = uc * other.uc;
81  zc = zc + other.zc;
82  }
83  };
84 
95  template<typename CurveType, typename DistributionType, typename GeneratorType>
96  struct pairing_check {
97  typedef CurveType curve_type;
98 
99  typedef typename curve_type::template g1_type<> g1_type;
100  typedef typename curve_type::template g2_type<> g2_type;
101  typedef typename curve_type::gt_type gt_type;
102  typedef typename curve_type::scalar_field_type scalar_field_type;
103 
104  typedef typename g1_type::value_type g1_value_type;
105  typedef typename g2_type::value_type g2_value_type;
106  typedef typename gt_type::value_type gt_value_type;
107  typedef typename scalar_field_type::value_type scalar_field_value_type;
108 
112  bool valid;
113 
114  inline pairing_check() :
116  valid(true) {
117  }
118 
127  template<typename InputG1Iterator, typename InputG2Iterator,
128  typename = typename std::enable_if<
129  std::is_same<g1_value_type,
130  typename std::iterator_traits<InputG1Iterator>::value_type>::value &&
131  std::is_same<g2_value_type,
132  typename std::iterator_traits<InputG2Iterator>::value_type>::value,
133  bool>::type>
134  inline pairing_check(InputG1Iterator a_first, InputG1Iterator a_last, InputG2Iterator b_first,
135  InputG2Iterator b_last, const gt_value_type &out) :
136  left(gt_value_type::one()),
137  right(gt_value_type::one()), non_random_check_done(false), valid(true) {
138  merge_random(a_first, a_last, b_first, b_last, out);
139  }
140 
141  void merge() {
142  }
143 
144  template<typename InputG1Iterator, typename InputG2Iterator>
145  inline typename std::enable_if<
146  std::is_same<g1_value_type,
147  typename std::iterator_traits<InputG1Iterator>::value_type>::value &&
148  std::is_same<g2_value_type,
149  typename std::iterator_traits<InputG2Iterator>::value_type>::value>::type
150  merge_random(InputG1Iterator a_first, InputG1Iterator a_last, InputG2Iterator b_first,
151  InputG2Iterator b_last, const gt_value_type &out) {
152  std::size_t len = std::distance(a_first, a_last);
153  BOOST_ASSERT(len > 0);
154  BOOST_ASSERT(len == std::distance(b_first, b_last));
155 
156  if (!valid) {
157  return;
158  }
159 
161  std::for_each(boost::make_zip_iterator(boost::make_tuple(a_first, b_first)),
162  boost::make_zip_iterator(boost::make_tuple(a_last, b_last)),
163  [&](const boost::tuple<const g1_value_type &, const g2_value_type &> &t) {
164  left = left * algebra::pair<curve_type>(coeff * t.template get<0>(),
165  t.template get<1>());
166  });
167  right = right * (out == CurveType::gt_type::value_type::one() ? out : out.pow(coeff.data));
168  }
169 
170  template<typename InputGTIterator>
171  inline typename std::enable_if<std::is_same<
172  gt_value_type, typename std::iterator_traits<InputGTIterator>::value_type>::value>::type
173  merge_nonrandom(InputGTIterator a_first, InputGTIterator a_last, const gt_value_type &out) {
174  BOOST_ASSERT(!non_random_check_done);
175  BOOST_ASSERT(std::distance(a_first, a_last) > 0);
176 
177  if (!valid) {
178  return;
179  }
180 
181  for (auto a_it = a_first; a_it != a_last; ++a_it) {
182  left = left * (*a_it);
183  }
184  right = right * out;
185 
186  non_random_check_done = true;
187  }
188 
189  inline bool verify() {
190  return valid && (algebra::final_exponentiation<curve_type>(left) == right);
191  }
192 
195  algebra::random_element<scalar_field_type, DistributionType, GeneratorType>();
196  while (coeff.is_zero()) {
197  coeff = algebra::random_element<scalar_field_type, DistributionType, GeneratorType>();
198  }
199  return coeff;
200  }
201 
202  inline void invalidate() {
203  valid = false;
204  }
205  };
206 
210  template<typename CurveType, typename DistributionType, typename GeneratorType,
211  typename InputScalarIterator>
212  inline typename std::enable_if<
213  std::is_same<typename CurveType::scalar_field_type::value_type,
214  typename std::iterator_traits<InputScalarIterator>::value_type>::value>::type
216  const std::pair<typename CurveType::template g2_type<>::value_type,
217  typename CurveType::template g2_type<>::value_type> &final_vkey,
218  const kzg_opening<typename CurveType::template g2_type<>> &vkey_opening,
219  InputScalarIterator challenges_first, InputScalarIterator challenges_last,
220  const typename CurveType::scalar_field_type::value_type &kzg_challenge,
222  // f_v(z)
223  typename CurveType::scalar_field_type::value_type vpoly_eval_z =
224  polynomial_evaluation_product_form_from_transcript<typename CurveType::scalar_field_type>(
225  challenges_first, challenges_last, kzg_challenge,
226  CurveType::scalar_field_type::value_type::one());
227 
228  // TODO:: parallel
229  // -g such that when we test a pairing equation we only need to check if
230  // it's equal 1 at the end:
231  // e(a,b) = e(c,d) <=> e(a,b)e(-c,d) = 1
232  // e(A,B) = e(C,D) <=> e(A,B)e(-C,D) == 1 <=> e(A,B)e(C,D)^-1 == 1
233  // verify first part of opening - v1
234  // e(-g, v1-(f_v(z)}*h)) ==> e(g^-1,h^{f_v(a)} * h^{-f_v(z)})
235  // e(g^{a - z}, opening_1) ==> e(g^{a-z}, h^q(a))
236  std::vector<typename CurveType::template g1_type<>::value_type> a_input1 {
237  -v_srs.g,
238  v_srs.g_alpha - (v_srs.g * kzg_challenge),
239  };
240  std::vector<typename CurveType::template g2_type<>::value_type> b_input1 {
241  // in additive notation: final_vkey = uH,
242  // uH - f_v(z)H = (u - f_v)H --> v1h^{-af_v(z)}
243  final_vkey.first - (v_srs.h * vpoly_eval_z),
244  vkey_opening.first,
245  };
246  pc.merge_random(a_input1.begin(), a_input1.end(), b_input1.begin(), b_input1.end(),
247  CurveType::gt_type::value_type::one());
248 
249  // verify second part of opening - v2 - similar but changing secret exponent
250  // e(g, v2 h^{-bf_v(z)})
251  std::vector<typename CurveType::template g1_type<>::value_type> a_input2 {
252  -v_srs.g,
253  v_srs.g_beta - (v_srs.g * kzg_challenge),
254  };
255  std::vector<typename CurveType::template g2_type<>::value_type> b_input2 {
256  // in additive notation: final_vkey = uH,
257  // uH - f_v(z)H = (u - f_v)H --> v1h^{-f_v(z)}
258  final_vkey.second - (v_srs.h * vpoly_eval_z),
259  vkey_opening.second,
260  };
261  pc.merge_random(a_input2.begin(), a_input2.end(), b_input2.begin(), b_input2.end(),
262  CurveType::gt_type::value_type::one());
263  }
264 
266  template<typename CurveType, typename DistributionType, typename GeneratorType,
267  typename InputScalarIterator>
268  inline typename std::enable_if<
269  std::is_same<typename CurveType::scalar_field_type::value_type,
270  typename std::iterator_traits<InputScalarIterator>::value_type>::value>::type
272  const std::pair<typename CurveType::template g1_type<>::value_type,
273  typename CurveType::template g1_type<>::value_type> &final_wkey,
274  const kzg_opening<typename CurveType::template g1_type<>> &wkey_opening,
275  InputScalarIterator challenges_first, InputScalarIterator challenges_last,
276  const typename CurveType::scalar_field_type::value_type &r_shift,
277  const typename CurveType::scalar_field_type::value_type &kzg_challenge,
279  // TODO: parallel
280  // compute in parallel f(z) and z^n and then combines into f_w(z) = z^n * f(z)
281  typename CurveType::scalar_field_type::value_type fwz =
282  polynomial_evaluation_product_form_from_transcript<typename CurveType::scalar_field_type>(
283  challenges_first, challenges_last, kzg_challenge, r_shift) *
284  kzg_challenge.pow(v_srs.n);
285 
286  // TODO: parallel
287  // first check on w1
288  // e(w_1 / g^{f_w(z)},h) == e(\pi_{w,1},h^a/h^z) \\
289  // e(g^{f_w(a) - f_w(z)},
290  std::vector<typename CurveType::template g1_type<>::value_type> a_input1 {
291  final_wkey.first - (v_srs.g * fwz),
292  // e(opening, h^{a - z})
293  wkey_opening.first,
294  };
295  std::vector<typename CurveType::template g2_type<>::value_type> b_input1 {
296  -v_srs.h,
297  v_srs.h_alpha - (v_srs.h * kzg_challenge),
298  };
299  pc.merge_random(a_input1.begin(), a_input1.end(), b_input1.begin(), b_input1.end(),
300  CurveType::gt_type::value_type::one());
301 
302  // then do second check
303  // e(w_2 / g^{f_w(z)},h) == e(\pi_{w,2},h^b/h^z)
304  std::vector<typename CurveType::template g1_type<>::value_type> a_input2 {
305  final_wkey.second - (v_srs.g * fwz),
306  wkey_opening.second,
307  };
308  std::vector<typename CurveType::template g2_type<>::value_type> b_input2 {
309  -v_srs.h,
310  v_srs.h_beta - (v_srs.h * kzg_challenge),
311  };
312  pc.merge_random(a_input2.begin(), a_input2.end(), b_input2.begin(), b_input2.end(),
313  CurveType::gt_type::value_type::one());
314  }
315 
325  template<typename CurveType, typename Hash = hashes::sha2<256>>
326  inline std::tuple<gipa_tuz<CurveType>, typename CurveType::scalar_field_type::value_type,
327  std::vector<typename CurveType::scalar_field_type::value_type>,
328  std::vector<typename CurveType::scalar_field_type::value_type>>
331  const typename CurveType::scalar_field_type::value_type &r_shift) {
332  std::vector<typename CurveType::scalar_field_type::value_type> challenges;
333  std::vector<typename CurveType::scalar_field_type::value_type> challenges_inv;
334 
335  constexpr std::array<std::uint8_t, 4> domain_separator = {'g', 'i', 'p', 'a'};
336  tr.write_domain_separator(domain_separator.begin(), domain_separator.end());
337 
338  // We first generate all challenges as this is the only consecutive process
339  // that can not be parallelized then we scale the commitments in a
340  // parallelized way
341  std::for_each(
342  boost::make_zip_iterator(
343  boost::make_tuple(proof.tmipp.gipa.comms_ab.begin(), proof.tmipp.gipa.z_ab.begin(),
344  proof.tmipp.gipa.comms_c.begin(), proof.tmipp.gipa.z_c.begin())),
345  boost::make_zip_iterator(
346  boost::make_tuple(proof.tmipp.gipa.comms_ab.end(), proof.tmipp.gipa.z_ab.end(),
347  proof.tmipp.gipa.comms_c.end(), proof.tmipp.gipa.z_c.end())),
350  const std::pair<typename CurveType::gt_type::value_type,
351  typename CurveType::gt_type::value_type> &,
354  const std::pair<typename CurveType::template g1_type<>::value_type,
355  typename CurveType::template g1_type<>::value_type> &>
356  &t) {
357  // .write(&zab_l)
358  tr.template write<typename CurveType::gt_type>(t.template get<1>().first);
359  // .write(&zab_r)
360  tr.template write<typename CurveType::gt_type>(t.template get<1>().second);
361  // .write(&zc_l)
362  tr.template write<typename CurveType::template g1_type<>>(t.template get<3>().first);
363  // .write(&zc_r)
364  tr.template write<typename CurveType::template g1_type<>>(t.template get<3>().second);
365  // .write(&tab_l.0)
366  tr.template write<typename CurveType::gt_type>(t.template get<0>().first.first);
367  // .write(&tab_l.1)
368  tr.template write<typename CurveType::gt_type>(t.template get<0>().first.second);
369  // .write(&tab_r.0)
370  tr.template write<typename CurveType::gt_type>(t.template get<0>().second.first);
371  // .write(&tab_r.1)
372  tr.template write<typename CurveType::gt_type>(t.template get<0>().second.second);
373  // .write(&tc_l.0)
374  tr.template write<typename CurveType::gt_type>(t.template get<2>().first.first);
375  // .write(&tc_l.1)
376  tr.template write<typename CurveType::gt_type>(t.template get<2>().first.second);
377  // .write(&tc_r.0)
378  tr.template write<typename CurveType::gt_type>(t.template get<2>().second.first);
379  // .write(&tc_r.1)
380  tr.template write<typename CurveType::gt_type>(t.template get<2>().second.second);
381  challenges_inv.emplace_back(tr.read_challenge());
382  challenges.emplace_back(challenges_inv.back().inversed());
383  });
384 
385  gipa_tuz<CurveType> final_res {// output of the pair commitment T and U in TIPP -> COM((v,w),A,B)
386  proof.com_ab.first, proof.com_ab.second,
387  // in the end must be equal to Z = A^r * B
388  proof.ip_ab,
389  // COM(v,C)
390  proof.com_c.first, proof.com_c.second,
391  // in the end must be equal to Z = C^r
392  proof.agg_c};
393 
394  // we first multiply each entry of the Z U and L vectors by the respective
395  // challenges independently
396  // Since at the end we want to multiple all "t" values together, we do
397  // multiply all of them in parrallel and then merge then back at the end.
398  // same for u and z.
400  std::for_each(
401  boost::make_zip_iterator(
402  boost::make_tuple(proof.tmipp.gipa.comms_ab.begin(), proof.tmipp.gipa.z_ab.begin(),
403  proof.tmipp.gipa.comms_c.begin(), proof.tmipp.gipa.z_c.begin(),
404  challenges.begin(), challenges_inv.begin())),
405  boost::make_zip_iterator(
406  boost::make_tuple(proof.tmipp.gipa.comms_ab.end(), proof.tmipp.gipa.z_ab.end(),
407  proof.tmipp.gipa.comms_c.end(), proof.tmipp.gipa.z_c.end(),
408  challenges.end(), challenges_inv.end())),
411  const std::pair<typename CurveType::gt_type::value_type,
412  typename CurveType::gt_type::value_type> &,
415  const std::pair<typename CurveType::template g1_type<>::value_type,
416  typename CurveType::template g1_type<>::value_type> &,
417  const typename CurveType::scalar_field_type::value_type &,
418  const typename CurveType::scalar_field_type::value_type &> &t) {
419  // Op::TAB::<E>(tab_l, c_repr),
420  res.tab = res.tab * t.template get<0>().first.first.pow(t.template get<4>().data);
421  // Op::TAB(tab_r, c_inv_repr),
422  res.tab = res.tab * t.template get<0>().second.first.pow(t.template get<5>().data);
423  // Op::UAB(uab_l, c_repr),
424  res.uab = res.uab * t.template get<0>().first.second.pow(t.template get<4>().data);
425  // Op::UAB(uab_r, c_inv_repr),
426  res.uab = res.uab * t.template get<0>().second.second.pow(t.template get<5>().data);
427  // Op::ZAB(zab_l, c_repr),
428  res.zab = res.zab * t.template get<1>().first.pow(t.template get<4>().data);
429  // Op::ZAB(zab_r, c_inv_repr),
430  res.zab = res.zab * t.template get<1>().second.pow(t.template get<5>().data);
431  // Op::TC::<E>(tc_l, c_repr),
432  res.tc = res.tc * t.template get<2>().first.first.pow(t.template get<4>().data);
433  // Op::TC(tc_r, c_inv_repr),
434  res.tc = res.tc * t.template get<2>().second.first.pow(t.template get<5>().data);
435  // Op::UC(uc_l, c_repr),
436  res.uc = res.uc * t.template get<2>().first.second.pow(t.template get<4>().data);
437  // Op::UC(uc_r, c_inv_repr),
438  res.uc = res.uc * t.template get<2>().second.second.pow(t.template get<5>().data);
439  // Op::ZC(zc_l, c_repr),
440  res.zc = res.zc + (t.template get<4>() * t.template get<3>().first);
441  // Op::ZC(zc_r, c_inv_repr),
442  res.zc = res.zc + (t.template get<5>() * t.template get<3>().second);
443  });
444 
445  // we reverse the order because the polynomial evaluation routine expects
446  // the challenges in reverse order.Doing it here allows us to compute the final_r
447  // in log time. Challenges are used as well in the KZG verification checks.
448  std::reverse(challenges.begin(), challenges.end());
449  std::reverse(challenges_inv.begin(), challenges_inv.end());
450 
451  final_res.merge(res);
452  typename CurveType::scalar_field_type::value_type final_r =
453  polynomial_evaluation_product_form_from_transcript<typename CurveType::scalar_field_type>(
454  challenges_inv.begin(), challenges_inv.end(), r_shift,
455  CurveType::scalar_field_type::value_type::one());
456 
457  return std::make_tuple(final_res, final_r, challenges, challenges_inv);
458  }
459 
463  template<typename CurveType, typename DistributionType, typename GeneratorType,
464  typename Hash = hashes::sha2<256>>
468  const typename CurveType::scalar_field_type::value_type &r_shift,
470  // (T,U), Z for TIPP and MIPP and all challenges
471  auto [final_res, final_r, challenges, challenges_inv] =
472  gipa_verify_tipp_mipp<CurveType, Hash>(tr, proof, r_shift);
473 
474  // Verify commitment keys wellformed
475  // KZG challenge point
476  constexpr std::array<std::uint8_t, 8> domain_separator {'r', 'a', 'n', 'd', 'o', 'm', '-', 'z'};
477  tr.write_domain_separator(domain_separator.begin(), domain_separator.end());
478  tr.template write<typename CurveType::scalar_field_type>(challenges.front());
479  tr.template write<typename CurveType::template g2_type<>>(proof.tmipp.gipa.final_vkey.first);
480  tr.template write<typename CurveType::template g2_type<>>(proof.tmipp.gipa.final_vkey.second);
481  tr.template write<typename CurveType::template g1_type<>>(proof.tmipp.gipa.final_wkey.first);
482  tr.template write<typename CurveType::template g1_type<>>(proof.tmipp.gipa.final_wkey.second);
483  typename CurveType::scalar_field_type::value_type c = tr.read_challenge();
484 
485  // TODO: parallel
486  // check the opening proof for v
487  verify_kzg_v<CurveType, DistributionType, GeneratorType>(
488  v_srs, proof.tmipp.gipa.final_vkey, proof.tmipp.vkey_opening, challenges_inv.begin(),
489  challenges_inv.end(), c, pc);
490  // check the opening proof for w - note that w has been rescaled by $r^{-1}$
491  verify_kzg_w<CurveType, DistributionType, GeneratorType>(
492  v_srs, proof.tmipp.gipa.final_wkey, proof.tmipp.wkey_opening, challenges.begin(),
493  challenges.end(), r_shift.inversed(), c, pc);
494  //
495  // We create a sequence of pairing tuple that we aggregate together at
496  // the end to perform only once the final exponentiation.
497  //
498  // TIPP
499  // z = e(A,B)
500  std::vector<typename CurveType::template g1_type<>::value_type> a_input1 {
501  proof.tmipp.gipa.final_a,
502  };
503  std::vector<typename CurveType::template g2_type<>::value_type> b_input1 {
504  proof.tmipp.gipa.final_b,
505  };
506  pc.merge_random(a_input1.begin(), a_input1.end(), b_input1.begin(), b_input1.end(), final_res.zab);
507 
508  // final_aB.0 = T = e(A,v1)e(w1,B)
509  a_input1.template emplace_back(proof.tmipp.gipa.final_wkey.first);
510  b_input1.template emplace(b_input1.begin(), proof.tmipp.gipa.final_vkey.first);
511  pc.merge_random(a_input1.begin(), a_input1.end(), b_input1.begin(), b_input1.end(), final_res.tab);
512 
513  // final_aB.1 = U = e(A,v2)e(w2,B)
514  a_input1.pop_back();
515  a_input1.template emplace_back(proof.tmipp.gipa.final_wkey.second);
516  b_input1.erase(b_input1.begin());
517  b_input1.template emplace(b_input1.begin(), proof.tmipp.gipa.final_vkey.second);
518  pc.merge_random(a_input1.begin(), a_input1.end(), b_input1.begin(), b_input1.end(), final_res.uab);
519 
520  // MIPP
521  // Verify base inner product commitment
522  // Z == c ^ r
523  typename CurveType::template g1_type<>::value_type final_z = final_r * proof.tmipp.gipa.final_c;
524 
525  // Check commiment correctness
526  // T = e(C,v1)
527  std::vector<typename CurveType::template g1_type<>::value_type> a_input2 {
528  proof.tmipp.gipa.final_c,
529  };
530  std::vector<typename CurveType::template g2_type<>::value_type> b_input2 {
531  proof.tmipp.gipa.final_vkey.first,
532  };
533  pc.merge_random(a_input2.begin(), a_input2.end(), b_input2.begin(), b_input2.end(), final_res.tc);
534 
535  // U = e(A,v2)
536  b_input2.pop_back();
537  b_input2.template emplace_back(proof.tmipp.gipa.final_vkey.second);
538  pc.merge_random(a_input2.begin(), a_input2.end(), b_input2.begin(), b_input2.end(), final_res.uc);
539 
540  if (final_z != final_res.zc) {
541  pc.invalidate();
542  }
543  }
544 
558  template<typename CurveType,
559  typename DistributionType = boost::random::uniform_int_distribution<
560  typename CurveType::scalar_field_type::integral_type>,
561  typename GeneratorType = boost::random::mt19937, typename Hash = hashes::sha2<256>,
562  typename InputRangesRange, typename InputIterator>
563  inline typename std::enable_if<
564  std::is_same<typename CurveType::scalar_field_type::value_type,
565  typename std::iterator_traits<typename std::iterator_traits<
566  typename InputRangesRange::iterator>::value_type::iterator>::value_type>::value &&
567  std::is_same<std::uint8_t, typename std::iterator_traits<InputIterator>::value_type>::value,
568  bool>::type
572  const InputRangesRange &public_inputs,
574  InputIterator transcript_include_first,
575  InputIterator transcript_include_last) {
576  for (const auto &public_input : public_inputs) {
577  BOOST_ASSERT((public_input.size()) == pvk.gamma_ABC_g1.size());
578  }
579 
580  // Random linear combination of proofs
581  constexpr std::array<std::uint8_t, 9> application_tag = {'s', 'n', 'a', 'r', 'k',
582  'p', 'a', 'c', 'k'};
583  constexpr std::array<std::uint8_t, 8> domain_separator {'r', 'a', 'n', 'd', 'o', 'm', '-', 'r'};
584  transcript<CurveType, Hash> tr(application_tag.begin(), application_tag.end());
585  tr.write_domain_separator(domain_separator.begin(), domain_separator.end());
586  tr.template write<typename CurveType::gt_type>(proof.com_ab.first);
587  tr.template write<typename CurveType::gt_type>(proof.com_ab.second);
588  tr.template write<typename CurveType::gt_type>(proof.com_c.first);
589  tr.template write<typename CurveType::gt_type>(proof.com_c.second);
590  tr.write(transcript_include_first, transcript_include_last);
591  typename CurveType::scalar_field_type::value_type r = tr.read_challenge();
592  tr.template write<typename CurveType::gt_type>(proof.ip_ab);
593  tr.template write<typename CurveType::template g1_type<>>(proof.agg_c);
594 
596 
597  // TODO: parallel
598  // 1.Check TIPA proof ab
599  // 2.Check TIPA proof c
600  verify_tipp_mipp<CurveType, DistributionType, GeneratorType, Hash>(
601  tr,
602  ip_verifier_srs,
603  proof,
604  // we give the extra r as it's not part of the proof itself - it is simply used on top for the
605  // groth16 aggregation
606  r,
607  pc);
608 
609  // Check aggregate pairing product equation
610  // SUM of a geometric progression
611  // SUM a^i = (1 - a^n) / (1 - a) = -(1-a^n)/-(1-a)
612  // = (a^n - 1) / (a - 1)
613  typename CurveType::scalar_field_type::value_type r_sum =
614  (r.pow(public_inputs.size()) - CurveType::scalar_field_type::value_type::one()) *
615  (r - CurveType::scalar_field_type::value_type::one()).inversed();
616 
617  // The following parts 3 4 5 are independently computing the parts of the Groth16
618  // verification equation
619  // NOTE From this point on, we are only checking *one* pairing check (the Groth16
620  // verification equation) so we don't need to randomize as all other checks are being
621  // randomized already. When merging all pairing checks together, this will be the only one
622  // non-randomized.
623  //
624  // now we do the multi exponentiation
625  std::vector<typename CurveType::scalar_field_type::value_type> powers =
626  structured_scalar_power<typename CurveType::scalar_field_type>(public_inputs.size(), r);
627  std::vector<typename CurveType::scalar_field_type::value_type> multi_r_vec;
628  // i denotes the column of the public input, and j denotes which public input
629  for (std::size_t i = 0; i < public_inputs[0].size(); ++i) {
630  typename CurveType::scalar_field_type::value_type c = public_inputs[0][i];
631  for (std::size_t j = 1; j < public_inputs.size(); ++j) {
632  c = c + public_inputs[j][i] * powers[j];
633  }
634  multi_r_vec.emplace_back(c);
635  }
636 
637  // 3. Compute left part of the final pairing equation
638  typename CurveType::gt_type::value_type left =
639  algebra::pair<CurveType>(pvk.alpha_g1 * r_sum, pvk.beta_g2);
640 
641  // 4. Compute right part of the final pairing equation
642  typename CurveType::gt_type::value_type right = algebra::pair<CurveType>(proof.agg_c, pvk.delta_g2);
643 
644  // 5. compute the middle part of the final pairing equation, the one
645  // with the public inputs
646  // We want to compute MUL(i:0 -> l) S_i ^ (SUM(j:0 -> n) ai,j * r^j)
647  // this table keeps tracks of incremental computation of each i-th
648  // exponent to later multiply with S_i
649  // The index of the table is i, which is an index of the public
650  // input element
651  // We incrementally build the r vector and the table
652  // NOTE: in this version it's not r^2j but simply r^j
653  typename CurveType::template g1_type<>::value_type g_ic = pvk.gamma_ABC_g1.first * r_sum;
654  // TODO: do without using of accumulation_vector
655  typename CurveType::template g1_type<>::value_type totsi =
656  pvk.gamma_ABC_g1.accumulate_chunk(multi_r_vec.begin(), multi_r_vec.end(), 0).first -
657  pvk.gamma_ABC_g1.first;
658  g_ic = g_ic + totsi;
659  typename CurveType::gt_type::value_type middle = algebra::pair<CurveType>(g_ic, pvk.gamma_g2);
660 
661  std::vector<typename CurveType::gt_type::value_type> a_input {left, middle, right};
662  pc.merge_nonrandom(a_input.begin(), a_input.end(), proof.ip_ab);
663  return pc.verify();
664  }
665 
666  template<typename CurveType>
672 
673  public:
678 
679  // Aggregate verify
680  template<typename DistributionType, typename GeneratorType, typename Hash,
681  typename InputPrimaryInputRange, typename InputIterator>
682  static inline typename std::enable_if<
683  std::is_same<primary_input_type,
684  typename std::iterator_traits<
685  typename InputPrimaryInputRange::iterator>::value_type>::value,
686  bool>::type
687  process(const verification_srs_type &ip_verifier_srs,
688  const verification_key_type &pvk,
689  const InputPrimaryInputRange &public_inputs,
690  const proof_type &proof,
691  InputIterator transcript_include_first,
692  InputIterator transcript_include_last) {
693  return verify_aggregate_proof<CurveType, DistributionType, GeneratorType, Hash>(
694  ip_verifier_srs, pvk, public_inputs, proof, transcript_include_first,
695  transcript_include_last);
696  }
697 
698  // Basic verify
699  template<typename VerificationKey>
700  static inline bool process(const VerificationKey &vk,
701  const primary_input_type &primary_input,
702  const basic_proof_type &proof) {
703  return basic_verifier::process(vk, primary_input, proof);
704  }
705  };
706  } // namespace snark
707  } // namespace zk
708  } // namespace crypto3
709 } // namespace nil
710 
711 #endif // CRYPTO3_R1CS_GG_PPZKSNARK_TYPES_POLICY_HPP
SHA2.
Definition: sha2.hpp:46
std::size_t size() const
Definition: accumulation_vector.hpp:83
accumulation_vector< Type > accumulate_chunk(InputIterator begin, InputIterator end, std::size_t offset) const
Definition: accumulation_vector.hpp:94
underlying_value_type first
Definition: accumulation_vector.hpp:52
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:47
curve_type::gt_type::value_type tab
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:52
gipa_tuz(const typename curve_type::gt_type::value_type &tab, const typename curve_type::gt_type::value_type &uab, const typename curve_type::gt_type::value_type &zab, const typename curve_type::gt_type::value_type &tc, const typename curve_type::gt_type::value_type &uc, const typename g1_type::value_type &zc)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:65
curve_type::gt_type::value_type uc
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:56
g1_type::value_type zc
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:57
gipa_tuz()
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:59
void merge(const gipa_tuz &other)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:75
curve_type::gt_type::value_type tc
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:55
curve_type::gt_type::value_type uab
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:53
curve_type::gt_type::value_type zab
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:54
Definition: snark/proof.hpp:37
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/verifier.hpp:190
policy_type::verification_srs_type verification_srs_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:676
static std::enable_if< std::is_same< primary_input_type, typename std::iterator_traits< typename InputPrimaryInputRange::iterator >::value_type >::value, bool >::type process(const verification_srs_type &ip_verifier_srs, const verification_key_type &pvk, const InputPrimaryInputRange &public_inputs, const proof_type &proof, InputIterator transcript_include_first, InputIterator transcript_include_last)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:687
policy_type::verification_key_type verification_key_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:675
static bool process(const VerificationKey &vk, const primary_input_type &primary_input, const basic_proof_type &proof)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:700
policy_type::proof_type proof_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:677
policy_type::primary_input_type primary_input_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:674
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/verifier.hpp:75
PairingCurveType::gt_type::value_type pair(const typename PairingCurveType::template g1_type<>::value_type &v1, const typename PairingCurveType::template g2_type<>::value_type &v2)
Definition: pair.hpp:73
void reverse(Range &a, std::size_t n)
Definition: basic_operations.hpp:54
std::pair< typename GroupType::value_type, typename GroupType::value_type > kzg_opening
Definition: snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/proof.hpp:45
std::tuple< gipa_tuz< CurveType >, typename CurveType::scalar_field_type::value_type, std::vector< typename CurveType::scalar_field_type::value_type >, std::vector< typename CurveType::scalar_field_type::value_type > > gipa_verify_tipp_mipp(transcript< CurveType, Hash > &tr, const r1cs_gg_ppzksnark_aggregate_proof< CurveType > &proof, const typename CurveType::scalar_field_type::value_type &r_shift)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:329
void verify_tipp_mipp(transcript< CurveType, Hash > &tr, const r1cs_gg_ppzksnark_aggregate_verification_srs< CurveType > &v_srs, const r1cs_gg_ppzksnark_aggregate_proof< CurveType > &proof, const typename CurveType::scalar_field_type::value_type &r_shift, pairing_check< CurveType, DistributionType, GeneratorType > &pc)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:465
std::enable_if< std::is_same< typename CurveType::scalar_field_type::value_type, typename std::iterator_traits< typename std::iterator_traits< typename InputRangesRange::iterator >::value_type::iterator >::value_type >::value &&std::is_same< std::uint8_t, typename std::iterator_traits< InputIterator >::value_type >::value, bool >::type verify_aggregate_proof(const r1cs_gg_ppzksnark_aggregate_verification_srs< CurveType > &ip_verifier_srs, const r1cs_gg_ppzksnark_aggregate_verification_key< CurveType > &pvk, const InputRangesRange &public_inputs, const r1cs_gg_ppzksnark_aggregate_proof< CurveType > &proof, InputIterator transcript_include_first, InputIterator transcript_include_last)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:569
ProvingMode
Definition: modes.hpp:33
std::pair< typename CurveType::gt_type::value_type, typename CurveType::gt_type::value_type > r1cs_gg_ppzksnark_ipp2_commitment_output
Both commitment outputs a pair of $F_q^k$ element.
Definition: commitment.hpp:76
std::enable_if< std::is_same< typename CurveType::scalar_field_type::value_type, typename std::iterator_traits< InputScalarIterator >::value_type >::value >::type verify_kzg_w(const r1cs_gg_ppzksnark_aggregate_verification_srs< CurveType > &v_srs, const std::pair< typename CurveType::template g1_type<>::value_type, typename CurveType::template g1_type<>::value_type > &final_wkey, const kzg_opening< typename CurveType::template g1_type<>> &wkey_opening, InputScalarIterator challenges_first, InputScalarIterator challenges_last, const typename CurveType::scalar_field_type::value_type &r_shift, const typename CurveType::scalar_field_type::value_type &kzg_challenge, pairing_check< CurveType, DistributionType, GeneratorType > &pc)
Similar to verify_kzg_opening_g2 but for g1.
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:271
std::enable_if< std::is_same< typename CurveType::scalar_field_type::value_type, typename std::iterator_traits< InputScalarIterator >::value_type >::value >::type verify_kzg_v(const r1cs_gg_ppzksnark_aggregate_verification_srs< CurveType > &v_srs, const std::pair< typename CurveType::template g2_type<>::value_type, typename CurveType::template g2_type<>::value_type > &final_vkey, const kzg_opening< typename CurveType::template g2_type<>> &vkey_opening, InputScalarIterator challenges_first, InputScalarIterator challenges_last, const typename CurveType::scalar_field_type::value_type &kzg_challenge, pairing_check< CurveType, DistributionType, GeneratorType > &pc)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:215
Definition: pair.hpp:31
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/detail/basic_policy.hpp:168
r1cs_primary_input< typename curve_type::scalar_field_type > primary_input_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/detail/basic_policy.hpp:180
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:96
bool valid
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:112
gt_value_type left
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:109
curve_type::template g2_type g2_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:100
void merge()
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:141
void invalidate()
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:202
bool verify()
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:189
bool non_random_check_done
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:111
pairing_check(InputG1Iterator a_first, InputG1Iterator a_last, InputG2Iterator b_first, InputG2Iterator b_last, const gt_value_type &out)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:134
g1_type::value_type g1_value_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:104
curve_type::gt_type gt_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:101
scalar_field_type::value_type scalar_field_value_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:107
curve_type::scalar_field_type scalar_field_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:102
std::enable_if< std::is_same< g1_value_type, typename std::iterator_traits< InputG1Iterator >::value_type >::value &&std::is_same< g2_value_type, typename std::iterator_traits< InputG2Iterator >::value_type >::value >::type merge_random(InputG1Iterator a_first, InputG1Iterator a_last, InputG2Iterator b_first, InputG2Iterator b_last, const gt_value_type &out)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:150
scalar_field_value_type derive_non_zero()
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:193
pairing_check()
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:114
gt_type::value_type gt_value_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:106
g2_type::value_type g2_value_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:105
CurveType curve_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:97
gt_value_type right
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:110
std::enable_if< std::is_same< gt_value_type, typename std::iterator_traits< InputGTIterator >::value_type >::value >::type merge_nonrandom(InputGTIterator a_first, InputGTIterator a_last, const gt_value_type &out)
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:173
curve_type::template g1_type g1_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verifier.hpp:99
Definition: snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/proof.hpp:96
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verification_key.hpp:38
curve_type::template g2_type ::value_type gamma_g2
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verification_key.hpp:43
curve_type::template g2_type ::value_type beta_g2
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verification_key.hpp:42
curve_type::template g1_type ::value_type alpha_g1
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verification_key.hpp:41
curve_type::template g2_type ::value_type delta_g2
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verification_key.hpp:44
accumulation_vector< typename CurveType::template g1_type<> > gamma_ABC_g1
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/verification_key.hpp:46
CurveType::template g1_type ::value_type g
Definition: srs.hpp:105
CurveType::template g2_type ::value_type h_beta
Definition: srs.hpp:110
CurveType::template g1_type ::value_type g_beta
Definition: srs.hpp:108
CurveType::template g2_type ::value_type h
Definition: srs.hpp:106
CurveType::template g2_type ::value_type h_alpha
Definition: srs.hpp:109
CurveType::template g1_type ::value_type g_alpha
Definition: srs.hpp:107
Definition: snark/systems/ppzksnark/r1cs_gg_ppzksnark/proof.hpp:40
Transcript policy. Assumed to be inherited by particular algorithms.
Definition: systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/transcript.hpp:46
curve_type::scalar_field_type::value_type read_challenge()
Definition: systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/transcript.hpp:120
std::enable_if< std::is_same< typename curve_type::base_field_type, FieldType >::value||std::is_same< typename curve_type::scalar_field_type, FieldType >::value||std::is_same< typename curve_type::gt_type, FieldType >::value >::type write(const typename FieldType::value_type &x)
Definition: systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/transcript.hpp:82
void write_domain_separator(InputIterator first, InputIterator last)
Definition: systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/transcript.hpp:71