Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
fp6_3over2_gadgets.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3  * @author This file is part of libsnark, developed by Clearmatics Ltd
4  * (originally developed by SCIPR Lab) and contributors
5  * (see AUTHORS).
6  * @copyright MIT license (see LICENSE file)
7  *****************************************************************************/
8 
9 #ifndef LIBSNARK_GADGETLIB1_GADGETS_FIELDS_FP6_3OVER2_GADGETS_TCC_
10 #define LIBSNARK_GADGETLIB1_GADGETS_FIELDS_FP6_3OVER2_GADGETS_TCC_
11 
12 #include "libsnark/gadgetlib1/gadgets/fields/fp6_3over2_gadgets.hpp"
13 
14 namespace libsnark
15 {
16 
17 // Fp6_3over2_variable methods
18 
19 template<typename Fp6T>
20 Fp6_3over2_variable<Fp6T>::Fp6_3over2_variable(
21  protoboard<FieldT> &pb, const std::string &annotation_prefix)
22  : gadget<FieldT>(pb, annotation_prefix)
23  , _c0(pb, FMT(annotation_prefix, " c0"))
24  , _c1(pb, FMT(annotation_prefix, " c1"))
25  , _c2(pb, FMT(annotation_prefix, " c2"))
26 {
27 }
28 
29 template<typename Fp6T>
30 Fp6_3over2_variable<Fp6T>::Fp6_3over2_variable(
31  protoboard<FieldT> &pb,
32  const Fp6_3over2_variable<Fp6T> &el,
33  const std::string &annotation_prefix)
34  : gadget<FieldT>(pb, annotation_prefix)
35  , _c0(el._c0)
36  , _c1(el._c1)
37  , _c2(el._c2)
38 {
39 }
40 
41 template<typename Fp6T>
42 Fp6_3over2_variable<Fp6T>::Fp6_3over2_variable(
43  protoboard<FieldT> &pb,
44  const Fp6T &el,
45  const std::string &annotation_prefix)
46  : gadget<FieldT>(pb, annotation_prefix)
47  , _c0(pb, el.coeffs[0], FMT(annotation_prefix, " c0"))
48  , _c1(pb, el.coeffs[1], FMT(annotation_prefix, " c1"))
49  , _c2(pb, el.coeffs[2], FMT(annotation_prefix, " c2"))
50 {
51 }
52 
53 template<typename Fp6T>
54 Fp6_3over2_variable<Fp6T>::Fp6_3over2_variable(
55  protoboard<FieldT> &pb,
56  const Fp2_variable<Fp2T> &c0,
57  const Fp2_variable<Fp2T> &c1,
58  const Fp2_variable<Fp2T> &c2,
59  const std::string &annotation_prefix)
60  : gadget<FieldT>(pb, annotation_prefix), _c0(c0), _c1(c1), _c2(c2)
61 {
62 }
63 
64 template<typename Fp6T>
65 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator*(
66  const FieldT &scalar) const
67 {
68  return Fp6_3over2_variable<Fp6T>(
69  this->pb,
70  _c0 * scalar,
71  _c1 * scalar,
72  _c2 * scalar,
73  FMT(this->annotation_prefix, " fp6_var*scalar"));
74 }
75 
76 template<typename Fp6T>
77 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator*(
78  const Fp2T &fp2_const) const
79 {
80  return Fp6_3over2_variable<Fp6T>(
81  this->pb,
82  _c0 * fp2_const,
83  _c1 * fp2_const,
84  _c2 * fp2_const,
85  FMT(this->annotation_prefix, " fp6_var*fp2_const"));
86 }
87 
88 template<typename Fp6T>
89 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator*(
90  const Fp6T &fp6_const) const
91 {
92  // c0 = a0*b0 + non_residue * (a1*b2 + a2*b1)
93  // c1 = a0*b1 + a1*b0 + non_residue * a2*b2
94  // c3 = a0*b2 + a1*b1 + a2*b0
95  return Fp6_3over2_variable<Fp6T>(
96  this->pb,
97  _c0 * fp6_const.coeffs[0] +
98  (_c1 * fp6_const.coeffs[2] + _c2 * fp6_const.coeffs[1]) *
99  Fp6T::non_residue,
100  _c0 * fp6_const.coeffs[1] + _c1 * fp6_const.coeffs[0] +
101  _c2 * fp6_const.coeffs[2] * Fp6T::non_residue,
102  _c0 * fp6_const.coeffs[2] + _c1 * fp6_const.coeffs[1] +
103  _c2 * fp6_const.coeffs[0],
104  FMT(this->annotation_prefix, " fp6_var*fp6_const"));
105 }
106 
107 template<typename Fp6T>
108 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator+(
109  const Fp6_3over2_variable<Fp6T> &other) const
110 {
111  return Fp6_3over2_variable<Fp6T>(
112  this->pb,
113  _c0 + other._c0,
114  _c1 + other._c1,
115  _c2 + other._c2,
116  FMT(this->annotation_prefix.c_str(), " +other"));
117 }
118 
119 template<typename Fp6T>
120 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator-(
121  const Fp6_3over2_variable<Fp6T> &other) const
122 {
123  return Fp6_3over2_variable<Fp6T>(
124  this->pb,
125  _c0 - other._c0,
126  _c1 - other._c1,
127  _c2 - other._c2,
128  FMT(this->annotation_prefix, " -other"));
129 }
130 
131 template<typename Fp6T>
132 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::operator-() const
133 {
134  return Fp6_3over2_variable<Fp6T>(
135  this->pb,
136  -_c0,
137  -_c1,
138  -_c2,
139  FMT(this->annotation_prefix, " fp6_negate"));
140 }
141 
142 template<typename Fp6T>
143 Fp6_3over2_variable<Fp6T> Fp6_3over2_variable<Fp6T>::frobenius_map(
144  size_t power) const
145 {
146  return Fp6_3over2_variable<Fp6T>(
147  this->pb,
148  _c0.frobenius_map(power),
149  _c1.frobenius_map(power) * Fp6T::Frobenius_coeffs_c1[power % 6],
150  _c2.frobenius_map(power) * Fp6T::Frobenius_coeffs_c2[power % 6],
151  FMT(this->annotation_prefix, " fp6_frobenius_map"));
152 }
153 
154 template<typename Fp6T> void Fp6_3over2_variable<Fp6T>::evaluate() const
155 {
156  _c0.evaluate();
157  _c1.evaluate();
158  _c2.evaluate();
159 }
160 
161 template<typename Fp6T>
162 void Fp6_3over2_variable<Fp6T>::generate_r1cs_witness(const Fp6T &el)
163 {
164  _c0.generate_r1cs_witness(el.coeffs[0]);
165  _c1.generate_r1cs_witness(el.coeffs[1]);
166  _c2.generate_r1cs_witness(el.coeffs[2]);
167 }
168 
169 template<typename Fp6T> Fp6T Fp6_3over2_variable<Fp6T>::get_element() const
170 {
171  return Fp6T(_c0.get_element(), _c1.get_element(), _c2.get_element());
172 }
173 
174 // Fp6_3over2_mul_gadget methods
175 
176 template<typename Fp6T>
177 Fp6_3over2_mul_gadget<Fp6T>::Fp6_3over2_mul_gadget(
178  protoboard<FieldT> &pb,
179  const Fp6_3over2_variable<Fp6T> &A,
180  const Fp6_3over2_variable<Fp6T> &B,
181  const Fp6_3over2_variable<Fp6T> &result,
182  const std::string &annotation_prefix)
183  : gadget<FieldT>(pb, annotation_prefix)
184  , _A(A)
185  , _B(B)
186  , _result(result)
187  , _compute_v1(
188  pb,
189  A._c1,
190  B._c1,
191  Fp2_variable<Fp2T>(pb, FMT(annotation_prefix, " v1")),
192  FMT(annotation_prefix, " _compute_v1"))
193  , _compute_v2(
194  pb,
195  A._c2,
196  B._c2,
197  Fp2_variable<Fp2T>(pb, FMT(annotation_prefix, " v2")),
198  FMT(annotation_prefix, " _compute_v2"))
199  , _compute_a1a2_times_b1b2(
200  pb,
201  A._c1 + A._c2,
202  B._c1 + B._c2,
203  Fp2_variable<Fp2T>(pb, FMT(annotation_prefix, " (a1+a2)*(b1+b2)")),
204  FMT(annotation_prefix, " _compute_a1a2_times_b1b2"))
205  // c0 = a0*b0 + non_residue*((a1 + a2)(b1 + b2) - a1*b1 - a2*b2)
206  , _compute_v0(
207  pb,
208  A._c0,
209  B._c0,
210  _result._c0 - (_compute_a1a2_times_b1b2.result - _compute_v1.result -
211  _compute_v2.result) *
212  Fp6T::non_residue,
213  FMT(annotation_prefix, " _compute_v0"))
214  // c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 + non_residue * a2*b2
215  , _compute_a0a1_times_b0b1(
216  pb,
217  A._c0 + A._c1,
218  B._c0 + B._c1,
219  _result._c1 + _compute_v0.result + _compute_v1.result -
220  _compute_v2.result * Fp6T::non_residue,
221  FMT(annotation_prefix, " _compute_a0a1_times_b0b1"))
222  // c2 = (a0 + a2)(b0 + b2) - a0*b0 - a2*b2 + a1*b1
223  , _compute_a0a2_times_b0b2(
224  pb,
225  A._c0 + A._c2,
226  B._c0 + B._c2,
227  _result._c2 + _compute_v0.result + _compute_v2.result -
228  _compute_v1.result,
229  FMT(annotation_prefix, " _compute_a0a2_times_b0b2"))
230 {
231 }
232 
233 template<typename Fp6T>
234 void Fp6_3over2_mul_gadget<Fp6T>::generate_r1cs_constraints()
235 {
236  _compute_v1.generate_r1cs_constraints();
237  _compute_v2.generate_r1cs_constraints();
238  _compute_a1a2_times_b1b2.generate_r1cs_constraints();
239  _compute_v0.generate_r1cs_constraints();
240  _compute_a0a1_times_b0b1.generate_r1cs_constraints();
241  _compute_a0a2_times_b0b2.generate_r1cs_constraints();
242 }
243 
244 template<typename Fp6T>
245 void Fp6_3over2_mul_gadget<Fp6T>::generate_r1cs_witness()
246 {
247  const Fp2T a0 = _A._c0.get_element();
248  const Fp2T a1 = _A._c1.get_element();
249  const Fp2T a2 = _A._c2.get_element();
250  const Fp2T b0 = _B._c0.get_element();
251  const Fp2T b1 = _B._c1.get_element();
252  const Fp2T b2 = _B._c2.get_element();
253 
254  // c0 = v1 + non_residue*((a1 + a2)(b1 + b2) - v1 - v2)
255  _compute_v1.generate_r1cs_witness();
256  const Fp2T v1 = _compute_v1.result.get_element();
257  _compute_v2.generate_r1cs_witness();
258  const Fp2T v2 = _compute_v2.result.get_element();
259  _compute_a1a2_times_b1b2.A.evaluate();
260  _compute_a1a2_times_b1b2.B.evaluate();
261  _compute_a1a2_times_b1b2.generate_r1cs_witness();
262  const Fp2T a1a2_times_b1b2 = _compute_a1a2_times_b1b2.result.get_element();
263  const Fp2T v0 = a0 * b0;
264  _result._c0.generate_r1cs_witness(
265  v0 + Fp6T::mul_by_non_residue(a1a2_times_b1b2 - v1 - v2));
266  _compute_v0.generate_r1cs_witness();
267 
268  // c1 = (a0 + a1)(b0 + b1) - v1 - v1 + non_residue * v2
269  const Fp2T a0a1_times_b0b1 = (a0 + a1) * (b0 + b1);
270  _result._c1.generate_r1cs_witness(
271  a0a1_times_b0b1 - v0 - v1 + Fp6T::mul_by_non_residue(v2));
272  _compute_a0a1_times_b0b1.A.evaluate();
273  _compute_a0a1_times_b0b1.B.evaluate();
274  _compute_a0a1_times_b0b1.generate_r1cs_witness();
275 
276  // c2 = (a0 + a2)(b0 + b2) - v1 - v2 + v1
277  const Fp2T a0a2_times_b0b2 = (a0 + a2) * (b0 + b2);
278  _result._c2.generate_r1cs_witness(a0a2_times_b0b2 - v0 - v2 + v1);
279  _compute_a0a2_times_b0b2.A.evaluate();
280  _compute_a0a2_times_b0b2.B.evaluate();
281  _compute_a0a2_times_b0b2.generate_r1cs_witness();
282 }
283 
284 } // namespace libsnark
285 
286 #endif // LIBSNARK_GADGETLIB1_GADGETS_FIELDS_FP6_3OVER2_GADGETS_TCC_