2 *****************************************************************************
4 Implementation of interfaces for gadgets for Miller loops.
6 See weierstrass_miller_loop.hpp .
8 *****************************************************************************
9 * @author This file is part of libsnark, developed by SCIPR Lab
10 * and contributors (see AUTHORS).
11 * @copyright MIT license (see LICENSE file)
12 *****************************************************************************/
14 #ifndef LIBSNARK_GADGETLIB1_GADGETS_PAIRING_MNT_MNT_MILLER_LOOP_TCC_
15 #define LIBSNARK_GADGETLIB1_GADGETS_PAIRING_MNT_MNT_MILLER_LOOP_TCC_
17 #include "libsnark/gadgetlib1/constraint_profiling.hpp"
18 #include "libsnark/gadgetlib1/gadgets/basic_gadgets.hpp"
19 #include "libsnark/gadgetlib1/gadgets/pairing/mnt/mnt_miller_loop.hpp"
21 #include <libff/algebra/scalar_multiplication/wnaf.hpp>
29 mnt_Fqk g_RR_at_P = mnt_Fqk(prec_P.PY_twist_squared,
30 -prec_P.PX * c.gamma_twist + c.gamma_X - c.old_RY);
32 (later in Miller loop: f = f.squared() * g_RR_at_P)
35 /* Note the slight interface change: this gadget will allocate g_RR_at_P inside
37 template<typename ppT>
38 mnt_miller_loop_dbl_line_eval<ppT>::mnt_miller_loop_dbl_line_eval(
39 protoboard<FieldT> &pb,
40 const mnt_G1_precomputation<ppT> &prec_P,
41 const mnt_precompute_G2_gadget_coeffs<ppT> &c,
42 std::shared_ptr<Fqk_variable<ppT>> &g_RR_at_P,
43 const std::string &annotation_prefix)
44 : gadget<FieldT>(pb, annotation_prefix)
47 , g_RR_at_P(g_RR_at_P)
49 gamma_twist.reset(new Fqe_variable<ppT>(c.gamma->mul_by_X()));
50 // prec_P.PX * c.gamma_twist = c.gamma_X - c.old_RY - g_RR_at_P_c1
51 if (gamma_twist->is_constant()) {
52 gamma_twist->evaluate();
53 const FqeT gamma_twist_const = gamma_twist->get_element();
54 g_RR_at_P_c1.reset(new Fqe_variable<ppT>(
59 FMT(annotation_prefix, " tmp")) +
60 *(c.gamma_X) + *(c.RY) * (-FieldT::one())));
61 } else if (prec_P.P->X.is_constant()) {
62 prec_P.P->X.evaluate(pb);
63 const FieldT P_X_const = prec_P.P->X.constant_term();
64 g_RR_at_P_c1.reset(new Fqe_variable<ppT>(
65 *gamma_twist * (-P_X_const) + *(c.gamma_X) +
66 *(c.RY) * (-FieldT::one())));
69 new Fqe_variable<ppT>(pb, FMT(annotation_prefix, " g_RR_at_P_c1")));
70 compute_g_RR_at_P_c1.reset(new Fqe_mul_by_lc_gadget<ppT>(
74 *(c.gamma_X) + *(c.RY) * (-FieldT::one()) +
75 (*g_RR_at_P_c1) * (-FieldT::one()),
76 FMT(annotation_prefix, " compute_g_RR_at_P_c1")));
78 g_RR_at_P.reset(new Fqk_variable<ppT>(
80 *(prec_P.PY_twist_squared),
82 FMT(annotation_prefix, " g_RR_at_P")));
85 template<typename ppT>
86 void mnt_miller_loop_dbl_line_eval<ppT>::generate_r1cs_constraints()
88 if (!gamma_twist->is_constant() && !prec_P.P->X.is_constant()) {
89 compute_g_RR_at_P_c1->generate_r1cs_constraints();
93 template<typename ppT>
94 void mnt_miller_loop_dbl_line_eval<ppT>::generate_r1cs_witness()
96 gamma_twist->evaluate();
97 const FqeT gamma_twist_val = gamma_twist->get_element();
98 const FieldT PX_val = this->pb.lc_val(prec_P.P->X);
99 const FqeT gamma_X_val = c.gamma_X->get_element();
100 const FqeT RY_val = c.RY->get_element();
101 const FqeT g_RR_at_P_c1_val =
102 -PX_val * gamma_twist_val + gamma_X_val - RY_val;
103 g_RR_at_P_c1->generate_r1cs_witness(g_RR_at_P_c1_val);
105 if (!gamma_twist->is_constant() && !prec_P.P->X.is_constant()) {
106 compute_g_RR_at_P_c1->generate_r1cs_witness();
108 g_RR_at_P->evaluate();
113 mnt_Fqk g_RQ_at_P = mnt_Fqk(prec_P.PY_twist_squared,
114 -prec_P.PX * c.gamma_twist + c.gamma_X - prec_Q.QY);
116 (later in Miller loop: f = f * g_RQ_at_P)
118 If invert_Q is set to true: use -QY in place of QY everywhere above.
121 /* Note the slight interface change: this gadget will allocate g_RQ_at_P inside
123 template<typename ppT>
124 mnt_miller_loop_add_line_eval<ppT>::mnt_miller_loop_add_line_eval(
125 protoboard<FieldT> &pb,
127 const mnt_G1_precomputation<ppT> &prec_P,
128 const mnt_precompute_G2_gadget_coeffs<ppT> &c,
129 const G2_variable<ppT> &Q,
130 std::shared_ptr<Fqk_variable<ppT>> &g_RQ_at_P,
131 const std::string &annotation_prefix)
132 : gadget<FieldT>(pb, annotation_prefix)
137 , g_RQ_at_P(g_RQ_at_P)
139 gamma_twist.reset(new Fqe_variable<ppT>(c.gamma->mul_by_X()));
140 // prec_P.PX * c.gamma_twist = c.gamma_X - prec_Q.QY - g_RQ_at_P_c1
141 if (gamma_twist->is_constant()) {
142 gamma_twist->evaluate();
143 const FqeT gamma_twist_const = gamma_twist->get_element();
144 g_RQ_at_P_c1.reset(new Fqe_variable<ppT>(
149 FMT(annotation_prefix, " tmp")) +
151 *(Q.Y) * (!invert_Q ? -FieldT::one() : FieldT::one())));
152 } else if (prec_P.P->X.is_constant()) {
153 prec_P.P->X.evaluate(pb);
154 const FieldT P_X_const = prec_P.P->X.constant_term();
155 g_RQ_at_P_c1.reset(new Fqe_variable<ppT>(
156 *gamma_twist * (-P_X_const) + *(c.gamma_X) +
157 *(Q.Y) * (!invert_Q ? -FieldT::one() : FieldT::one())));
160 new Fqe_variable<ppT>(pb, FMT(annotation_prefix, " g_RQ_at_Q_c1")));
161 compute_g_RQ_at_P_c1.reset(new Fqe_mul_by_lc_gadget<ppT>(
166 *(Q.Y) * (!invert_Q ? -FieldT::one() : FieldT::one()) +
167 (*g_RQ_at_P_c1) * (-FieldT::one()),
168 FMT(annotation_prefix, " compute_g_RQ_at_P_c1")));
170 g_RQ_at_P.reset(new Fqk_variable<ppT>(
172 *(prec_P.PY_twist_squared),
174 FMT(annotation_prefix, " g_RQ_at_P")));
177 template<typename ppT>
178 void mnt_miller_loop_add_line_eval<ppT>::generate_r1cs_constraints()
180 if (!gamma_twist->is_constant() && !prec_P.P->X.is_constant()) {
181 compute_g_RQ_at_P_c1->generate_r1cs_constraints();
185 template<typename ppT>
186 void mnt_miller_loop_add_line_eval<ppT>::generate_r1cs_witness()
188 gamma_twist->evaluate();
189 const FqeT gamma_twist_val = gamma_twist->get_element();
190 const FieldT PX_val = this->pb.lc_val(prec_P.P->X);
191 const FqeT gamma_X_val = c.gamma_X->get_element();
192 const FqeT QY_val = Q.Y->get_element();
193 const FqeT g_RQ_at_P_c1_val = -PX_val * gamma_twist_val + gamma_X_val +
194 (!invert_Q ? -QY_val : QY_val);
195 g_RQ_at_P_c1->generate_r1cs_witness(g_RQ_at_P_c1_val);
197 if (!gamma_twist->is_constant() && !prec_P.P->X.is_constant()) {
198 compute_g_RQ_at_P_c1->generate_r1cs_witness();
200 g_RQ_at_P->evaluate();
203 template<typename ppT>
204 mnt_miller_loop_gadget<ppT>::mnt_miller_loop_gadget(
205 protoboard<FieldT> &pb,
206 const mnt_G1_precomputation<ppT> &prec_P,
207 const mnt_G2_precomputation<ppT> &prec_Q,
208 const Fqk_variable<ppT> &result,
209 const std::string &annotation_prefix)
210 : gadget<FieldT>(pb, annotation_prefix)
215 const auto &loop_count = mnt_pairing_params<ppT>::pairing_loop_count;
217 f_count = add_count = dbl_count = 0;
219 bool found_nonzero = false;
220 std::vector<long> NAF = find_wnaf(1, loop_count);
221 for (long i = NAF.size() - 1; i >= 0; --i) {
222 if (!found_nonzero) {
223 /* this skips the MSB itself */
224 found_nonzero |= (NAF[i] != 0);
238 doubling_steps.resize(dbl_count);
239 addition_steps.resize(add_count);
240 g_RR_at_Ps.resize(dbl_count);
241 g_RQ_at_Ps.resize(add_count);
243 for (size_t i = 0; i < f_count; ++i) {
245 new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " fs_%zu", i)));
248 dbl_sqrs.resize(dbl_count);
249 dbl_muls.resize(dbl_count);
250 add_muls.resize(add_count);
257 found_nonzero = false;
258 for (long i = NAF.size() - 1; i >= 0; --i) {
259 if (!found_nonzero) {
260 /* this skips the MSB itself */
261 found_nonzero |= (NAF[i] != 0);
265 doubling_steps[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
268 *prec_Q.coeffs[prec_id],
270 FMT(annotation_prefix, " doubling_steps_%zu", dbl_id)));
272 dbl_sqrs[dbl_id].reset(new Fqk_sqr_gadget<ppT>(
276 FMT(annotation_prefix, " dbl_sqrs_%zu", dbl_id)));
278 dbl_muls[dbl_id].reset(new Fqk_special_mul_gadget(
282 (f_id + 1 == f_count ? result : *fs[f_id + 1]),
283 FMT(annotation_prefix, " dbl_muls_%zu", dbl_id)));
288 addition_steps[add_id].reset(new mnt_miller_loop_add_line_eval<ppT>(
292 *prec_Q.coeffs[prec_id],
295 FMT(annotation_prefix, " addition_steps_%zu", add_id)));
297 add_muls[add_id].reset(new Fqk_special_mul_gadget(
301 (f_id + 1 == f_count ? result : *fs[f_id + 1]),
302 FMT(annotation_prefix, " add_muls_%zu", add_id)));
309 template<typename ppT>
310 void mnt_miller_loop_gadget<ppT>::generate_r1cs_constraints()
312 fs[0]->generate_r1cs_equals_const_constraints(FqkT::one());
314 for (size_t i = 0; i < dbl_count; ++i) {
315 doubling_steps[i]->generate_r1cs_constraints();
316 dbl_sqrs[i]->generate_r1cs_constraints();
317 dbl_muls[i]->generate_r1cs_constraints();
320 for (size_t i = 0; i < add_count; ++i) {
321 addition_steps[i]->generate_r1cs_constraints();
322 add_muls[i]->generate_r1cs_constraints();
326 template<typename ppT> void mnt_miller_loop_gadget<ppT>::generate_r1cs_witness()
328 fs[0]->generate_r1cs_witness(FqkT::one());
333 const auto &loop_count = mnt_pairing_params<ppT>::pairing_loop_count;
335 bool found_nonzero = false;
336 std::vector<long> NAF = find_wnaf(1, loop_count);
337 for (long i = NAF.size() - 1; i >= 0; --i) {
338 if (!found_nonzero) {
339 /* this skips the MSB itself */
340 found_nonzero |= (NAF[i] != 0);
344 doubling_steps[dbl_id]->generate_r1cs_witness();
345 dbl_sqrs[dbl_id]->generate_r1cs_witness();
346 dbl_muls[dbl_id]->generate_r1cs_witness();
350 addition_steps[add_id]->generate_r1cs_witness();
351 add_muls[add_id]->generate_r1cs_witness();
357 template<typename ppT>
358 mnt_e_over_e_miller_loop_gadget<ppT>::mnt_e_over_e_miller_loop_gadget(
359 protoboard<FieldT> &pb,
360 const mnt_G1_precomputation<ppT> &prec_P1,
361 const mnt_G2_precomputation<ppT> &prec_Q1,
362 const mnt_G1_precomputation<ppT> &prec_P2,
363 const mnt_G2_precomputation<ppT> &prec_Q2,
364 const Fqk_variable<ppT> &result,
365 const std::string &annotation_prefix)
366 : gadget<FieldT>(pb, annotation_prefix)
373 const auto &loop_count = mnt_pairing_params<ppT>::pairing_loop_count;
375 f_count = add_count = dbl_count = 0;
377 bool found_nonzero = false;
378 std::vector<long> NAF = find_wnaf(1, loop_count);
379 for (long i = NAF.size() - 1; i >= 0; --i) {
380 if (!found_nonzero) {
381 /* this skips the MSB itself */
382 found_nonzero |= (NAF[i] != 0);
396 doubling_steps1.resize(dbl_count);
397 addition_steps1.resize(add_count);
398 doubling_steps2.resize(dbl_count);
399 addition_steps2.resize(add_count);
400 g_RR_at_P1s.resize(dbl_count);
401 g_RQ_at_P1s.resize(add_count);
402 g_RR_at_P2s.resize(dbl_count);
403 g_RQ_at_P2s.resize(add_count);
405 for (size_t i = 0; i < f_count; ++i) {
407 new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " fs_%zu", i)));
410 dbl_sqrs.resize(dbl_count);
411 dbl_muls1.resize(dbl_count);
412 add_muls1.resize(add_count);
413 dbl_muls2.resize(dbl_count);
414 add_muls2.resize(add_count);
421 found_nonzero = false;
422 for (long i = NAF.size() - 1; i >= 0; --i) {
423 if (!found_nonzero) {
424 /* this skips the MSB itself */
425 found_nonzero |= (NAF[i] != 0);
429 doubling_steps1[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
432 *prec_Q1.coeffs[prec_id],
434 FMT(annotation_prefix, " doubling_steps1_%zu", dbl_id)));
435 doubling_steps2[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
438 *prec_Q2.coeffs[prec_id],
440 FMT(annotation_prefix, " doubling_steps2_%zu", dbl_id)));
443 dbl_sqrs[dbl_id].reset(new Fqk_sqr_gadget<ppT>(
447 FMT(annotation_prefix, " dbl_sqrs_%zu", dbl_id)));
449 dbl_muls1[dbl_id].reset(new Fqk_special_mul_gadget(
452 *g_RR_at_P1s[dbl_id],
454 FMT(annotation_prefix, " dbl_mul1s_%zu", dbl_id)));
456 dbl_muls2[dbl_id].reset(new Fqk_special_mul_gadget(
458 (f_id + 1 == f_count ? result : *fs[f_id + 1]),
459 *g_RR_at_P2s[dbl_id],
461 FMT(annotation_prefix, " dbl_mul2s_%zu", dbl_id)));
466 addition_steps1[add_id].reset(
467 new mnt_miller_loop_add_line_eval<ppT>(
471 *prec_Q1.coeffs[prec_id],
474 FMT(annotation_prefix, " addition_steps1_%zu", add_id)));
475 addition_steps2[add_id].reset(
476 new mnt_miller_loop_add_line_eval<ppT>(
480 *prec_Q2.coeffs[prec_id],
483 FMT(annotation_prefix, " addition_steps2_%zu", add_id)));
485 add_muls1[add_id].reset(new Fqk_special_mul_gadget(
488 *g_RQ_at_P1s[add_id],
490 FMT(annotation_prefix, " add_mul1s_%zu", add_id)));
492 add_muls2[add_id].reset(new Fqk_special_mul_gadget(
494 (f_id + 1 == f_count ? result : *fs[f_id + 1]),
495 *g_RQ_at_P2s[add_id],
497 FMT(annotation_prefix, " add_mul2s_%zu", add_id)));
504 template<typename ppT>
505 void mnt_e_over_e_miller_loop_gadget<ppT>::generate_r1cs_constraints()
507 fs[0]->generate_r1cs_equals_const_constraints(FqkT::one());
509 for (size_t i = 0; i < dbl_count; ++i) {
510 doubling_steps1[i]->generate_r1cs_constraints();
511 doubling_steps2[i]->generate_r1cs_constraints();
512 dbl_sqrs[i]->generate_r1cs_constraints();
513 dbl_muls1[i]->generate_r1cs_constraints();
514 dbl_muls2[i]->generate_r1cs_constraints();
517 for (size_t i = 0; i < add_count; ++i) {
518 addition_steps1[i]->generate_r1cs_constraints();
519 addition_steps2[i]->generate_r1cs_constraints();
520 add_muls1[i]->generate_r1cs_constraints();
521 add_muls2[i]->generate_r1cs_constraints();
525 template<typename ppT>
526 void mnt_e_over_e_miller_loop_gadget<ppT>::generate_r1cs_witness()
528 fs[0]->generate_r1cs_witness(FqkT::one());
534 const auto &loop_count = mnt_pairing_params<ppT>::pairing_loop_count;
536 bool found_nonzero = false;
537 std::vector<long> NAF = find_wnaf(1, loop_count);
538 for (long i = NAF.size() - 1; i >= 0; --i) {
539 if (!found_nonzero) {
540 /* this skips the MSB itself */
541 found_nonzero |= (NAF[i] != 0);
545 doubling_steps1[dbl_id]->generate_r1cs_witness();
546 doubling_steps2[dbl_id]->generate_r1cs_witness();
547 dbl_sqrs[dbl_id]->generate_r1cs_witness();
549 dbl_muls1[dbl_id]->generate_r1cs_witness();
551 (f_id + 1 == f_count ? result : *fs[f_id + 1])
552 .generate_r1cs_witness(
553 fs[f_id]->get_element() *
554 g_RR_at_P2s[dbl_id]->get_element().inverse());
555 dbl_muls2[dbl_id]->generate_r1cs_witness();
560 addition_steps1[add_id]->generate_r1cs_witness();
561 addition_steps2[add_id]->generate_r1cs_witness();
562 add_muls1[add_id]->generate_r1cs_witness();
564 (f_id + 1 == f_count ? result : *fs[f_id + 1])
565 .generate_r1cs_witness(
566 fs[f_id]->get_element() *
567 g_RQ_at_P2s[add_id]->get_element().inverse());
568 add_muls2[add_id]->generate_r1cs_witness();
575 template<typename ppT>
576 mnt_e_times_e_over_e_miller_loop_gadget<ppT>::
577 mnt_e_times_e_over_e_miller_loop_gadget(
578 protoboard<FieldT> &pb,
579 const mnt_G1_precomputation<ppT> &prec_P1,
580 const mnt_G2_precomputation<ppT> &prec_Q1,
581 const mnt_G1_precomputation<ppT> &prec_P2,
582 const mnt_G2_precomputation<ppT> &prec_Q2,
583 const mnt_G1_precomputation<ppT> &prec_P3,
584 const mnt_G2_precomputation<ppT> &prec_Q3,
585 const Fqk_variable<ppT> &result,
586 const std::string &annotation_prefix)
587 : gadget<FieldT>(pb, annotation_prefix)
596 const auto &loop_count = mnt_pairing_params<ppT>::pairing_loop_count;
598 f_count = add_count = dbl_count = 0;
600 bool found_nonzero = false;
601 std::vector<long> NAF = find_wnaf(1, loop_count);
602 for (long i = NAF.size() - 1; i >= 0; --i) {
603 if (!found_nonzero) {
604 /* this skips the MSB itself */
605 found_nonzero |= (NAF[i] != 0);
619 doubling_steps1.resize(dbl_count);
620 addition_steps1.resize(add_count);
621 doubling_steps2.resize(dbl_count);
622 addition_steps2.resize(add_count);
623 doubling_steps3.resize(dbl_count);
624 addition_steps3.resize(add_count);
625 g_RR_at_P1s.resize(dbl_count);
626 g_RQ_at_P1s.resize(add_count);
627 g_RR_at_P2s.resize(dbl_count);
628 g_RQ_at_P2s.resize(add_count);
629 g_RR_at_P3s.resize(dbl_count);
630 g_RQ_at_P3s.resize(add_count);
632 for (size_t i = 0; i < f_count; ++i) {
634 new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " fs_%zu", i)));
637 dbl_sqrs.resize(dbl_count);
638 dbl_muls1.resize(dbl_count);
639 add_muls1.resize(add_count);
640 dbl_muls2.resize(dbl_count);
641 add_muls2.resize(add_count);
642 dbl_muls3.resize(dbl_count);
643 add_muls3.resize(add_count);
650 found_nonzero = false;
651 for (long i = NAF.size() - 1; i >= 0; --i) {
652 if (!found_nonzero) {
653 /* this skips the MSB itself */
654 found_nonzero |= (NAF[i] != 0);
658 doubling_steps1[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
661 *prec_Q1.coeffs[prec_id],
663 FMT(annotation_prefix, " doubling_steps1_%zu", dbl_id)));
664 doubling_steps2[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
667 *prec_Q2.coeffs[prec_id],
669 FMT(annotation_prefix, " doubling_steps2_%zu", dbl_id)));
670 doubling_steps3[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
673 *prec_Q3.coeffs[prec_id],
675 FMT(annotation_prefix, " doubling_steps3_%zu", dbl_id)));
678 dbl_sqrs[dbl_id].reset(new Fqk_sqr_gadget<ppT>(
682 FMT(annotation_prefix, " dbl_sqrs_%zu", dbl_id)));
684 dbl_muls1[dbl_id].reset(new Fqk_special_mul_gadget(
687 *g_RR_at_P1s[dbl_id],
689 FMT(annotation_prefix, " dbl_muls1_%zu", dbl_id)));
691 dbl_muls2[dbl_id].reset(new Fqk_special_mul_gadget(
694 *g_RR_at_P2s[dbl_id],
696 FMT(annotation_prefix, " dbl_muls2_%zu", dbl_id)));
698 dbl_muls3[dbl_id].reset(new Fqk_special_mul_gadget(
700 (f_id + 1 == f_count ? result : *fs[f_id + 1]),
701 *g_RR_at_P3s[dbl_id],
703 FMT(annotation_prefix, " dbl_muls3_%zu", dbl_id)));
708 addition_steps1[add_id].reset(
709 new mnt_miller_loop_add_line_eval<ppT>(
713 *prec_Q1.coeffs[prec_id],
716 FMT(annotation_prefix, " addition_steps1_%zu", add_id)));
717 addition_steps2[add_id].reset(
718 new mnt_miller_loop_add_line_eval<ppT>(
722 *prec_Q2.coeffs[prec_id],
725 FMT(annotation_prefix, " addition_steps2_%zu", add_id)));
726 addition_steps3[add_id].reset(
727 new mnt_miller_loop_add_line_eval<ppT>(
731 *prec_Q3.coeffs[prec_id],
734 FMT(annotation_prefix, " addition_steps3_%zu", add_id)));
736 add_muls1[add_id].reset(new Fqk_special_mul_gadget(
739 *g_RQ_at_P1s[add_id],
741 FMT(annotation_prefix, " add_muls1_%zu", add_id)));
743 add_muls2[add_id].reset(new Fqk_special_mul_gadget(
746 *g_RQ_at_P2s[add_id],
748 FMT(annotation_prefix, " add_muls2_%zu", add_id)));
750 add_muls3[add_id].reset(new Fqk_special_mul_gadget(
752 (f_id + 1 == f_count ? result : *fs[f_id + 1]),
753 *g_RQ_at_P3s[add_id],
755 FMT(annotation_prefix, " add_muls3_%zu", add_id)));
762 template<typename ppT>
763 void mnt_e_times_e_over_e_miller_loop_gadget<ppT>::generate_r1cs_constraints()
765 fs[0]->generate_r1cs_equals_const_constraints(FqkT::one());
767 for (size_t i = 0; i < dbl_count; ++i) {
768 doubling_steps1[i]->generate_r1cs_constraints();
769 doubling_steps2[i]->generate_r1cs_constraints();
770 doubling_steps3[i]->generate_r1cs_constraints();
771 dbl_sqrs[i]->generate_r1cs_constraints();
772 dbl_muls1[i]->generate_r1cs_constraints();
773 dbl_muls2[i]->generate_r1cs_constraints();
774 dbl_muls3[i]->generate_r1cs_constraints();
777 for (size_t i = 0; i < add_count; ++i) {
778 addition_steps1[i]->generate_r1cs_constraints();
779 addition_steps2[i]->generate_r1cs_constraints();
780 addition_steps3[i]->generate_r1cs_constraints();
781 add_muls1[i]->generate_r1cs_constraints();
782 add_muls2[i]->generate_r1cs_constraints();
783 add_muls3[i]->generate_r1cs_constraints();
787 template<typename ppT>
788 void mnt_e_times_e_over_e_miller_loop_gadget<ppT>::generate_r1cs_witness()
790 fs[0]->generate_r1cs_witness(FqkT::one());
796 const auto &loop_count = mnt_pairing_params<ppT>::pairing_loop_count;
798 bool found_nonzero = false;
799 std::vector<long> NAF = find_wnaf(1, loop_count);
800 for (long i = NAF.size() - 1; i >= 0; --i) {
801 if (!found_nonzero) {
802 /* this skips the MSB itself */
803 found_nonzero |= (NAF[i] != 0);
807 doubling_steps1[dbl_id]->generate_r1cs_witness();
808 doubling_steps2[dbl_id]->generate_r1cs_witness();
809 doubling_steps3[dbl_id]->generate_r1cs_witness();
810 dbl_sqrs[dbl_id]->generate_r1cs_witness();
812 dbl_muls1[dbl_id]->generate_r1cs_witness();
814 dbl_muls2[dbl_id]->generate_r1cs_witness();
816 (f_id + 1 == f_count ? result : *fs[f_id + 1])
817 .generate_r1cs_witness(
818 fs[f_id]->get_element() *
819 g_RR_at_P3s[dbl_id]->get_element().inverse());
820 dbl_muls3[dbl_id]->generate_r1cs_witness();
825 addition_steps1[add_id]->generate_r1cs_witness();
826 addition_steps2[add_id]->generate_r1cs_witness();
827 addition_steps3[add_id]->generate_r1cs_witness();
828 add_muls1[add_id]->generate_r1cs_witness();
830 add_muls2[add_id]->generate_r1cs_witness();
832 (f_id + 1 == f_count ? result : *fs[f_id + 1])
833 .generate_r1cs_witness(
834 fs[f_id]->get_element() *
835 g_RQ_at_P3s[add_id]->get_element().inverse());
836 add_muls3[add_id]->generate_r1cs_witness();
843 template<typename ppT>
844 mnt_e_times_e_times_e_over_e_miller_loop_gadget<ppT>::
845 mnt_e_times_e_times_e_over_e_miller_loop_gadget(
846 protoboard<FieldT> &pb,
847 const G1_precomputation<ppT> &prec_P1,
848 const G2_precomputation<ppT> &prec_Q1,
849 const G1_precomputation<ppT> &prec_P2,
850 const G2_precomputation<ppT> &prec_Q2,
851 const G1_precomputation<ppT> &prec_P3,
852 const G2_precomputation<ppT> &prec_Q3,
853 const G1_precomputation<ppT> &prec_P4,
854 const G2_precomputation<ppT> &prec_Q4,
855 const Fqk_variable<ppT> &result,
856 const std::string &annotation_prefix)
857 : gadget<FieldT>(pb, annotation_prefix)
868 const auto &loop_count = mnt_pairing_params<ppT>::pairing_loop_count;
870 f_count = add_count = dbl_count = 0;
872 bool found_nonzero = false;
873 std::vector<long> NAF = find_wnaf(1, loop_count);
874 for (long i = NAF.size() - 1; i >= 0; --i) {
875 if (!found_nonzero) {
876 /* this skips the MSB itself */
877 found_nonzero |= (NAF[i] != 0);
891 doubling_steps1.resize(dbl_count);
892 addition_steps1.resize(add_count);
893 doubling_steps2.resize(dbl_count);
894 addition_steps2.resize(add_count);
895 doubling_steps3.resize(dbl_count);
896 addition_steps3.resize(add_count);
897 doubling_steps4.resize(dbl_count);
898 addition_steps4.resize(add_count);
899 g_RR_at_P1s.resize(dbl_count);
900 g_RQ_at_P1s.resize(add_count);
901 g_RR_at_P2s.resize(dbl_count);
902 g_RQ_at_P2s.resize(add_count);
903 g_RR_at_P3s.resize(dbl_count);
904 g_RQ_at_P3s.resize(add_count);
905 g_RR_at_P4s.resize(dbl_count);
906 g_RQ_at_P4s.resize(add_count);
908 for (size_t i = 0; i < f_count; ++i) {
910 new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " fs_%zu", i)));
913 dbl_sqrs.resize(dbl_count);
914 dbl_muls1.resize(dbl_count);
915 add_muls1.resize(add_count);
916 dbl_muls2.resize(dbl_count);
917 add_muls2.resize(add_count);
918 dbl_muls3.resize(dbl_count);
919 add_muls3.resize(add_count);
920 dbl_muls4.resize(dbl_count);
921 add_muls4.resize(add_count);
928 found_nonzero = false;
929 for (long i = NAF.size() - 1; i >= 0; --i) {
930 if (!found_nonzero) {
931 /* this skips the MSB itself */
932 found_nonzero |= (NAF[i] != 0);
936 doubling_steps1[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
939 *prec_Q1.coeffs[prec_id],
941 FMT(annotation_prefix, " doubling_steps1_%zu", dbl_id)));
942 doubling_steps2[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
945 *prec_Q2.coeffs[prec_id],
947 FMT(annotation_prefix, " doubling_steps2_%zu", dbl_id)));
948 doubling_steps3[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
951 *prec_Q3.coeffs[prec_id],
953 FMT(annotation_prefix, " doubling_steps3_%zu", dbl_id)));
954 doubling_steps4[dbl_id].reset(new mnt_miller_loop_dbl_line_eval<ppT>(
957 *prec_Q4.coeffs[prec_id],
959 FMT(annotation_prefix, " doubling_steps4_%zu", dbl_id)));
962 dbl_sqrs[dbl_id].reset(new Fqk_sqr_gadget<ppT>(
966 FMT(annotation_prefix, " dbl_sqrs_%zu", dbl_id)));
968 dbl_muls1[dbl_id].reset(new Fqk_special_mul_gadget(
971 *g_RR_at_P1s[dbl_id],
973 FMT(annotation_prefix, " dbl_muls1_%zu", dbl_id)));
975 dbl_muls2[dbl_id].reset(new Fqk_special_mul_gadget(
978 *g_RR_at_P2s[dbl_id],
980 FMT(annotation_prefix, " dbl_muls2_%zu", dbl_id)));
982 dbl_muls3[dbl_id].reset(new Fqk_special_mul_gadget(
985 *g_RR_at_P3s[dbl_id],
987 FMT(annotation_prefix, " dbl_muls3_%zu", dbl_id)));
989 dbl_muls4[dbl_id].reset(new Fqk_special_mul_gadget(
991 (f_id + 1 == f_count ? result : *fs[f_id + 1]),
992 *g_RR_at_P4s[dbl_id],
994 FMT(annotation_prefix, " dbl_muls4_%zu", dbl_id)));
999 addition_steps1[add_id].reset(
1000 new mnt_miller_loop_add_line_eval<ppT>(
1004 *prec_Q1.coeffs[prec_id],
1006 g_RQ_at_P1s[add_id],
1007 FMT(annotation_prefix, " addition_steps1_%zu", add_id)));
1008 addition_steps2[add_id].reset(
1009 new mnt_miller_loop_add_line_eval<ppT>(
1013 *prec_Q2.coeffs[prec_id],
1015 g_RQ_at_P2s[add_id],
1016 FMT(annotation_prefix, " addition_steps2_%zu", add_id)));
1017 addition_steps3[add_id].reset(
1018 new mnt_miller_loop_add_line_eval<ppT>(
1022 *prec_Q3.coeffs[prec_id],
1024 g_RQ_at_P3s[add_id],
1025 FMT(annotation_prefix, " addition_steps3_%zu", add_id)));
1026 addition_steps4[add_id].reset(
1027 new mnt_miller_loop_add_line_eval<ppT>(
1031 *prec_Q4.coeffs[prec_id],
1033 g_RQ_at_P4s[add_id],
1034 FMT(annotation_prefix, " addition_steps4_%zu", add_id)));
1036 add_muls1[add_id].reset(new Fqk_special_mul_gadget(
1039 *g_RQ_at_P1s[add_id],
1041 FMT(annotation_prefix, " add_muls1_%zu", add_id)));
1043 add_muls2[add_id].reset(new Fqk_special_mul_gadget(
1046 *g_RQ_at_P2s[add_id],
1048 FMT(annotation_prefix, " add_muls2_%zu", add_id)));
1050 add_muls3[add_id].reset(new Fqk_special_mul_gadget(
1053 *g_RQ_at_P3s[add_id],
1055 FMT(annotation_prefix, " add_muls3_%zu", add_id)));
1057 add_muls4[add_id].reset(new Fqk_special_mul_gadget(
1059 (f_id + 1 == f_count ? result : *fs[f_id + 1]),
1060 *g_RQ_at_P4s[add_id],
1062 FMT(annotation_prefix, " add_muls4_%zu", add_id)));
1069 template<typename ppT>
1070 void mnt_e_times_e_times_e_over_e_miller_loop_gadget<
1071 ppT>::generate_r1cs_constraints()
1073 fs[0]->generate_r1cs_equals_const_constraints(FqkT::one());
1075 for (size_t i = 0; i < dbl_count; ++i) {
1076 doubling_steps1[i]->generate_r1cs_constraints();
1077 doubling_steps2[i]->generate_r1cs_constraints();
1078 doubling_steps3[i]->generate_r1cs_constraints();
1079 doubling_steps4[i]->generate_r1cs_constraints();
1080 dbl_sqrs[i]->generate_r1cs_constraints();
1081 dbl_muls1[i]->generate_r1cs_constraints();
1082 dbl_muls2[i]->generate_r1cs_constraints();
1083 dbl_muls3[i]->generate_r1cs_constraints();
1084 dbl_muls4[i]->generate_r1cs_constraints();
1087 for (size_t i = 0; i < add_count; ++i) {
1088 addition_steps1[i]->generate_r1cs_constraints();
1089 addition_steps2[i]->generate_r1cs_constraints();
1090 addition_steps3[i]->generate_r1cs_constraints();
1091 addition_steps4[i]->generate_r1cs_constraints();
1092 add_muls1[i]->generate_r1cs_constraints();
1093 add_muls2[i]->generate_r1cs_constraints();
1094 add_muls3[i]->generate_r1cs_constraints();
1095 add_muls4[i]->generate_r1cs_constraints();
1099 template<typename ppT>
1100 void mnt_e_times_e_times_e_over_e_miller_loop_gadget<
1101 ppT>::generate_r1cs_witness()
1103 fs[0]->generate_r1cs_witness(FqkT::one());
1109 const auto &loop_count = mnt_pairing_params<ppT>::pairing_loop_count;
1111 bool found_nonzero = false;
1112 std::vector<long> NAF = find_wnaf(1, loop_count);
1113 for (long i = NAF.size() - 1; i >= 0; --i) {
1114 if (!found_nonzero) {
1115 /* this skips the MSB itself */
1116 found_nonzero |= (NAF[i] != 0);
1120 doubling_steps1[dbl_id]->generate_r1cs_witness();
1121 doubling_steps2[dbl_id]->generate_r1cs_witness();
1122 doubling_steps3[dbl_id]->generate_r1cs_witness();
1123 doubling_steps4[dbl_id]->generate_r1cs_witness();
1124 dbl_sqrs[dbl_id]->generate_r1cs_witness();
1126 dbl_muls1[dbl_id]->generate_r1cs_witness();
1128 dbl_muls2[dbl_id]->generate_r1cs_witness();
1130 dbl_muls3[dbl_id]->generate_r1cs_witness();
1132 (f_id + 1 == f_count ? result : *fs[f_id + 1])
1133 .generate_r1cs_witness(
1134 fs[f_id]->get_element() *
1135 g_RR_at_P4s[dbl_id]->get_element().inverse());
1136 dbl_muls4[dbl_id]->generate_r1cs_witness();
1141 addition_steps1[add_id]->generate_r1cs_witness();
1142 addition_steps2[add_id]->generate_r1cs_witness();
1143 addition_steps3[add_id]->generate_r1cs_witness();
1144 addition_steps4[add_id]->generate_r1cs_witness();
1145 add_muls1[add_id]->generate_r1cs_witness();
1147 add_muls2[add_id]->generate_r1cs_witness();
1149 add_muls3[add_id]->generate_r1cs_witness();
1151 (f_id + 1 == f_count ? result : *fs[f_id + 1])
1152 .generate_r1cs_witness(
1153 fs[f_id]->get_element() *
1154 g_RQ_at_P4s[add_id]->get_element().inverse());
1155 add_muls4[add_id]->generate_r1cs_witness();
1162 } // namespace libsnark
1164 #endif // LIBSNARK_GADGETLIB1_GADGETS_PAIRING_MNT_MNT_MILLER_LOOP_TCC_