2 *****************************************************************************
3 * @author This file is part of libsnark, developed by Clearmatics Ltd
4 * (originally developed by SCIPR Lab) and contributors
6 * @copyright MIT license (see LICENSE file)
7 *****************************************************************************/
9 #ifndef LIBSNARK_GADGETLIB1_GADGETS_PAIRING_BW6_761_BLS12_377_BLS12_377_MILLER_LOOP_TCC_
10 #define LIBSNARK_GADGETLIB1_GADGETS_PAIRING_BW6_761_BLS12_377_BLS12_377_MILLER_LOOP_TCC_
12 #include "libsnark/gadgetlib1/gadgets/basic_gadgets.hpp"
13 #include "libsnark/gadgetlib1/gadgets/pairing/bw6_761_bls12_377/bls12_377_miller_loop.hpp"
18 // bls12_377_ate_compute_f_ell_P methods
20 template<typename ppT>
21 bls12_377_ate_compute_f_ell_P<ppT>::bls12_377_ate_compute_f_ell_P(
22 protoboard<FieldT> &pb,
23 const pb_linear_combination<FieldT> &Px,
24 const pb_linear_combination<FieldT> &Py,
25 const bls12_377_ate_ell_coeffs<ppT> &ell_coeffs,
26 const Fp12_2over3over2_variable<FqkT> &f,
27 const Fp12_2over3over2_variable<FqkT> &f_out,
28 const std::string &annotation_prefix)
29 : gadget<FieldT>(pb, annotation_prefix)
30 , _compute_ell_vv_times_Px(
34 Fqe_variable<ppT>(pb, FMT(annotation_prefix, " ell_vv_times_Px")),
35 FMT(annotation_prefix, " _compute_ell_vv_times_Px"))
36 , _compute_ell_vw_times_Py(
40 Fqe_variable<ppT>(pb, FMT(annotation_prefix, " ell_vw_times_Py")),
41 FMT(annotation_prefix, " _compute_ell_vw_times_Py"))
42 , _compute_f_mul_ell_P(
46 _compute_ell_vv_times_Px.result,
47 _compute_ell_vw_times_Py.result,
49 FMT(annotation_prefix, " _compute_f_mul_ell_P"))
53 template<typename ppT>
54 const Fp12_2over3over2_variable<libff::Fqk<other_curve<ppT>>>
55 &bls12_377_ate_compute_f_ell_P<ppT>::result() const
57 return _compute_f_mul_ell_P.result();
60 template<typename ppT>
61 void bls12_377_ate_compute_f_ell_P<ppT>::generate_r1cs_constraints()
63 _compute_ell_vv_times_Px.generate_r1cs_constraints();
64 _compute_ell_vw_times_Py.generate_r1cs_constraints();
65 _compute_f_mul_ell_P.generate_r1cs_constraints();
68 template<typename ppT>
69 void bls12_377_ate_compute_f_ell_P<ppT>::generate_r1cs_witness()
71 _compute_ell_vv_times_Px.generate_r1cs_witness();
72 _compute_ell_vw_times_Py.generate_r1cs_witness();
73 _compute_f_mul_ell_P.generate_r1cs_witness();
76 // bls12_377_miller_loop_gadget methods
78 template<typename ppT>
79 bls12_377_miller_loop_gadget<ppT>::bls12_377_miller_loop_gadget(
80 protoboard<FieldT> &pb,
81 const bls12_377_G1_precomputation<ppT> &prec_P,
82 const bls12_377_G2_precomputation<ppT> &prec_Q,
83 const Fqk_variable<ppT> &result,
84 const std::string &annotation_prefix)
85 : gadget<FieldT>(pb, annotation_prefix)
86 , _f0(pb, FqkT::one(), FMT(annotation_prefix, " f0"))
89 const Fp12_2over3over2_variable<FqkT> *f = &_f0;
91 bls12_377_miller_loop_bits bits;
95 std::shared_ptr<Fp12_2over3over2_square_gadget<FqkT>>(
96 new Fp12_2over3over2_square_gadget<FqkT>(
99 Fp12_2over3over2_variable<FqkT>(
100 pb, FMT(annotation_prefix, " f^2")),
101 FMT(annotation_prefix, " _f_squared[%zu]", bits.index()))));
102 f = &_f_squared.back()->result();
105 _f_ell_P.push_back(std::shared_ptr<bls12_377_ate_compute_f_ell_P<ppT>>(
106 new bls12_377_ate_compute_f_ell_P<ppT>(
110 *prec_Q._coeffs[coeff_idx++],
112 Fp12_2over3over2_variable<FqkT>(
113 pb, FMT(annotation_prefix, " f^2*ell(P)")),
114 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size()))));
115 f = &_f_ell_P.back()->result();
117 if (bits.current()) {
121 std::shared_ptr<bls12_377_ate_compute_f_ell_P<ppT>>(
122 new bls12_377_ate_compute_f_ell_P<ppT>(
126 *prec_Q._coeffs[coeff_idx++],
129 FMT(annotation_prefix,
134 std::shared_ptr<bls12_377_ate_compute_f_ell_P<ppT>>(
135 new bls12_377_ate_compute_f_ell_P<ppT>(
139 *prec_Q._coeffs[coeff_idx++],
141 Fp12_2over3over2_variable<FqkT>(
142 pb, FMT(annotation_prefix, " f*ell(P)")),
143 FMT(annotation_prefix,
147 f = &_f_ell_P.back()->result();
152 template<typename ppT>
153 const Fp12_2over3over2_variable<libff::Fqk<other_curve<ppT>>>
154 &bls12_377_miller_loop_gadget<ppT>::result() const
156 return _f_ell_P.back()->result();
159 template<typename ppT>
160 void bls12_377_miller_loop_gadget<ppT>::generate_r1cs_constraints()
162 // TODO: everything is allocated, so constraint generation does not need
163 // to be done in this order. For now, keep a consistent loop.
166 size_t f_ell_P_idx = 0;
167 bls12_377_miller_loop_bits bits;
168 while (bits.next()) {
169 _f_squared[sqr_idx++]->generate_r1cs_constraints();
170 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
171 if (bits.current()) {
172 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
176 assert(sqr_idx == _f_squared.size());
177 assert(f_ell_P_idx == _f_ell_P.size());
180 template<typename ppT>
181 void bls12_377_miller_loop_gadget<ppT>::generate_r1cs_witness()
184 size_t f_ell_P_idx = 0;
185 bls12_377_miller_loop_bits bits;
186 while (bits.next()) {
187 _f_squared[sqr_idx++]->generate_r1cs_witness();
188 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
189 if (bits.current()) {
190 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
194 assert(sqr_idx == _f_squared.size());
195 assert(f_ell_P_idx == _f_ell_P.size());
198 template<typename ppT>
199 bls12_377_e_over_e_miller_loop_gadget<ppT>::
200 bls12_377_e_over_e_miller_loop_gadget(
201 protoboard<libff::Fr<ppT>> &pb,
202 const bls12_377_G1_precomputation<ppT> &P1_prec,
203 const bls12_377_G2_precomputation<ppT> &Q1_prec,
204 const bls12_377_G1_precomputation<ppT> &P2_prec,
205 const bls12_377_G2_precomputation<ppT> &Q2_prec,
206 const Fp12_2over3over2_variable<FqkT> &result,
207 const std::string &annotation_prefix)
208 : gadget<FieldT>(pb, annotation_prefix)
209 , _f0(pb, FqkT::one(), FMT(annotation_prefix, " f0"))
212 _minus_P2_Y.assign(pb, -(*P2_prec._Py));
213 size_t coeff_idx = 0;
214 const Fp12_2over3over2_variable<FqkT> *f = &_f0;
216 bls12_377_miller_loop_bits bits;
217 while (bits.next()) {
219 _f_squared.emplace_back(new Fp12_2over3over2_square_gadget<FqkT>(
222 Fp12_2over3over2_variable<FqkT>(pb, FMT(annotation_prefix, "f^2")),
223 FMT(annotation_prefix, " _f_squared[%zu]", _f_squared.size())));
224 f = &_f_squared.back()->result();
226 // f <- f^2 * ell_Q1(P1)
227 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
231 *Q1_prec._coeffs[coeff_idx],
233 Fp12_2over3over2_variable<FqkT>(
234 pb, FMT(annotation_prefix, " f^2*ell_Q1(P1)")),
235 FMT(annotation_prefix, " _f_ell_P1[%zu]", _f_ell_P.size())));
236 f = &_f_ell_P.back()->result();
238 // f <- f^2 * ell_Q2(P2)
239 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
243 *Q2_prec._coeffs[coeff_idx],
245 Fp12_2over3over2_variable<FqkT>(
246 pb, FMT(annotation_prefix, " f^2*ell_Q2(P2)")),
247 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
248 f = &_f_ell_P.back()->result();
250 assert(0 == _f_ell_P.size() % 2);
254 if (bits.current()) {
255 // f <- f * ell_Q1(P1)
256 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
260 *Q1_prec._coeffs[coeff_idx],
262 Fp12_2over3over2_variable<FqkT>(
263 pb, FMT(annotation_prefix, " f*ell_Q1(P2)")),
264 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
265 f = &_f_ell_P.back()->result();
267 // f <- f * ell_Q2(P2)
269 _f_ell_P.emplace_back(
270 std::shared_ptr<bls12_377_ate_compute_f_ell_P<ppT>>(
271 new bls12_377_ate_compute_f_ell_P<ppT>(
275 *Q2_prec._coeffs[coeff_idx],
278 FMT(annotation_prefix,
282 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
286 *Q2_prec._coeffs[coeff_idx],
288 Fp12_2over3over2_variable<FqkT>(
289 pb, FMT(annotation_prefix, " f*ell_Q2(P2)")),
290 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
292 f = &_f_ell_P.back()->result();
294 assert(0 == _f_ell_P.size() % 2);
301 template<typename ppT>
302 void bls12_377_e_over_e_miller_loop_gadget<ppT>::generate_r1cs_constraints()
305 size_t f_ell_P_idx = 0;
306 bls12_377_miller_loop_bits bits;
307 while (bits.next()) {
308 _f_squared[sqr_idx++]->generate_r1cs_constraints();
309 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
310 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
311 if (bits.current()) {
312 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
313 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
317 assert(sqr_idx == _f_squared.size());
318 assert(f_ell_P_idx == _f_ell_P.size());
321 template<typename ppT>
322 void bls12_377_e_over_e_miller_loop_gadget<ppT>::generate_r1cs_witness()
324 _minus_P2_Y.evaluate(this->pb);
326 size_t f_ell_P_idx = 0;
327 bls12_377_miller_loop_bits bits;
328 while (bits.next()) {
329 _f_squared[sqr_idx++]->generate_r1cs_witness();
330 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
331 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
332 if (bits.current()) {
333 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
334 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
338 assert(sqr_idx == _f_squared.size());
339 assert(f_ell_P_idx == _f_ell_P.size());
342 template<typename ppT>
343 bls12_377_e_times_e_times_e_over_e_miller_loop_gadget<ppT>::
344 bls12_377_e_times_e_times_e_over_e_miller_loop_gadget(
345 protoboard<libff::Fr<ppT>> &pb,
346 const bls12_377_G1_precomputation<ppT> &P1_prec,
347 const bls12_377_G2_precomputation<ppT> &Q1_prec,
348 const bls12_377_G1_precomputation<ppT> &P2_prec,
349 const bls12_377_G2_precomputation<ppT> &Q2_prec,
350 const bls12_377_G1_precomputation<ppT> &P3_prec,
351 const bls12_377_G2_precomputation<ppT> &Q3_prec,
352 const bls12_377_G1_precomputation<ppT> &P4_prec,
353 const bls12_377_G2_precomputation<ppT> &Q4_prec,
354 const Fp12_2over3over2_variable<FqkT> &result,
355 const std::string &annotation_prefix)
356 : gadget<FieldT>(pb, annotation_prefix)
357 , _f0(pb, FqkT::one(), FMT(annotation_prefix, " f0"))
360 _minus_P4_Y.assign(pb, -(*P4_prec._Py));
361 size_t coeff_idx = 0;
362 const Fp12_2over3over2_variable<FqkT> *f = &_f0;
364 bls12_377_miller_loop_bits bits;
365 while (bits.next()) {
367 _f_squared.emplace_back(new Fp12_2over3over2_square_gadget<FqkT>(
370 Fp12_2over3over2_variable<FqkT>(pb, FMT(annotation_prefix, "f^2")),
371 FMT(annotation_prefix, " _f_squared[%zu]", _f_squared.size())));
372 f = &_f_squared.back()->result();
374 // f <- f^2 * ell_Q1(P1)
375 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
379 *Q1_prec._coeffs[coeff_idx],
381 Fp12_2over3over2_variable<FqkT>(
382 pb, FMT(annotation_prefix, " f^2*ell_Q1(P1)")),
383 FMT(annotation_prefix, " _f_ell_P1[%zu]", _f_ell_P.size())));
384 f = &_f_ell_P.back()->result();
386 // f <- f^2 * ell_Q2(P2)
387 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
391 *Q2_prec._coeffs[coeff_idx],
393 Fp12_2over3over2_variable<FqkT>(
394 pb, FMT(annotation_prefix, " f^2*ell_Q2(P2)")),
395 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
396 f = &_f_ell_P.back()->result();
398 // f <- f^2 * ell_Q3(P3)
399 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
403 *Q3_prec._coeffs[coeff_idx],
405 Fp12_2over3over2_variable<FqkT>(
406 pb, FMT(annotation_prefix, " f^2*ell_Q3(P3)")),
407 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
408 f = &_f_ell_P.back()->result();
410 // f <- f^2 * ell_Q4(P4)
411 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
415 *Q4_prec._coeffs[coeff_idx],
417 Fp12_2over3over2_variable<FqkT>(
418 pb, FMT(annotation_prefix, " f^2*ell_Q4(P4)")),
419 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
420 f = &_f_ell_P.back()->result();
422 assert(0 == _f_ell_P.size() % 4);
426 if (bits.current()) {
427 // f <- f * ell_Q1(P1)
428 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
432 *Q1_prec._coeffs[coeff_idx],
434 Fp12_2over3over2_variable<FqkT>(
435 pb, FMT(annotation_prefix, " f*ell_Q1(P2)")),
436 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
437 f = &_f_ell_P.back()->result();
439 // f <- f * ell_Q2(P2)
440 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
444 *Q2_prec._coeffs[coeff_idx],
446 Fp12_2over3over2_variable<FqkT>(
447 pb, FMT(annotation_prefix, " f*ell_Q2(P2)")),
448 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
449 f = &_f_ell_P.back()->result();
451 // f <- f * ell_Q3(P3)
452 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
456 *Q3_prec._coeffs[coeff_idx],
458 Fp12_2over3over2_variable<FqkT>(
459 pb, FMT(annotation_prefix, " f*ell_Q3(P3)")),
460 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
461 f = &_f_ell_P.back()->result();
463 // f <- f * ell_Q4(P4)
465 _f_ell_P.emplace_back(
466 std::shared_ptr<bls12_377_ate_compute_f_ell_P<ppT>>(
467 new bls12_377_ate_compute_f_ell_P<ppT>(
471 *Q4_prec._coeffs[coeff_idx],
474 FMT(annotation_prefix,
478 _f_ell_P.emplace_back(new bls12_377_ate_compute_f_ell_P<ppT>(
482 *Q4_prec._coeffs[coeff_idx],
484 Fp12_2over3over2_variable<FqkT>(
485 pb, FMT(annotation_prefix, " f*ell_Q4(P4)")),
486 FMT(annotation_prefix, " _f_ell_P[%zu]", _f_ell_P.size())));
488 f = &_f_ell_P.back()->result();
490 assert(0 == _f_ell_P.size() % 4);
497 template<typename ppT>
498 void bls12_377_e_times_e_times_e_over_e_miller_loop_gadget<
499 ppT>::generate_r1cs_constraints()
502 size_t f_ell_P_idx = 0;
503 bls12_377_miller_loop_bits bits;
504 while (bits.next()) {
505 _f_squared[sqr_idx++]->generate_r1cs_constraints();
506 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
507 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
508 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
509 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
510 if (bits.current()) {
511 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
512 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
513 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
514 _f_ell_P[f_ell_P_idx++]->generate_r1cs_constraints();
518 assert(sqr_idx == _f_squared.size());
519 assert(f_ell_P_idx == _f_ell_P.size());
522 template<typename ppT>
523 void bls12_377_e_times_e_times_e_over_e_miller_loop_gadget<
524 ppT>::generate_r1cs_witness()
526 _minus_P4_Y.evaluate(this->pb);
528 size_t f_ell_P_idx = 0;
529 bls12_377_miller_loop_bits bits;
530 while (bits.next()) {
531 _f_squared[sqr_idx++]->generate_r1cs_witness();
532 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
533 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
534 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
535 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
536 if (bits.current()) {
537 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
538 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
539 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
540 _f_ell_P[f_ell_P_idx++]->generate_r1cs_witness();
544 assert(sqr_idx == _f_squared.size());
545 assert(f_ell_P_idx == _f_ell_P.size());
548 } // namespace libsnark
550 #endif // LIBSNARK_GADGETLIB1_GADGETS_PAIRING_BW6_761_BLS12_377_BLS12_377_MILLER_LOOP_TCC_