r1cs_gg_ppzksnark/ipp2/prover.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_PROVE_HPP
28 #define CRYPTO3_R1CS_GG_PPZKSNARK_IPP2_PROVE_HPP
29 
30 #include <algorithm>
31 #include <vector>
32 #include <tuple>
33 #include <string>
34 
35 #include <boost/iterator/zip_iterator.hpp>
36 
37 #include <nil/crypto3/detail/pack_numeric.hpp>
38 
41 
43 
47 
54 
55 namespace nil {
56  namespace crypto3 {
57  namespace zk {
58  namespace snark {
63  template<typename FieldType>
64  std::vector<typename FieldType::value_type>
65  structured_scalar_power(std::size_t num, const typename FieldType::value_type &s) {
66  std::vector<typename FieldType::value_type> powers = {FieldType::value_type::one()};
67  for (int i = 1; i < num; i++) {
68  powers.emplace_back(powers.back() * s);
69  }
70  return powers;
71  }
72 
76  template<typename CurveType, typename InputRange,
77  typename ValueType = typename std::iterator_traits<typename InputRange::iterator>::value_type>
78  typename std::enable_if<
79  std::is_same<typename CurveType::template g1_type<>::value_type, ValueType>::value ||
80  std::is_same<typename CurveType::template g2_type<>::value_type, ValueType>::value ||
81  std::is_same<typename CurveType::scalar_field_type::value_type, ValueType>::value>::type
82  compress(InputRange &vec, std::size_t split,
83  const typename CurveType::scalar_field_type::value_type &scalar) {
84  std::for_each(boost::make_zip_iterator(boost::make_tuple(vec.begin(), vec.begin() + split)),
85  boost::make_zip_iterator(boost::make_tuple(vec.begin() + split, vec.end())),
86  [&](const boost::tuple<ValueType &, ValueType &> &t) {
87  t.template get<0>() = t.template get<0>() + t.template get<1>() * scalar;
88  });
89  vec.resize(split);
90  }
91 
96  template<typename FieldType, typename InputFieldValueIterator>
97  typename std::enable_if<std::is_same<typename std::iterator_traits<InputFieldValueIterator>::value_type,
98  typename FieldType::value_type>::value,
99  typename FieldType::value_type>::type
100  polynomial_evaluation_product_form_from_transcript(InputFieldValueIterator transcript_first,
101  InputFieldValueIterator transcript_last,
102  const typename FieldType::value_type &z,
103  const typename FieldType::value_type &r_shift) {
104  // this is the term (rz) that will get squared at each step to produce the
105  // $(rz)^{2j}$ of the formula
106  typename FieldType::value_type power_zr = z;
107  power_zr = power_zr * r_shift;
108 
109  // 0 iteration
110  InputFieldValueIterator transcript_iter = transcript_first;
111  typename FieldType::value_type res = FieldType::value_type::one() + (*transcript_iter * power_zr);
112  power_zr = power_zr * power_zr;
113  ++transcript_iter;
114 
115  // the rest
116  while (transcript_iter != transcript_last) {
117  res = res * (FieldType::value_type::one() + (*transcript_iter * power_zr));
118  power_zr = power_zr * power_zr;
119  ++transcript_iter;
120  }
121 
122  return res;
123  }
124 
125  // Compute the coefficients of the polynomial $\prod_{j=0}^{l-1} (1 + x_{l-j}(rX)^{2j})$
126  // It does this in logarithmic time directly; here is an example with 2
127  // challenges:
128  //
129  // We wish to compute $(1+x_1ra)(1+x_0(ra)^2) = 1 + x_1ra + x_0(ra)^2 + x_0x_1(ra)^3$
130  // Algorithm: $c_{-1} = [1]$; $c_j = c_{i-1} \| (x_{l-j} * c_{i-1})$; $r = r*r$
131  // $c_0 = c_{-1} \| (x_1 * r * c_{-1}) = [1] \| [rx_1] = [1, rx_1]$, $r = r^2$
132  // $c_1 = c_0 \| (x_0 * r^2c_0) = [1, rx_1] \| [x_0r^2, x_0x_1r^3] = [1, x_1r, x_0r^2, x_0x_1r^3]$
133  // which is equivalent to $f(a) = 1 + x_1ra + x_0(ra)^2 + x_0x_1r^2a^3$
134  //
135  // This method expects the coefficients in reverse order so transcript[i] =
136  // x_{l-j}.
137  template<typename FieldType, typename InputFieldValueIterator>
138  typename std::enable_if<std::is_same<typename std::iterator_traits<InputFieldValueIterator>::value_type,
139  typename FieldType::value_type>::value,
140  std::vector<typename FieldType::value_type>>::type
141  polynomial_coefficients_from_transcript(InputFieldValueIterator transcript_first,
142  InputFieldValueIterator transcript_last,
143  const typename FieldType::value_type &r_shift) {
144  std::vector<typename FieldType::value_type> coefficients = {FieldType::value_type::one()};
145  typename FieldType::value_type power_2_r = r_shift;
146 
147  InputFieldValueIterator transcript_iter = transcript_first;
148  while (transcript_iter != transcript_last) {
149  std::size_t n = coefficients.size();
150  for (int j = 0; j < n; j++) {
151  coefficients.emplace_back(coefficients[j] * (*transcript_iter * power_2_r));
152  }
153  power_2_r = power_2_r * power_2_r;
154 
155  ++transcript_iter;
156  }
157 
158  return coefficients;
159  }
160 
163  template<typename GroupType, typename InputGroupIterator, typename InputScalarRange>
164  typename std::enable_if<
165  std::is_same<typename GroupType::value_type,
166  typename std::iterator_traits<InputGroupIterator>::value_type>::value &&
167  std::is_same<
168  typename GroupType::curve_type::scalar_field_type::value_type,
169  typename std::iterator_traits<typename InputScalarRange::iterator>::value_type>::value,
170  kzg_opening<GroupType>>::type
172  InputGroupIterator srs_powers_alpha_first, InputGroupIterator srs_powers_alpha_last,
173  InputGroupIterator srs_powers_beta_first, InputGroupIterator srs_powers_beta_last,
174  const InputScalarRange &poly,
175  const typename GroupType::curve_type::scalar_field_type::value_type &eval_poly,
176  const typename GroupType::curve_type::scalar_field_type::value_type &kzg_challenge) {
177  typename GroupType::curve_type::scalar_field_type::value_type neg_kzg_challenge = -kzg_challenge;
178 
179  BOOST_ASSERT(poly.size() == std::distance(srs_powers_alpha_first, srs_powers_alpha_last));
180  BOOST_ASSERT(poly.size() == std::distance(srs_powers_beta_first, srs_powers_beta_last));
181 
182  // f_v(X) - f_v(z) / (X - z)
183  std::vector<typename GroupType::curve_type::scalar_field_type::value_type> f_vX_sub_f_vZ;
184  math::polynomial::subtraction(f_vX_sub_f_vZ,
185  poly,
186  {{
187  eval_poly,
188  }});
189  std::vector<typename GroupType::curve_type::scalar_field_type::value_type> quotient_polynomial,
190  remainder_polynomial;
191  math::polynomial::division<typename GroupType::curve_type::scalar_field_type>(
192  quotient_polynomial, remainder_polynomial, f_vX_sub_f_vZ,
193  {{
194  neg_kzg_challenge,
195  GroupType::curve_type::scalar_field_type::value_type::one(),
196  }});
197 
198  if (quotient_polynomial.size() < poly.size()) {
199  quotient_polynomial.resize(poly.size(),
200  GroupType::curve_type::scalar_field_type::value_type::zero());
201  }
202  BOOST_ASSERT(quotient_polynomial.size() == poly.size());
203 
204  // we do one proof over h^a and one proof over h^b (or g^a and g^b depending
205  // on the curve we are on). that's the extra cost of the commitment scheme
206  // used which is compatible with Groth16 CRS insteaf of the original paper
207  // of Bunz'19
208  return kzg_opening<GroupType> {algebra::multiexp<algebra::policies::multiexp_method_bos_coster>(
209  srs_powers_alpha_first, srs_powers_alpha_last,
210  quotient_polynomial.begin(), quotient_polynomial.end(), 1),
211  algebra::multiexp<algebra::policies::multiexp_method_bos_coster>(
212  srs_powers_beta_first, srs_powers_beta_last,
213  quotient_polynomial.begin(), quotient_polynomial.end(), 1)};
214  }
215 
216  template<typename CurveType, typename InputG2Iterator, typename InputScalarIterator>
217  typename std::enable_if<
218  std::is_same<typename CurveType::template g2_type<>::value_type,
219  typename std::iterator_traits<InputG2Iterator>::value_type>::value &&
220  std::is_same<typename CurveType::scalar_field_type::value_type,
221  typename std::iterator_traits<InputScalarIterator>::value_type>::value,
222  kzg_opening<typename CurveType::template g2_type<>>>::type
223  prove_commitment_v(InputG2Iterator srs_powers_alpha_first, InputG2Iterator srs_powers_alpha_last,
224  InputG2Iterator srs_powers_beta_first, InputG2Iterator srs_powers_beta_last,
225  InputScalarIterator transcript_first, InputScalarIterator transcript_last,
226  const typename CurveType::scalar_field_type::value_type &kzg_challenge) {
227  std::vector<typename CurveType::scalar_field_type::value_type> vkey_poly =
228  polynomial_coefficients_from_transcript<typename CurveType::scalar_field_type>(
229  transcript_first, transcript_last, CurveType::scalar_field_type::value_type::one());
230  math::polynomial::condense(vkey_poly);
231  BOOST_ASSERT(!math::polynomial::is_zero(vkey_poly));
232 
233  typename CurveType::scalar_field_type::value_type vkey_poly_z =
234  polynomial_evaluation_product_form_from_transcript<typename CurveType::scalar_field_type>(
235  transcript_first, transcript_last, kzg_challenge,
236  CurveType::scalar_field_type::value_type::one());
237 
238  return prove_commitment_key_kzg_opening<typename CurveType::template g2_type<>>(
239  srs_powers_alpha_first, srs_powers_alpha_last, srs_powers_beta_first, srs_powers_beta_last,
240  vkey_poly, vkey_poly_z, kzg_challenge);
241  }
242 
243  template<typename CurveType, typename InputG1Iterator, typename InputScalarIterator>
244  typename std::enable_if<
245  std::is_same<typename CurveType::template g1_type<>::value_type,
246  typename std::iterator_traits<InputG1Iterator>::value_type>::value &&
247  std::is_same<typename CurveType::scalar_field_type::value_type,
248  typename std::iterator_traits<InputScalarIterator>::value_type>::value,
249  kzg_opening<typename CurveType::template g1_type<>>>::type
250  prove_commitment_w(InputG1Iterator srs_powers_alpha_first, InputG1Iterator srs_powers_alpha_last,
251  InputG1Iterator srs_powers_beta_first, InputG1Iterator srs_powers_beta_last,
252  InputScalarIterator transcript_first, InputScalarIterator transcript_last,
253  typename CurveType::scalar_field_type::value_type r_shift,
254  const typename CurveType::scalar_field_type::value_type &kzg_challenge) {
255  std::size_t n = std::distance(srs_powers_beta_first, srs_powers_beta_last) / 2;
256  BOOST_ASSERT(2 * n == std::distance(srs_powers_alpha_first, srs_powers_alpha_last));
257 
258  // this computes f(X) = \prod (1 + x (rX)^{2^j})
259  std::vector<typename CurveType::scalar_field_type::value_type> fcoeffs =
260  polynomial_coefficients_from_transcript<typename CurveType::scalar_field_type>(
261  transcript_first, transcript_last, r_shift);
262  // this computes f_w(X) = X^n * f(X) - it simply shifts all coefficients to by n
263  fcoeffs.insert(fcoeffs.begin(), n, CurveType::scalar_field_type::value_type::zero());
264 
265  // this computes f(z)
266  typename CurveType::scalar_field_type::value_type fz =
267  polynomial_evaluation_product_form_from_transcript<typename CurveType::scalar_field_type>(
268  transcript_first, transcript_last, kzg_challenge, r_shift);
269  // this computes the "shift" z^n
270  typename CurveType::scalar_field_type::value_type zn = kzg_challenge.pow(n);
271  // this computes f_w(z) by multiplying by zn
272  typename CurveType::scalar_field_type::value_type fwz = fz * zn;
273 
274  return prove_commitment_key_kzg_opening<typename CurveType::template g1_type<>>(
275  srs_powers_alpha_first, srs_powers_alpha_last, srs_powers_beta_first, srs_powers_beta_last,
276  fcoeffs, fwz, kzg_challenge);
277  }
278 
283  template<typename CurveType, typename Hash = hashes::sha2<256>, typename InputG1Iterator1,
284  typename InputG2Iterator, typename InputG1Iterator2, typename InputScalarIterator>
285  typename std::enable_if<
286  std::is_same<typename CurveType::template g1_type<>::value_type,
287  typename std::iterator_traits<InputG1Iterator1>::value_type>::value &&
288  std::is_same<typename CurveType::template g2_type<>::value_type,
289  typename std::iterator_traits<InputG2Iterator>::value_type>::value &&
290  std::is_same<typename CurveType::scalar_field_type::value_type,
291  typename std::iterator_traits<InputScalarIterator>::value_type>::value &&
292  std::is_same<typename CurveType::template g1_type<>::value_type,
293  typename std::iterator_traits<InputG1Iterator2>::value_type>::value,
294  std::tuple<gipa_proof<CurveType>, std::vector<typename CurveType::scalar_field_type::value_type>,
295  std::vector<typename CurveType::scalar_field_type::value_type>>>::type
296  gipa_tipp_mipp(transcript<CurveType, Hash> &tr, InputG1Iterator1 a_first, InputG1Iterator1 a_last,
297  InputG2Iterator b_first, InputG2Iterator b_last, InputG1Iterator2 c_first,
298  InputG1Iterator2 c_last, const r1cs_gg_ppzksnark_ipp2_vkey<CurveType> &vkey_input,
299  const r1cs_gg_ppzksnark_ipp2_wkey<CurveType> &wkey_input,
300  InputScalarIterator r_first, InputScalarIterator r_last) {
301  std::size_t input_len = std::distance(a_first, a_last);
302  BOOST_ASSERT(input_len >= 2);
303  BOOST_ASSERT((input_len & (input_len - 1)) == 0);
304  BOOST_ASSERT(input_len == std::distance(b_first, b_last));
305  BOOST_ASSERT(input_len == std::distance(r_first, r_last));
306  BOOST_ASSERT(input_len == std::distance(c_first, c_last));
307 
308  // the values of vectors A and B rescaled at each step of the loop
309  // the values of vectors C and r rescaled at each step of the loop
310  std::vector<typename CurveType::template g1_type<>::value_type> m_a {a_first, a_last},
311  m_c {c_first, c_last};
312  std::vector<typename CurveType::template g2_type<>::value_type> m_b {b_first, b_last};
313  std::vector<typename CurveType::scalar_field_type::value_type> m_r {r_first, r_last};
314 
315  // the values of the commitment keys rescaled at each step of the loop
316  r1cs_gg_ppzksnark_ipp2_vkey<CurveType> vkey = vkey_input;
317  r1cs_gg_ppzksnark_ipp2_wkey<CurveType> wkey = wkey_input;
318 
319  // storing the values for including in the proof
320  std::vector<std::pair<typename r1cs_gg_ppzksnark_ipp2_commitment<CurveType>::output_type,
322  comms_ab;
323  std::vector<std::pair<typename r1cs_gg_ppzksnark_ipp2_commitment<CurveType>::output_type,
325  comms_c;
326  std::vector<
327  std::pair<typename CurveType::gt_type::value_type, typename CurveType::gt_type::value_type>>
328  z_ab;
329  std::vector<std::pair<typename CurveType::template g1_type<>::value_type,
330  typename CurveType::template g1_type<>::value_type>>
331  z_c;
332  std::vector<typename CurveType::scalar_field_type::value_type> challenges, challenges_inv;
333 
334  constexpr std::array<std::uint8_t, 4> domain_separator {'g', 'i', 'p', 'a'};
335  tr.write_domain_separator(domain_separator.begin(), domain_separator.end());
336  typename CurveType::scalar_field_type::value_type _i = tr.read_challenge();
337 
338  while (m_a.size() > 1) {
339  // recursive step
340  // Recurse with problem of half size
341  std::size_t split = m_a.size() / 2;
342 
343  auto [vk_left, vk_right] = vkey.split(split);
344  auto [wk_left, wk_right] = wkey.split(split);
345 
346  // TODO: parallel
347  // See section 3.3 for paper version with equivalent names
348  // TIPP part
351  vk_left, wk_right, m_a.begin() + split, m_a.end(), m_b.begin(), m_b.begin() + split);
354  vk_right, wk_left, m_a.begin(), m_a.begin() + split, m_b.begin() + split, m_b.end());
355 
356  // \prod e(A_right,B_left)
357  typename CurveType::gt_type::value_type zab_l = CurveType::gt_type::value_type::one();
358  std::for_each(
359  boost::make_zip_iterator(boost::make_tuple(m_a.begin() + split, m_b.begin())),
360  boost::make_zip_iterator(boost::make_tuple(m_a.end(), m_b.begin() + split)),
361  [&](const boost::tuple<const typename CurveType::template g1_type<>::value_type &,
362  const typename CurveType::template g2_type<>::value_type &> &t) {
363  zab_l = zab_l * algebra::pair<CurveType>(t.template get<0>(), t.template get<1>());
364  });
365  zab_l = algebra::final_exponentiation<CurveType>(zab_l);
366  typename CurveType::gt_type::value_type zab_r = CurveType::gt_type::value_type::one();
367  std::for_each(
368  boost::make_zip_iterator(boost::make_tuple(m_a.begin(), m_b.begin() + split)),
369  boost::make_zip_iterator(boost::make_tuple(m_a.begin() + split, m_b.end())),
370  [&](const boost::tuple<const typename CurveType::template g1_type<>::value_type &,
371  const typename CurveType::template g2_type<>::value_type &> &t) {
372  zab_r = zab_r * algebra::pair<CurveType>(t.template get<0>(), t.template get<1>());
373  });
374  zab_r = algebra::final_exponentiation<CurveType>(zab_r);
375 
376  // MIPP part
377  // z_l = c[n':] ^ r[:n']
378  typename CurveType::template g1_type<>::value_type zc_l =
379  algebra::multiexp<algebra::policies::multiexp_method_bos_coster>(
380  m_c.begin() + split, m_c.end(), m_r.begin(), m_r.begin() + split, 1);
381  // Z_r = c[:n'] ^ r[n':]
382  typename CurveType::template g1_type<>::value_type zc_r =
383  algebra::multiexp<algebra::policies::multiexp_method_bos_coster>(
384  m_c.begin(), m_c.begin() + split, m_r.begin() + split, m_r.end(), 1);
385  // u_l = c[n':] * v[:n']
387  r1cs_gg_ppzksnark_ipp2_commitment<CurveType>::single(vk_left, m_c.begin() + split,
388  m_c.end());
389  // u_r = c[:n'] * v[n':]
392  m_c.begin() + split);
393 
394  // Fiat-Shamir challenge
395  // combine both TIPP and MIPP transcript
396  tr.template write<typename CurveType::gt_type>(zab_l);
397  tr.template write<typename CurveType::gt_type>(zab_r);
398  tr.template write<typename CurveType::template g1_type<>>(zc_l);
399  tr.template write<typename CurveType::template g1_type<>>(zc_r);
400  tr.template write<typename CurveType::gt_type>(tab_l.first);
401  tr.template write<typename CurveType::gt_type>(tab_l.second);
402  tr.template write<typename CurveType::gt_type>(tab_r.first);
403  tr.template write<typename CurveType::gt_type>(tab_r.second);
404  tr.template write<typename CurveType::gt_type>(tuc_l.first);
405  tr.template write<typename CurveType::gt_type>(tuc_l.second);
406  tr.template write<typename CurveType::gt_type>(tuc_r.first);
407  tr.template write<typename CurveType::gt_type>(tuc_r.second);
408  typename CurveType::scalar_field_type::value_type c_inv = tr.read_challenge();
409 
410  // Optimization for multiexponentiation to rescale G2 elements with
411  // 128-bit challenge Swap 'c' and 'c_inv' since can't control bit size
412  // of c_inv
413  typename CurveType::scalar_field_type::value_type c = c_inv.inversed();
414 
415  // Set up values for next step of recursion
416  // A[:n'] + A[n':] ^ x
417  compress<CurveType>(m_a, split, c);
418  // B[:n'] + B[n':] ^ x^-1
419  compress<CurveType>(m_b, split, c_inv);
420  // c[:n'] + c[n':]^x
421  compress<CurveType>(m_c, split, c);
422  // r[:n'] + r[n':]^x^-1
423  compress<CurveType>(m_r, split, c_inv);
424 
425  // v_left + v_right^x^-1
426  vkey = vk_left.compress(vk_right, c_inv);
427  // w_left + w_right^x
428  wkey = wk_left.compress(wk_right, c);
429 
430  comms_ab.emplace_back(std::make_pair(tab_l, tab_r));
431  comms_c.emplace_back(std::make_pair(tuc_l, tuc_r));
432  z_ab.emplace_back(std::make_pair(zab_l, zab_r));
433  z_c.emplace_back(std::make_pair(zc_l, zc_r));
434  challenges.emplace_back(c);
435  challenges_inv.emplace_back(c_inv);
436  }
437 
438  BOOST_ASSERT(m_a.size() == 1 && m_b.size() == 1);
439  BOOST_ASSERT(m_c.size() == 1 && m_r.size() == 1);
440  BOOST_ASSERT(vkey.a.size() == 1 && vkey.b.size() == 1);
441  BOOST_ASSERT(wkey.a.size() == 1 && wkey.b.size() == 1);
442 
443  return std::make_tuple(gipa_proof<CurveType> {input_len, comms_ab, comms_c, z_ab, z_c, m_a[0],
444  m_b[0], m_c[0], vkey.first(), wkey.first()},
445  challenges, challenges_inv);
446  }
447 
454  template<typename CurveType, typename Hash = hashes::sha2<256>, typename InputG1Iterator1,
455  typename InputG2Iterator, typename InputG1Iterator2, typename InputScalarIterator>
456  typename std::enable_if<
457  std::is_same<typename CurveType::template g1_type<>::value_type,
458  typename std::iterator_traits<InputG1Iterator1>::value_type>::value &&
459  std::is_same<typename CurveType::template g2_type<>::value_type,
460  typename std::iterator_traits<InputG2Iterator>::value_type>::value &&
461  std::is_same<typename CurveType::template g1_type<>::value_type,
462  typename std::iterator_traits<InputG1Iterator2>::value_type>::value &&
463  std::is_same<typename CurveType::scalar_field_type::value_type,
464  typename std::iterator_traits<InputScalarIterator>::value_type>::value,
465  tipp_mipp_proof<CurveType>>::type
467  transcript<CurveType, Hash> &tr, InputG1Iterator1 a_first, InputG1Iterator1 a_last,
468  InputG2Iterator b_first, InputG2Iterator b_last, InputG1Iterator2 c_first,
469  InputG1Iterator2 c_last, const r1cs_gg_ppzksnark_ipp2_wkey<CurveType> &wkey,
470  InputScalarIterator r_first, InputScalarIterator r_last) {
471  typename CurveType::scalar_field_type::value_type r_shift = *(r_first + 1);
472  // Run GIPA
473  auto [proof, challenges, challenges_inv] = gipa_tipp_mipp<CurveType>(
474  tr, a_first, a_last, b_first, b_last, c_first, c_last, srs.vkey, wkey, r_first, r_last);
475 
476  // Prove final commitment keys are wellformed
477  // we reverse the transcript so the polynomial in kzg opening is constructed
478  // correctly - the formula indicates x_{l-j}. Also for deriving KZG
479  // challenge point, input must be the last challenge.
480  std::reverse(challenges.begin(), challenges.end());
481  std::reverse(challenges_inv.begin(), challenges_inv.end());
482  typename CurveType::scalar_field_type::value_type r_inverse = r_shift.inversed();
483 
484  // KZG challenge point
485  constexpr std::array<std::uint8_t, 8> domain_separator {'r', 'a', 'n', 'd', 'o', 'm', '-', 'z'};
486  tr.write_domain_separator(domain_separator.begin(), domain_separator.end());
487  tr.template write<typename CurveType::scalar_field_type>(challenges[0]);
488  tr.template write<typename CurveType::template g2_type<>>(proof.final_vkey.first);
489  tr.template write<typename CurveType::template g2_type<>>(proof.final_vkey.second);
490  tr.template write<typename CurveType::template g1_type<>>(proof.final_wkey.first);
491  tr.template write<typename CurveType::template g1_type<>>(proof.final_wkey.second);
492  typename CurveType::scalar_field_type::value_type z = tr.read_challenge();
493 
494  // Complete KZG proofs
496  proof,
497  prove_commitment_v<CurveType>(srs.h_alpha_powers.begin(), srs.h_alpha_powers.end(),
498  srs.h_beta_powers.begin(), srs.h_beta_powers.end(),
499  challenges_inv.begin(), challenges_inv.end(), z),
500  prove_commitment_w<CurveType>(srs.g_alpha_powers.begin(), srs.g_alpha_powers.end(),
501  srs.g_beta_powers.begin(), srs.g_beta_powers.end(),
502  challenges.begin(), challenges.end(), r_inverse, z)};
503  }
504 
506  template<typename CurveType, typename Hash = hashes::sha2<256>, typename InputTranscriptIncludeIterator,
507  typename InputProofIterator>
508  typename std::enable_if<
509  std::is_same<std::uint8_t,
510  typename std::iterator_traits<InputTranscriptIncludeIterator>::value_type>::value &&
511  std::is_same<typename std::iterator_traits<InputProofIterator>::value_type,
512  r1cs_gg_ppzksnark_proof<CurveType>>::value,
513  r1cs_gg_ppzksnark_aggregate_proof<CurveType>>::type
515  InputTranscriptIncludeIterator tr_include_first,
516  InputTranscriptIncludeIterator tr_include_last, InputProofIterator proofs_first,
517  InputProofIterator proofs_last) {
518  std::size_t nproofs = std::distance(proofs_first, proofs_last);
519  BOOST_ASSERT(nproofs >= 2);
520  BOOST_ASSERT((nproofs & (nproofs - 1)) == 0);
521  BOOST_ASSERT(srs.has_correct_len(nproofs));
522 
523  // TODO: parallel
524  // We first commit to A B and C - these commitments are what the verifier
525  // will use later to verify the TIPP and MIPP proofs
526  std::vector<typename CurveType::template g1_type<>::value_type> a, c;
527  std::vector<typename CurveType::template g2_type<>::value_type> b;
528  auto proofs_it = proofs_first;
529  while (proofs_it != proofs_last) {
530  a.emplace_back(proofs_it->g_A);
531  b.emplace_back(proofs_it->g_B);
532  c.emplace_back(proofs_it->g_C);
533  ++proofs_it;
534  }
535 
536  // A and B are committed together in this scheme
537  // we need to take the reference so the macro doesn't consume the value
538  // first
540  r1cs_gg_ppzksnark_ipp2_commitment<CurveType>::pair(srs.vkey, srs.wkey, a.begin(), a.end(),
541  b.begin(), b.end());
544 
545  // Derive a random scalar to perform a linear combination of proofs
546  constexpr std::array<std::uint8_t, 9> application_tag = {'s', 'n', 'a', 'r', 'k',
547  'p', 'a', 'c', 'k'};
548  constexpr std::array<std::uint8_t, 8> domain_separator {'r', 'a', 'n', 'd', 'o', 'm', '-', 'r'};
549  transcript<CurveType, Hash> tr(application_tag.begin(), application_tag.end());
550  tr.write_domain_separator(domain_separator.begin(), domain_separator.end());
551  tr.template write<typename CurveType::gt_type>(com_ab.first);
552  tr.template write<typename CurveType::gt_type>(com_ab.second);
553  tr.template write<typename CurveType::gt_type>(com_c.first);
554  tr.template write<typename CurveType::gt_type>(com_c.second);
555  tr.write(tr_include_first, tr_include_last);
556  typename CurveType::scalar_field_type::value_type r = tr.read_challenge();
557 
558  // 1,r, r^2, r^3, r^4 ...
559  std::vector<typename CurveType::scalar_field_type::value_type> r_vec =
560  structured_scalar_power<typename CurveType::scalar_field_type>(
561  std::distance(proofs_first, proofs_last), r);
562  // 1,r^-1, r^-2, r^-3
563  std::vector<typename CurveType::scalar_field_type::value_type> r_inv;
564  std::transform(r_vec.begin(), r_vec.end(), std::back_inserter(r_inv),
565  [](const auto &r_i) { return r_i.inversed(); });
566 
567  // B^{r}
568  std::vector<typename CurveType::template g2_type<>::value_type> b_r;
569  std::for_each(
570  boost::make_zip_iterator(boost::make_tuple(b.begin(), r_vec.begin())),
571  boost::make_zip_iterator(boost::make_tuple(b.end(), r_vec.end())),
572  [&](const boost::tuple<const typename CurveType::template g2_type<>::value_type &,
573  const typename CurveType::scalar_field_type::value_type &> &t) {
574  b_r.emplace_back((t.template get<0>() * t.template get<1>()));
575  });
576  // TODO: parallel
577  // compute A * B^r for the verifier
578  // auto ip_ab = algebra::pair<CurveType>(a, b_r);
579  typename CurveType::gt_type::value_type ip_ab = CurveType::gt_type::value_type::one();
580  std::for_each(
581  boost::make_zip_iterator(boost::make_tuple(a.begin(), b_r.begin())),
582  boost::make_zip_iterator(boost::make_tuple(a.end(), b_r.end())),
583  [&](const boost::tuple<const typename CurveType::template g1_type<>::value_type &,
584  const typename CurveType::template g2_type<>::value_type &> &t) {
585  ip_ab = ip_ab * algebra::pair<CurveType>(t.template get<0>(), t.template get<1>());
586  });
587  ip_ab = algebra::final_exponentiation<CurveType>(ip_ab);
588  // compute C^r for the verifier
589  typename CurveType::template g1_type<>::value_type agg_c =
590  algebra::multiexp<algebra::policies::multiexp_method_bos_coster>(c.begin(), c.end(),
591  r_vec.begin(), r_vec.end(), 1);
592  tr.template write<typename CurveType::gt_type>(ip_ab);
593  tr.template write<typename CurveType::template g1_type<>>(agg_c);
594 
595  // w^{r^{-1}}
597  srs.wkey.scale(r_inv.begin(), r_inv.end());
598 
599  // we prove tipp and mipp using the same recursive loop
601  prove_tipp_mipp(srs, tr, a.begin(), a.end(), b_r.begin(), b_r.end(), c.begin(), c.end(),
602  wkey_r_inv, r_vec.begin(), r_vec.end());
603 
604  // debug assert
606  srs.vkey, wkey_r_inv, a.begin(), a.end(), b_r.begin(), b_r.end()));
607 
608  return {com_ab, com_c, ip_ab, agg_c, proof};
609  }
610 
611  template<typename CurveType>
616 
617  public:
623 
624  // Aggregate prove
625  template<typename Hash, typename InputTranscriptIncludeIterator, typename InputProofIterator>
626  static inline proof_type process(const proving_srs_type &srs,
627  InputTranscriptIncludeIterator transcript_include_first,
628  InputTranscriptIncludeIterator transcript_include_last,
629  InputProofIterator proofs_first,
630  InputProofIterator proofs_last) {
631  return aggregate_proofs<CurveType, Hash>(srs, transcript_include_first, transcript_include_last,
632  proofs_first, proofs_last);
633  }
634 
635  // Basic prove
636  static inline basic_proof_type process(const proving_key_type &pk,
637  const primary_input_type &primary_input,
638  const auxiliary_input_type &auxiliary_input) {
639 
640  return basic_prover::process(pk, primary_input, auxiliary_input);
641  }
642  };
643  } // namespace snark
644  } // namespace zk
645  } // namespace crypto3
646 } // namespace nil
647 
648 #endif // CRYPTO3_R1CS_GG_PPZKSNARK_TYPES_POLICY_HPP
void condense()
Definition: polynomial.hpp:363
bool is_zero() const
Definition: polynomial.hpp:353
Definition: snark/proof.hpp:37
static basic_proof_type process(const proving_key_type &pk, const primary_input_type &primary_input, const auxiliary_input_type &auxiliary_input)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:636
policy_type::proving_srs_type proving_srs_type
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:621
static proof_type process(const proving_srs_type &srs, InputTranscriptIncludeIterator transcript_include_first, InputTranscriptIncludeIterator transcript_include_last, InputProofIterator proofs_first, InputProofIterator proofs_last)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:626
policy_type::auxiliary_input_type auxiliary_input_type
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:619
policy_type::primary_input_type primary_input_type
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:618
policy_type::proving_key_type proving_key_type
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:620
policy_type::proof_type proof_type
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:622
Definition: r1cs_gg_ppzksnark/prover.hpp:47
vector(T, U...) -> vector< std::enable_if_t<(std::is_same_v< T, U > &&...), T >, 1+sizeof...(U)>
deduction guide for uniform initialization
decoded_range< UnaryFunction, SinglePassRange > transform(SinglePassRange &rng, UnaryFunction fn)
Definition: decrypted.hpp:100
typename std::iterator_traits< Iterator >::value_type ValueType
Definition: algebra/include/nil/crypto3/detail/make_array.hpp:50
void subtraction(Range &c, const Range &a, const Range &b)
Definition: basic_operations.hpp:112
void reverse(Range &a, std::size_t n)
Definition: basic_operations.hpp:54
std::enable_if< std::is_same< typename CurveType::template g1_type<>::value_type, typename std::iterator_traits< InputG1Iterator1 >::value_type >::value &&std::is_same< typename CurveType::template g2_type<>::value_type, typename std::iterator_traits< InputG2Iterator >::value_type >::value &&std::is_same< typename CurveType::template g1_type<>::value_type, typename std::iterator_traits< InputG1Iterator2 >::value_type >::value &&std::is_same< typename CurveType::scalar_field_type::value_type, typename std::iterator_traits< InputScalarIterator >::value_type >::value, tipp_mipp_proof< CurveType > >::type prove_tipp_mipp(const r1cs_gg_ppzksnark_aggregate_proving_srs< CurveType > &srs, transcript< CurveType, Hash > &tr, InputG1Iterator1 a_first, InputG1Iterator1 a_last, InputG2Iterator b_first, InputG2Iterator b_last, InputG1Iterator2 c_first, InputG1Iterator2 c_last, const r1cs_gg_ppzksnark_ipp2_wkey< CurveType > &wkey, InputScalarIterator r_first, InputScalarIterator r_last)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:466
std::vector< typename FieldType::value_type > structured_scalar_power(std::size_t num, const typename FieldType::value_type &s)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:65
std::pair< typename GroupType::value_type, typename GroupType::value_type > kzg_opening
Definition: snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/proof.hpp:45
std::enable_if< std::is_same< typename GroupType::value_type, typename std::iterator_traits< InputGroupIterator >::value_type >::value &&std::is_same< typename GroupType::curve_type::scalar_field_type::value_type, typename std::iterator_traits< typename InputScalarRange::iterator >::value_type >::value, kzg_opening< GroupType > >::type prove_commitment_key_kzg_opening(InputGroupIterator srs_powers_alpha_first, InputGroupIterator srs_powers_alpha_last, InputGroupIterator srs_powers_beta_first, InputGroupIterator srs_powers_beta_last, const InputScalarRange &poly, const typename GroupType::curve_type::scalar_field_type::value_type &eval_poly, const typename GroupType::curve_type::scalar_field_type::value_type &kzg_challenge)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:171
std::enable_if< std::is_same< typename CurveType::template g1_type<>::value_type, ValueType >::value||std::is_same< typename CurveType::template g2_type<>::value_type, ValueType >::value||std::is_same< typename CurveType::scalar_field_type::value_type, ValueType >::value >::type compress(InputRange &vec, std::size_t split, const typename CurveType::scalar_field_type::value_type &scalar)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:82
ProvingMode
Definition: modes.hpp:33
std::enable_if< std::is_same< typename CurveType::template g2_type<>::value_type, typename std::iterator_traits< InputG2Iterator >::value_type >::value &&std::is_same< typename CurveType::scalar_field_type::value_type, typename std::iterator_traits< InputScalarIterator >::value_type >::value, kzg_opening< typename CurveType::template g2_type<> > >::type prove_commitment_v(InputG2Iterator srs_powers_alpha_first, InputG2Iterator srs_powers_alpha_last, InputG2Iterator srs_powers_beta_first, InputG2Iterator srs_powers_beta_last, InputScalarIterator transcript_first, InputScalarIterator transcript_last, const typename CurveType::scalar_field_type::value_type &kzg_challenge)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:223
std::enable_if< std::is_same< typename std::iterator_traits< InputFieldValueIterator >::value_type, typename FieldType::value_type >::value, typename FieldType::value_type >::type polynomial_evaluation_product_form_from_transcript(InputFieldValueIterator transcript_first, InputFieldValueIterator transcript_last, const typename FieldType::value_type &z, const typename FieldType::value_type &r_shift)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:100
std::enable_if< std::is_same< typename std::iterator_traits< InputFieldValueIterator >::value_type, typename FieldType::value_type >::value, std::vector< typename FieldType::value_type > >::type polynomial_coefficients_from_transcript(InputFieldValueIterator transcript_first, InputFieldValueIterator transcript_last, const typename FieldType::value_type &r_shift)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:141
std::enable_if< std::is_same< typename CurveType::template g1_type<>::value_type, typename std::iterator_traits< InputG1Iterator >::value_type >::value &&std::is_same< typename CurveType::scalar_field_type::value_type, typename std::iterator_traits< InputScalarIterator >::value_type >::value, kzg_opening< typename CurveType::template g1_type<> > >::type prove_commitment_w(InputG1Iterator srs_powers_alpha_first, InputG1Iterator srs_powers_alpha_last, InputG1Iterator srs_powers_beta_first, InputG1Iterator srs_powers_beta_last, InputScalarIterator transcript_first, InputScalarIterator transcript_last, typename CurveType::scalar_field_type::value_type r_shift, const typename CurveType::scalar_field_type::value_type &kzg_challenge)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:250
std::enable_if< std::is_same< std::uint8_t, typename std::iterator_traits< InputTranscriptIncludeIterator >::value_type >::value &&std::is_same< typename std::iterator_traits< InputProofIterator >::value_type, r1cs_gg_ppzksnark_proof< CurveType > >::value, r1cs_gg_ppzksnark_aggregate_proof< CurveType > >::type aggregate_proofs(const r1cs_gg_ppzksnark_aggregate_proving_srs< CurveType > &srs, InputTranscriptIncludeIterator tr_include_first, InputTranscriptIncludeIterator tr_include_last, InputProofIterator proofs_first, InputProofIterator proofs_last)
Aggregate n zkSnark proofs, where n must be a power of two.
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:514
std::enable_if< std::is_same< typename CurveType::template g1_type<>::value_type, typename std::iterator_traits< InputG1Iterator1 >::value_type >::value &&std::is_same< typename CurveType::template g2_type<>::value_type, typename std::iterator_traits< InputG2Iterator >::value_type >::value &&std::is_same< typename CurveType::scalar_field_type::value_type, typename std::iterator_traits< InputScalarIterator >::value_type >::value &&std::is_same< typename CurveType::template g1_type<>::value_type, typename std::iterator_traits< InputG1Iterator2 >::value_type >::value, std::tuple< gipa_proof< CurveType >, std::vector< typename CurveType::scalar_field_type::value_type >, std::vector< typename CurveType::scalar_field_type::value_type > > >::type gipa_tipp_mipp(transcript< CurveType, Hash > &tr, InputG1Iterator1 a_first, InputG1Iterator1 a_last, InputG2Iterator b_first, InputG2Iterator b_last, InputG1Iterator2 c_first, InputG1Iterator2 c_last, const r1cs_gg_ppzksnark_ipp2_vkey< CurveType > &vkey_input, const r1cs_gg_ppzksnark_ipp2_wkey< CurveType > &wkey_input, InputScalarIterator r_first, InputScalarIterator r_last)
Definition: r1cs_gg_ppzksnark/ipp2/prover.hpp:296
Definition: pair.hpp:31
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/detail/basic_policy.hpp:168
r1cs_auxiliary_input< typename curve_type::scalar_field_type > auxiliary_input_type
Definition: zk/include/nil/crypto3/zk/snark/systems/ppzksnark/r1cs_gg_ppzksnark/detail/basic_policy.hpp:182
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: snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/proof.hpp:50
Definition: snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/proof.hpp:96
std::vector< g1_value_type > g_beta_powers
_{i=n}^{N}$ where N is the smallest size of the two Groth16 CRS.
Definition: srs.hpp:88
std::vector< g2_value_type > h_beta_powers
_{i=0}^{N}$ where N is the smallest size of the two Groth16 CRS.
Definition: srs.hpp:90
std::vector< g1_value_type > g_alpha_powers
_{i=0}^{N}$ where N is the smallest size of the two Groth16 CRS.
Definition: srs.hpp:84
vkey_type vkey
commitment key using in MIPP and TIPP
Definition: srs.hpp:92
wkey_type wkey
commitment key using in TIPP
Definition: srs.hpp:94
bool has_correct_len(std::size_t n) const
Definition: srs.hpp:77
std::vector< g2_value_type > h_alpha_powers
_{i=0}^{N}$ where N is the smallest size of the two Groth16 CRS.
Definition: srs.hpp:86
std::pair< r1cs_gg_ppzksnark_ipp2_commitment_key< group_type >, r1cs_gg_ppzksnark_ipp2_commitment_key< group_type > > split(std::size_t at) const
Returns the left and right commitment key part. It makes copy.
Definition: commitment.hpp:127
std::vector< group_value_type > a
Exponent is a.
Definition: commitment.hpp:90
r1cs_gg_ppzksnark_ipp2_commitment_key< group_type > scale(InputIterator s_first, InputIterator s_last) const
Definition: commitment.hpp:108
r1cs_gg_ppzksnark_ipp2_commitment_key< group_type > compress(const r1cs_gg_ppzksnark_ipp2_commitment_key< group_type > &right, const field_value_type &scale) const
Definition: commitment.hpp:156
std::pair< group_value_type, group_value_type > first() const
Definition: commitment.hpp:180
std::vector< group_value_type > b
Exponent is b.
Definition: commitment.hpp:92
static output_type pair(const vkey_type &vkey, const wkey_type &wkey, InputG1Iterator a_first, InputG1Iterator a_last, InputG2Iterator b_first, InputG2Iterator b_last)
Definition: commitment.hpp:222
static output_type single(const vkey_type &vkey, InputG1Iterator a_first, InputG1Iterator a_last)
Definition: commitment.hpp:270
r1cs_gg_ppzksnark_ipp2_commitment_output< curve_type > output_type
Definition: commitment.hpp:211
Definition: snark/systems/ppzksnark/r1cs_gg_ppzksnark/proof.hpp:40
Definition: systems/ppzksnark/r1cs_gg_ppzksnark/proving_key.hpp:39
Definition: snark/systems/ppzksnark/r1cs_gg_ppzksnark/ipp2/proof.hpp:85
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