Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
mnt_final_exponentiation.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of interfaces for final exponentiation gadgets.
5 
6  See weierstrass_final_exponentiation.hpp .
7 
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  *****************************************************************************/
13 
14 #ifndef LIBSNARK_GADGETLIB1_GADGETS_PAIRING_MNT_MNT_FINAL_EXPONENTIATION_TCC_
15 #define LIBSNARK_GADGETLIB1_GADGETS_PAIRING_MNT_MNT_FINAL_EXPONENTIATION_TCC_
16 
17 #include "libsnark/gadgetlib1/gadgets/basic_gadgets.hpp"
18 #include "libsnark/gadgetlib1/gadgets/pairing/mnt/mnt_pairing_params.hpp"
19 
20 namespace libsnark
21 {
22 
23 template<typename ppT>
24 mnt4_final_exp_gadget<ppT>::mnt4_final_exp_gadget(
25  protoboard<FieldT> &pb,
26  const Fqk_variable<ppT> &el,
27  const pb_variable<FieldT> &result_is_one,
28  const std::string &annotation_prefix)
29  : gadget<FieldT>(pb, annotation_prefix)
30  , el(el)
31  , result_is_one(result_is_one)
32 {
33  one.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " one")));
34  el_inv.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " el_inv")));
35  el_q_3.reset(new Fqk_variable<ppT>(el.Frobenius_map(3)));
36  el_q_3_minus_1.reset(
37  new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " el_q_3_minus_1")));
38  alpha.reset(new Fqk_variable<ppT>(el_q_3_minus_1->Frobenius_map(1)));
39  beta.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " beta")));
40  beta_q.reset(new Fqk_variable<ppT>(beta->Frobenius_map(1)));
41 
42  el_inv_q_3.reset(new Fqk_variable<ppT>(el_inv->Frobenius_map(3)));
43  el_inv_q_3_minus_1.reset(new Fqk_variable<ppT>(
44  pb, FMT(annotation_prefix, " el_inv_q_3_minus_1")));
45  inv_alpha.reset(
46  new Fqk_variable<ppT>(el_inv_q_3_minus_1->Frobenius_map(1)));
47  inv_beta.reset(
48  new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " inv_beta")));
49  w1.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " w1")));
50  w0.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " w0")));
51  result.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " result")));
52 
53  compute_el_inv.reset(new Fqk_mul_gadget<ppT>(
54  pb, el, *el_inv, *one, FMT(annotation_prefix, " compute_el_inv")));
55  compute_el_q_3_minus_1.reset(new Fqk_mul_gadget<ppT>(
56  pb,
57  *el_q_3,
58  *el_inv,
59  *el_q_3_minus_1,
60  FMT(annotation_prefix, " compute_el_q_3_minus_1")));
61  compute_beta.reset(new Fqk_mul_gadget<ppT>(
62  pb,
63  *alpha,
64  *el_q_3_minus_1,
65  *beta,
66  FMT(annotation_prefix, " compute_beta")));
67 
68  compute_el_inv_q_3_minus_1.reset(new Fqk_mul_gadget<ppT>(
69  pb,
70  *el_inv_q_3,
71  el,
72  *el_inv_q_3_minus_1,
73  FMT(annotation_prefix, " compute_el_inv__q_3_minus_1")));
74  compute_inv_beta.reset(new Fqk_mul_gadget<ppT>(
75  pb,
76  *inv_alpha,
77  *el_inv_q_3_minus_1,
78  *inv_beta,
79  FMT(annotation_prefix, " compute_inv_beta")));
80 
81  compute_w1.reset(new exponentiation_gadget<
82  FqkT<ppT>,
83  Fp6_2over3_variable,
84  Fp6_2over3_mul_gadget,
85  Fp6_2over3_cyclotomic_sqr_gadget,
86  libff::mnt6_q_limbs>(
87  pb,
88  *beta_q,
89  libff::mnt6_final_exponent_last_chunk_w1,
90  *w1,
91  FMT(annotation_prefix, " compute_w1")));
92 
93  compute_w0.reset(new exponentiation_gadget<
94  FqkT<ppT>,
95  Fp6_2over3_variable,
96  Fp6_2over3_mul_gadget,
97  Fp6_2over3_cyclotomic_sqr_gadget,
98  libff::mnt6_q_limbs>(
99  pb,
100  (libff::mnt6_final_exponent_last_chunk_is_w0_neg ? *inv_beta : *beta),
101  libff::mnt6_final_exponent_last_chunk_abs_of_w0,
102  *w0,
103  FMT(annotation_prefix, " compute_w0")));
104 
105  compute_result.reset(new Fqk_mul_gadget<ppT>(
106  pb, *w1, *w0, *result, FMT(annotation_prefix, " compute_result")));
107 }
108 
109 template<typename ppT>
110 void mnt4_final_exp_gadget<ppT>::generate_r1cs_constraints()
111 {
112  one->generate_r1cs_equals_const_constraints(
113  libff::Fqk<other_curve<ppT>>::one());
114 
115  compute_el_inv->generate_r1cs_constraints();
116  compute_el_q_3_minus_1->generate_r1cs_constraints();
117  compute_beta->generate_r1cs_constraints();
118 
119  compute_el_inv_q_3_minus_1->generate_r1cs_constraints();
120  compute_inv_beta->generate_r1cs_constraints();
121 
122  compute_w0->generate_r1cs_constraints();
123  compute_w1->generate_r1cs_constraints();
124  compute_result->generate_r1cs_constraints();
125 
126  generate_boolean_r1cs_constraint<FieldT>(
127  this->pb,
128  result_is_one,
129  FMT(this->annotation_prefix, " result_is_one"));
130  this->pb.add_r1cs_constraint(
131  r1cs_constraint<FieldT>(result_is_one, 1 - result->c0.c0, 0),
132  " check c0.c0");
133  this->pb.add_r1cs_constraint(
134  r1cs_constraint<FieldT>(result_is_one, result->c0.c1, 0),
135  " check c0.c1");
136  this->pb.add_r1cs_constraint(
137  r1cs_constraint<FieldT>(result_is_one, result->c0.c2, 0),
138  " check c0.c2");
139  this->pb.add_r1cs_constraint(
140  r1cs_constraint<FieldT>(result_is_one, result->c1.c0, 0),
141  " check c1.c0");
142  this->pb.add_r1cs_constraint(
143  r1cs_constraint<FieldT>(result_is_one, result->c1.c1, 0),
144  " check c1.c1");
145  this->pb.add_r1cs_constraint(
146  r1cs_constraint<FieldT>(result_is_one, result->c1.c2, 0),
147  " check c1.c2");
148 }
149 
150 template<typename ppT> void mnt4_final_exp_gadget<ppT>::generate_r1cs_witness()
151 {
152  one->generate_r1cs_witness(libff::Fqk<other_curve<ppT>>::one());
153  el_inv->generate_r1cs_witness(el.get_element().inverse());
154 
155  compute_el_inv->generate_r1cs_witness();
156  el_q_3->evaluate();
157  compute_el_q_3_minus_1->generate_r1cs_witness();
158  alpha->evaluate();
159  compute_beta->generate_r1cs_witness();
160  beta_q->evaluate();
161 
162  el_inv_q_3->evaluate();
163  compute_el_inv_q_3_minus_1->generate_r1cs_witness();
164  inv_alpha->evaluate();
165  compute_inv_beta->generate_r1cs_witness();
166 
167  compute_w0->generate_r1cs_witness();
168  compute_w1->generate_r1cs_witness();
169  compute_result->generate_r1cs_witness();
170 
171  this->pb.val(result_is_one) =
172  (result->get_element() == one->get_element() ? FieldT::one()
173  : FieldT::zero());
174 }
175 
176 template<typename ppT>
177 mnt6_final_exp_gadget<ppT>::mnt6_final_exp_gadget(
178  protoboard<FieldT> &pb,
179  const Fqk_variable<ppT> &el,
180  const pb_variable<FieldT> &result_is_one,
181  const std::string &annotation_prefix)
182  : gadget<FieldT>(pb, annotation_prefix)
183  , el(el)
184  , result_is_one(result_is_one)
185 {
186  one.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " one")));
187  el_inv.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " el_inv")));
188  el_q_2.reset(new Fqk_variable<ppT>(el.Frobenius_map(2)));
189  el_q_2_minus_1.reset(
190  new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " el_q_2_minus_1")));
191  el_q_3_minus_q.reset(
192  new Fqk_variable<ppT>(el_q_2_minus_1->Frobenius_map(1)));
193  el_inv_q_2.reset(new Fqk_variable<ppT>(el_inv->Frobenius_map(2)));
194  el_inv_q_2_minus_1.reset(new Fqk_variable<ppT>(
195  pb, FMT(annotation_prefix, " el_inv_q_2_minus_1")));
196  w1.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " w1")));
197  w0.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " w0")));
198  result.reset(new Fqk_variable<ppT>(pb, FMT(annotation_prefix, " result")));
199 
200  compute_el_inv.reset(new Fqk_mul_gadget<ppT>(
201  pb, el, *el_inv, *one, FMT(annotation_prefix, " compute_el_inv")));
202  compute_el_q_2_minus_1.reset(new Fqk_mul_gadget<ppT>(
203  pb,
204  *el_q_2,
205  *el_inv,
206  *el_q_2_minus_1,
207  FMT(annotation_prefix, " compute_el_q_2_minus_1")));
208  compute_el_inv_q_2_minus_1.reset(new Fqk_mul_gadget<ppT>(
209  pb,
210  *el_inv_q_2,
211  el,
212  *el_inv_q_2_minus_1,
213  FMT(annotation_prefix, " compute_el_inv_q_2_minus_1")));
214 
215  compute_w1.reset(new exponentiation_gadget<
216  FqkT<ppT>,
217  Fp4_variable,
218  Fp4_mul_gadget,
219  Fp4_cyclotomic_sqr_gadget,
220  libff::mnt4_q_limbs>(
221  pb,
222  *el_q_3_minus_q,
223  libff::mnt4_final_exponent_last_chunk_w1,
224  *w1,
225  FMT(annotation_prefix, " compute_w1")));
226  compute_w0.reset(new exponentiation_gadget<
227  FqkT<ppT>,
228  Fp4_variable,
229  Fp4_mul_gadget,
230  Fp4_cyclotomic_sqr_gadget,
231  libff::mnt4_q_limbs>(
232  pb,
233  (libff::mnt4_final_exponent_last_chunk_is_w0_neg ? *el_inv_q_2_minus_1
234  : *el_q_2_minus_1),
235  libff::mnt4_final_exponent_last_chunk_abs_of_w0,
236  *w0,
237  FMT(annotation_prefix, " compute_w0")));
238  compute_result.reset(new Fqk_mul_gadget<ppT>(
239  pb, *w1, *w0, *result, FMT(annotation_prefix, " compute_result")));
240 }
241 
242 template<typename ppT>
243 void mnt6_final_exp_gadget<ppT>::generate_r1cs_constraints()
244 {
245  one->generate_r1cs_equals_const_constraints(
246  libff::Fqk<other_curve<ppT>>::one());
247 
248  compute_el_inv->generate_r1cs_constraints();
249  compute_el_q_2_minus_1->generate_r1cs_constraints();
250  compute_el_inv_q_2_minus_1->generate_r1cs_constraints();
251  compute_w1->generate_r1cs_constraints();
252  compute_w0->generate_r1cs_constraints();
253  compute_result->generate_r1cs_constraints();
254 
255  generate_boolean_r1cs_constraint<FieldT>(
256  this->pb,
257  result_is_one,
258  FMT(this->annotation_prefix, " result_is_one"));
259  this->pb.add_r1cs_constraint(
260  r1cs_constraint<FieldT>(result_is_one, 1 - result->c0.c0, 0),
261  " check c0.c0");
262  this->pb.add_r1cs_constraint(
263  r1cs_constraint<FieldT>(result_is_one, result->c0.c1, 0),
264  " check c0.c1");
265  this->pb.add_r1cs_constraint(
266  r1cs_constraint<FieldT>(result_is_one, result->c1.c0, 0),
267  " check c1.c0");
268  this->pb.add_r1cs_constraint(
269  r1cs_constraint<FieldT>(result_is_one, result->c1.c1, 0),
270  " check c1.c0");
271 }
272 
273 template<typename ppT> void mnt6_final_exp_gadget<ppT>::generate_r1cs_witness()
274 {
275  one->generate_r1cs_witness(libff::Fqk<other_curve<ppT>>::one());
276  el_inv->generate_r1cs_witness(el.get_element().inverse());
277 
278  compute_el_inv->generate_r1cs_witness();
279  el_q_2->evaluate();
280  compute_el_q_2_minus_1->generate_r1cs_witness();
281  el_q_3_minus_q->evaluate();
282  el_inv_q_2->evaluate();
283  compute_el_inv_q_2_minus_1->generate_r1cs_witness();
284  compute_w1->generate_r1cs_witness();
285  compute_w0->generate_r1cs_witness();
286  compute_result->generate_r1cs_witness();
287 
288  this->pb.val(result_is_one) =
289  (result->get_element() == one->get_element() ? FieldT::one()
290  : FieldT::zero());
291 }
292 
293 } // namespace libsnark
294 
295 #endif // LIBSNARK_GADGETLIB1_GADGETS_PAIRING_MNT_MNT_FINAL_EXPONENTIATION_TCC_