element_fp4.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 //
5 // MIT License
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 //---------------------------------------------------------------------------//
25 // @file Declaration of interfaces for Fp4 components.
26 //
27 // The components verify field arithmetic in Fp4 = Fp2[V]/(V^2-U) where
28 // Fp2 = Fp[U]/(U^2-non_residue) and non_residue is in Fp.
29 //---------------------------------------------------------------------------//
30 
31 #ifndef CRYPTO3_ZK_BLUEPRINT_FP4_COMPONENTS_HPP
32 #define CRYPTO3_ZK_BLUEPRINT_FP4_COMPONENTS_HPP
33 
36 
38 
39 namespace nil {
40  namespace crypto3 {
41  namespace zk {
42  namespace components {
43 
44  /******************************** element_fp4 ************************************/
45 
49  template<typename Fp4T>
50  struct element_fp4 : public component<typename Fp4T::base_field_type> {
51 
52  using field_type = Fp4T;
53  using base_field_type = typename field_type::base_field_type;
54  using underlying_field_type = typename field_type::underlying_field_type;
55 
57 
58  using data_type =
59  std::array<underlying_element_type, field_type::arity / underlying_field_type::arity>;
60 
62 
66  }
67 
68  element_fp4(blueprint<base_field_type> &bp, const typename field_type::value_type &el) :
70  data({underlying_element_type(bp, el.data[0]), underlying_element_type(bp, el.data[1])}) {
71  }
72 
74  const underlying_element_type &in_data1) :
76  data({underlying_element_type(in_data0), underlying_element_type(in_data1)}) {
77  }
78 
79  void generate_r1cs_equals_const_constraints(const typename field_type::value_type &el) {
80  data[0].generate_r1cs_equals_const_constraints(el.data[0]);
81  data[1].generate_r1cs_equals_const_constraints(el.data[1]);
82  }
83 
84  void generate_r1cs_witness(const typename field_type::value_type &el) {
85  data[0].generate_r1cs_witness(el.data[0]);
86  data[1].generate_r1cs_witness(el.data[1]);
87  }
88 
89  typename field_type::value_type get_element() {
90  typename field_type::value_type el;
91  el.data[0] = data[0].get_element();
92  el.data[1] = data[1].get_element();
93  return el;
94  }
95 
96  element_fp4<field_type> Frobenius_map(const std::size_t power) const {
97  blueprint_linear_combination<base_field_type> new_c0c0, new_c0c1, new_c1c0, new_c1c1;
98  new_c0c0.assign(this->bp, data[0].data[0]);
99  new_c0c1.assign(this->bp,
100  data[0].data[1] * underlying_field_type::Frobenius_coeffs_c1[power % 2]);
101  new_c1c0.assign(this->bp, data[1].data[0] * field_type::Frobenius_coeffs_c1[power % 4]);
102  new_c1c1.assign(this->bp,
103  data[1].data[1] * field_type::Frobenius_coeffs_c1[power % 4] *
104  underlying_field_type::Frobenius_coeffs_c1[power % 2]);
105 
106  return element_fp4<field_type>(this->bp,
107  underlying_element_type(this->bp, new_c0c0, new_c0c1),
108  underlying_element_type(this->bp, new_c1c0, new_c1c1));
109  }
110 
111  void evaluate() const {
112  data[0].evaluate();
113  data[1].evaluate();
114  }
115  };
116 
117  /******************************** element_fp4_tower_mul ************************************/
118 
122  template<typename Fp4T>
123  class element_fp4_tower_mul : public component<typename Fp4T::base_field_type> {
124  public:
125  using field_type = Fp4T;
126  using base_field_type = typename field_type::base_field_type;
127  using underlying_field_type = typename field_type::underlying_field_type;
128 
130 
134 
137 
140  std::shared_ptr<underlying_element_type> Ac0_plus_Ac1;
141 
142  std::shared_ptr<underlying_element_type> v0;
143  std::shared_ptr<underlying_element_type> v1;
144 
147  std::shared_ptr<underlying_element_type> Bc0_plus_Bc1;
148 
151 
152  std::shared_ptr<underlying_element_type> result_c1_plus_v0_plus_v1;
153 
154  std::shared_ptr<element_fp2_mul<underlying_field_type>> compute_v0;
155  std::shared_ptr<element_fp2_mul<underlying_field_type>> compute_v1;
156  std::shared_ptr<element_fp2_mul<underlying_field_type>> compute_result_c1;
157 
159  const element_fp4<field_type> &A,
160  const element_fp4<field_type> &B,
163  A(A), B(B), result(result) {
164  /*
165  Karatsuba multiplication for Fp4 as a quadratic extension of Fp2:
166  v0 = A.data[0] * B.data[0]
167  v1 = A.data[1] * B.data[1]
168  result.data[0] = v0 + non_residue * v1
169  result.data[1] = (A.data[0] + A.data[1]) * (B.data[0] + B.data[1]) - v0 - v1
170  where "non_residue * elem" := (non_residue * elt.data[1], elt.data[0])
171 
172  Enforced with 3 element_fp2_mul's that ensure that:
173  A.data[1] * B.data[1] = v1
174  A.data[0] * B.data[0] = v0
175  (A.data[0]+A.data[1])*(B.data[0]+B.data[1]) = result.data[1] + v0 + v1
176 
177  Reference:
178  "Multiplication and Squaring on Pairing-Friendly Fields"
179  Devegili, OhEigeartaigh, Scott, Dahab
180  */
181  v1.reset(new underlying_element_type(bp));
182 
184 
185  v0_c0.assign(bp, result.data[0].data[0] - field_type::value_type::non_residue * v1->data[1]);
186 
187  v0_c1.assign(bp, result.data[0].data[1] - v1->data[0]);
188  v0.reset(new underlying_element_type(bp, v0_c0, v0_c1));
189 
191 
192  Ac0_plus_Ac1_c0.assign(bp, A.data[0].data[0] + A.data[1].data[0]);
193  Ac0_plus_Ac1_c1.assign(bp, A.data[0].data[1] + A.data[1].data[1]);
195 
196  Bc0_plus_Bc1_c0.assign(bp, B.data[0].data[0] + B.data[1].data[0]);
197  Bc0_plus_Bc1_c1.assign(bp, B.data[0].data[1] + B.data[1].data[1]);
199 
200  result_c1_plus_v0_plus_v1_c0.assign(bp, result.data[1].data[0] + v0->data[0] + v1->data[0]);
201  result_c1_plus_v0_plus_v1_c1.assign(bp, result.data[1].data[1] + v0->data[1] + v1->data[1]);
204 
207  }
208 
210  compute_v0->generate_r1cs_constraints();
211  compute_v1->generate_r1cs_constraints();
212  compute_result_c1->generate_r1cs_constraints();
213  }
214 
216  compute_v0->generate_r1cs_witness();
217  compute_v1->generate_r1cs_witness();
218 
219  Ac0_plus_Ac1_c0.evaluate(this->bp);
220  Ac0_plus_Ac1_c1.evaluate(this->bp);
221 
222  Bc0_plus_Bc1_c0.evaluate(this->bp);
223  Bc0_plus_Bc1_c1.evaluate(this->bp);
224 
225  compute_result_c1->generate_r1cs_witness();
226 
227  const typename field_type::value_type Aval = A.get_element();
228  const typename field_type::value_type Bval = B.get_element();
229  const typename field_type::value_type Rval = Aval * Bval;
230 
232  }
233  };
234 
235  /******************************** element_fp4_direct_mul ************************************/
236 
240  template<typename Fp4T>
241  class element_fp4_direct_mul : public component<typename Fp4T::base_field_type> {
242  public:
243  using field_type = Fp4T;
244  using base_field_type = typename field_type::base_field_type;
245  using underlying_field_type = typename field_type::underlying_field_type;
246 
248 
249  using base_field_value_type = typename base_field_type::value_type;
250 
254 
258 
260  const element_fp4<field_type> &A,
261  const element_fp4<field_type> &B,
264  A(A), B(B), result(result) {
265  /*
266  Tom-Cook-4x for Fp4 (beta is the quartic non-residue):
267  v0 = a0*b0,
268  v1 = (a0+a1+a2+a3)*(b0+b1+b2+b3),
269  v2 = (a0-a1+a2-a3)*(b0-b1+b2-b3),
270  v3 = (a0+2a1+4a2+8a3)*(b0+2b1+4b2+8b3),
271  v4 = (a0-2a1+4a2-8a3)*(b0-2b1+4b2-8b3),
272  v5 = (a0+3a1+9a2+27a3)*(b0+3b1+9b2+27b3),
273  v6 = a3*b3
274 
275  result.data[0] = v0+beta((1/4)v0-(1/6)(v1+v2)+(1/24)(v3+v4)-5v6),
276  result.data[1] =
277  -(1/3)v0+v1-(1/2)v2-(1/4)v3+(1/20)v4+(1/30)v5-12v6+beta(-(1/12)(v0-v1)+(1/24)(v2-v3)-(1/120)(v4-v5)-3v6),
278  result.c2 = -(5/4)v0+(2/3)(v1+v2)-(1/24)(v3+v4)+4v6+beta v6,
279  result.c3 = (1/12)(5v0-7v1)-(1/24)(v2-7v3+v4+v5)+15v6
280 
281  Enforced with 7 constraints. Doing so requires some care, as we first
282  compute three of the v_i explicitly, and then "inline" result.data[0]/c1/c2/c3
283  in computations of the remaining four v_i.
284 
285  Concretely, we first compute v1, v2 and v6 explicitly, via 3 constraints as above.
286  v1 = (a0+a1+a2+a3)*(b0+b1+b2+b3),
287  v2 = (a0-a1+a2-a3)*(b0-b1+b2-b3),
288  v6 = a3*b3
289 
290  Then we use the following 4 additional constraints:
291  (1-beta) v0 = c0 + beta c2 - (beta v1)/2 - (beta v2)/ 2 - (-1 + beta) beta v6
292  (1-beta) v3 = -15 c0 - 30 c1 - 3 (4 + beta) c2 - 6 (4 + beta) c3 + (24 - (3 beta)/2)
293  v1
294  +
295  (-8 + beta/2) v2 + 3 (-16 + beta) (-1 + beta) v6 (1-beta) v4 = -15 c0 + 30 c1 - 3 (4 +
296  beta) c2 + 6 (4 + beta) c3 + (-8 + beta/2) v1 + (24 - (3 beta)/2) v2 + 3 (-16 + beta) (-1
297  + beta) v6 (1-beta) v5 = -80 c0 - 240 c1 - 8 (9 + beta) c2 - 24 (9 + beta) c3 - 2 (-81 +
298  beta) v1 +
299  (-81 + beta) v2 + 8 (-81 + beta) (-1 + beta) v6
300 
301  The isomorphism between the representation above and towering is:
302  (a0, a1, a2, a3) <-> (a.data[0].data[0], a.data[1].data[0], a.data[0].data[1],
303  a.data[1].data[1])
304 
305  Reference:
306  "Multiplication and Squaring on Pairing-Friendly Fields"
307  Devegili, OhEigeartaigh, Scott, Dahab
308 
309  NOTE: the expressions above were cherry-picked from the Mathematica result
310  of the following command:
311 
312  (# -> Solve[{c0 == v0+beta((1/4)v0-(1/6)(v1+v2)+(1/24)(v3+v4)-5v6),
313  c1 ==
314  -(1/3)v0+v1-(1/2)v2-(1/4)v3+(1/20)v4+(1/30)v5-12v6+beta(-(1/12)(v0-v1)+(1/24)(v2-v3)-(1/120)(v4-v5)-3v6),
315  c2
316  == -(5/4)v0+(2/3)(v1+v2)-(1/24)(v3+v4)+4v6+beta v6, c3 ==
317  (1/12)(5v0-7v1)-(1/24)(v2-7v3+v4+v5)+15v6}, #] // FullSimplify) & /@ Subsets[{v0, v1, v2,
318  v3, v4, v5}, {4}]
319 
320  and simplified by multiplying the selected result by (1-beta)
321  */
322  v1.allocate(bp);
323  v2.allocate(bp);
324  v6.allocate(bp);
325  }
326 
328  const base_field_value_type beta = field_type::value_type::non_residue;
329 
330  const base_field_value_type u = (base_field_value_type::one() - beta).inversed();
331 
333  &a1 = A.data[1].data[0],
334  &a2 = A.data[0].data[1],
335  &a3 = A.data[1].data[1],
336  &b0 = B.data[0].data[0],
337  &b1 = B.data[1].data[0],
338  &b2 = B.data[0].data[1],
339  &b3 = B.data[1].data[1],
340  &c0 = result.data[0].data[0],
341  &c1 = result.data[1].data[0],
342  &c2 = result.data[0].data[1],
343  &c3 = result.data[1].data[1];
344 
345  this->bp.add_r1cs_constraint(
346  snark::r1cs_constraint<base_field_type>(a0 + a1 + a2 + a3, b0 + b1 + b2 + b3, v1));
347  this->bp.add_r1cs_constraint(
348  snark::r1cs_constraint<base_field_type>(a0 - a1 + a2 - a3, b0 - b1 + b2 - b3, v2));
349  this->bp.add_r1cs_constraint(snark::r1cs_constraint<base_field_type>(a3, b3, v6));
350 
351  this->bp.add_r1cs_constraint(snark::r1cs_constraint<base_field_type>(
352  a0,
353  b0,
354  u * c0 + beta * u * c2 - beta * u * base_field_value_type(0x02).inversed() * v1 -
355  beta * u * base_field_value_type(0x02).inversed() * v2 + beta * v6));
356  this->bp.add_r1cs_constraint(snark::r1cs_constraint<base_field_type>(
357  a0 + base_field_value_type(0x02) * a1 + base_field_value_type(0x04) * a2 +
358  base_field_value_type(0x08) * a3,
359  b0 + base_field_value_type(0x02) * b1 + base_field_value_type(0x04) * b2 +
360  base_field_value_type(0x08) * b3,
361  -base_field_value_type(15) * u * c0 - base_field_value_type(30) * u * c1 -
362  base_field_value_type(0x03) * (base_field_value_type(0x04) + beta) * u * c2 -
363  base_field_value_type(6) * (base_field_value_type(0x04) + beta) * u * c3 +
364  (base_field_value_type(24) -
365  base_field_value_type(0x03) * beta * base_field_value_type(0x02).inversed()) *
366  u * v1 +
367  (-base_field_value_type(0x08) + beta * base_field_value_type(0x02).inversed()) * u *
368  v2 -
369  base_field_value_type(0x03) * (-base_field_value_type(16) + beta) * v6));
370  this->bp.add_r1cs_constraint(snark::r1cs_constraint<base_field_type>(
371  a0 - base_field_value_type(0x02) * a1 + base_field_value_type(0x04) * a2 -
372  base_field_value_type(0x08) * a3,
373  b0 - base_field_value_type(0x02) * b1 + base_field_value_type(0x04) * b2 -
374  base_field_value_type(0x08) * b3,
375  -base_field_value_type(15) * u * c0 + base_field_value_type(30) * u * c1 -
376  base_field_value_type(0x03) * (base_field_value_type(0x04) + beta) * u * c2 +
377  base_field_value_type(6) * (base_field_value_type(0x04) + beta) * u * c3 +
378  (base_field_value_type(24) -
379  base_field_value_type(0x03) * beta * base_field_value_type(0x02).inversed()) *
380  u * v2 +
381  (-base_field_value_type(0x08) + beta * base_field_value_type(0x02).inversed()) * u *
382  v1 -
383  base_field_value_type(0x03) * (-base_field_value_type(16) + beta) * v6));
384  this->bp.add_r1cs_constraint(snark::r1cs_constraint<base_field_type>(
385  a0 + base_field_value_type(0x03) * a1 + base_field_value_type(0x09) * a2 +
386  base_field_value_type(27) * a3,
387  b0 + base_field_value_type(0x03) * b1 + base_field_value_type(0x09) * b2 +
388  base_field_value_type(27) * b3,
389  -base_field_value_type(80) * u * c0 - base_field_value_type(240) * u * c1 -
390  base_field_value_type(0x08) * (base_field_value_type(0x09) + beta) * u * c2 -
391  base_field_value_type(24) * (base_field_value_type(0x09) + beta) * u * c3 -
392  base_field_value_type(0x02) * (-base_field_value_type(81) + beta) * u * v1 +
393  (-base_field_value_type(81) + beta) * u * v2 -
394  base_field_value_type(0x08) * (-base_field_value_type(81) + beta) * v6));
395  }
396 
399  &a1 = A.data[1].data[0],
400  &a2 = A.data[0].data[1],
401  &a3 = A.data[1].data[1],
402  &b0 = B.data[0].data[0],
403  &b1 = B.data[1].data[0],
404  &b2 = B.data[0].data[1],
405  &b3 = B.data[1].data[1];
406 
407  this->bp.val(v1) =
408  ((this->bp.lc_val(a0) + this->bp.lc_val(a1) + this->bp.lc_val(a2) + this->bp.lc_val(a3)) *
409  (this->bp.lc_val(b0) + this->bp.lc_val(b1) + this->bp.lc_val(b2) + this->bp.lc_val(b3)));
410  this->bp.val(v2) =
411  ((this->bp.lc_val(a0) - this->bp.lc_val(a1) + this->bp.lc_val(a2) - this->bp.lc_val(a3)) *
412  (this->bp.lc_val(b0) - this->bp.lc_val(b1) + this->bp.lc_val(b2) - this->bp.lc_val(b3)));
413  this->bp.val(v6) = this->bp.lc_val(a3) * this->bp.lc_val(b3);
414 
415  const typename field_type::value_type Aval = A.get_element();
416  const typename field_type::value_type Bval = B.get_element();
417  const typename field_type::value_type Rval = Aval * Bval;
418 
420  }
421  };
422 
426  template<typename Fp4T>
428 
429  /******************************** element_fp4_squared ************************************/
430 
434  template<typename Fp4T>
435  class element_fp4_squared : public component<typename Fp4T::base_field_type> {
436  public:
437  using field_type = Fp4T;
438  using base_field_type = typename field_type::base_field_type;
439  using underlying_field_type = typename field_type::underlying_field_type;
440 
442 
445 
446  std::shared_ptr<underlying_element_type> v1;
447 
450  std::shared_ptr<underlying_element_type> v0;
451 
452  std::shared_ptr<element_fp2_squared<underlying_field_type>> compute_v0;
453  std::shared_ptr<element_fp2_squared<underlying_field_type>> compute_v1;
454 
457  std::shared_ptr<underlying_element_type> Ac0_plus_Ac1;
458 
461 
462  std::shared_ptr<underlying_element_type> result_c1_plus_v0_plus_v1;
463 
464  std::shared_ptr<element_fp2_squared<underlying_field_type>> compute_result_c1;
465 
467  const element_fp4<field_type> &A,
470  A(A), result(result) {
471  /*
472  Karatsuba squaring for Fp4 as a quadratic extension of Fp2:
473  v0 = A.data[0]^2
474  v1 = A.data[1]^2
475  result.data[0] = v0 + non_residue * v1
476  result.data[1] = (A.data[0] + A.data[1])^2 - v0 - v1
477  where "non_residue * elem" := (non_residue * elt.data[1], elt.data[0])
478 
479  Enforced with 3 element_fp2_squared's that ensure that:
480  A.data[1]^2 = v1
481  A.data[0]^2 = v0
482  (A.data[0]+A.data[1])^2 = result.data[1] + v0 + v1
483 
484  Reference:
485  "Multiplication and Squaring on Pairing-Friendly Fields"
486  Devegili, OhEigeartaigh, Scott, Dahab
487  */
488 
489  v1.reset(new underlying_element_type(bp));
491 
492  v0_c0.assign(bp, result.data[0].data[0] - field_type::value_type::non_residue * v1->data[1]);
493 
494  v0_c1.assign(bp, result.data[0].data[1] - v1->data[0]);
495  v0.reset(new underlying_element_type(bp, v0_c0, v0_c1));
496 
498 
499  Ac0_plus_Ac1_c0.assign(bp, A.data[0].data[0] + A.data[1].data[0]);
500  Ac0_plus_Ac1_c1.assign(bp, A.data[0].data[1] + A.data[1].data[1]);
502 
503  result_c1_plus_v0_plus_v1_c0.assign(bp, result.data[1].data[0] + v0->data[0] + v1->data[0]);
504  result_c1_plus_v0_plus_v1_c1.assign(bp, result.data[1].data[1] + v0->data[1] + v1->data[1]);
507 
510  }
511 
513  compute_v1->generate_r1cs_constraints();
514  compute_v0->generate_r1cs_constraints();
515  compute_result_c1->generate_r1cs_constraints();
516  }
517 
519  compute_v1->generate_r1cs_witness();
520 
521  v0_c0.evaluate(this->bp);
522  v0_c1.evaluate(this->bp);
523  compute_v0->generate_r1cs_witness();
524 
525  Ac0_plus_Ac1_c0.evaluate(this->bp);
526  Ac0_plus_Ac1_c1.evaluate(this->bp);
527  compute_result_c1->generate_r1cs_witness();
528 
529  const typename field_type::value_type Aval = A.get_element();
530  const typename field_type::value_type Rval = Aval.squared();
532  }
533  };
534 
535  /******************************** element_fp4_cyclotomic_squared ************************************/
536 
540  template<typename Fp4T>
541  class element_fp4_cyclotomic_squared : public component<typename Fp4T::base_field_type> {
542  public:
543  using field_type = Fp4T;
544  using base_field_type = typename field_type::base_field_type;
545  using underlying_field_type = typename field_type::underlying_field_type;
546 
548 
549  using base_field_value_type = typename base_field_type::value_type;
550 
553 
556  std::shared_ptr<underlying_element_type> c0_expr;
557  std::shared_ptr<element_fp2_squared<underlying_field_type>> compute_c0_expr;
558 
561  std::shared_ptr<underlying_element_type> A_c0_plus_A_c1;
562 
565  std::shared_ptr<underlying_element_type> c1_expr;
566  std::shared_ptr<element_fp2_squared<underlying_field_type>> compute_c1_expr;
567 
569  const element_fp4<field_type> &A,
572  A(A), result(result) {
573  /*
574  A = elt.data[1] ^ 2
575  B = elt.data[1] + elt.data[0];
576  C = B ^ 2 - A
577  D = Fp2(A.data[1] * non_residue, A.data[0])
578  E = C - D
579  F = D + D + Fp2::one()
580  G = E - Fp2::one()
581 
582  return Fp4(F, G);
583 
584  Enforced with 2 element_fp2_squared's that ensure that:
585 
586  elt.data[1] ^ 2 = Fp2(result.data[0].data[1] / 2, (result.data[0].data[0] - 1) / (2 *
587  non_residue)) = A (elt.data[1] + elt.data[0]) ^ 2 = A + result.data[1] + Fp2(A.data[1] *
588  non_residue + 1, A.data[0])
589 
590  (elt.data[1] + elt.data[0]) ^ 2 = Fp2(result.data[0].data[1] / 2 + result.data[1].data[0]
591  + (result.data[0].data[0] - 1) / 2 + 1, (result.data[0].data[0] - 1) / (2 * non_residue) +
592  result.data[1].data[1] + result.data[0].data[1] / 2)
593  */
594  c0_expr_c0.assign(bp, result.data[0].data[1] * base_field_value_type(0x02).inversed());
596  bp,
597  (result.data[0].data[0] - base_field_value_type(0x01)) *
598  (base_field_value_type(0x02) * field_type::value_type::non_residue).inversed());
599 
602 
603  A_c0_plus_A_c1_c0.assign(bp, A.data[0].data[0] + A.data[1].data[0]);
604  A_c0_plus_A_c1_c1.assign(bp, A.data[0].data[1] + A.data[1].data[1]);
606 
608  bp,
609  (result.data[0].data[1] + result.data[0].data[0] - base_field_value_type(0x01)) *
610  base_field_value_type(0x02).inversed() +
611  result.data[1].data[0] + base_field_value_type(0x01));
613  bp,
614  (result.data[0].data[0] - base_field_value_type(0x01)) *
615  (base_field_value_type(0x02) * field_type::value_type::non_residue).inversed() +
616  result.data[1].data[1] +
617  result.data[0].data[1] * base_field_value_type(0x02).inversed());
618 
620 
621  compute_c1_expr.reset(
623  }
624 
626  compute_c0_expr->generate_r1cs_constraints();
627  compute_c1_expr->generate_r1cs_constraints();
628  }
629 
631  compute_c0_expr->generate_r1cs_witness();
632 
634  A_c0_plus_A_c1_c1.evaluate(this->bp);
635  compute_c1_expr->generate_r1cs_witness();
636 
637  const typename field_type::value_type Aval = A.get_element();
638  const typename field_type::value_type Rval = Aval.squared();
640  }
641  };
642  } // namespace components
643  } // namespace zk
644  } // namespace crypto3
645 } // namespace nil
646 
647 #endif // CRYPTO3_ZK_BLUEPRINT_FP4_COMPONENTS_HPP
void assign(blueprint< field_type > &bp, const snark::linear_combination< field_type > &lc)
Definition: blueprint_linear_combination.hpp:65
void evaluate(blueprint< field_type > &bp) const
Definition: blueprint_linear_combination.hpp:71
void allocate(blueprint< FieldType > &bp)
Definition: blueprint_variable.hpp:51
Definition: blueprint.hpp:46
Definition: component.hpp:37
blueprint< Fp4T::base_field_type > & bp
Definition: component.hpp:39
blueprint_linear_combination< base_field_type > c1_expr_c1
Definition: element_fp4.hpp:564
element_fp4_cyclotomic_squared(blueprint< base_field_type > &bp, const element_fp4< field_type > &A, const element_fp4< field_type > &result)
Definition: element_fp4.hpp:568
blueprint_linear_combination< base_field_type > A_c0_plus_A_c1_c1
Definition: element_fp4.hpp:560
typename field_type::base_field_type base_field_type
Definition: element_fp4.hpp:544
void generate_r1cs_constraints()
Definition: element_fp4.hpp:625
std::shared_ptr< element_fp2_squared< underlying_field_type > > compute_c0_expr
Definition: element_fp4.hpp:557
std::shared_ptr< underlying_element_type > A_c0_plus_A_c1
Definition: element_fp4.hpp:561
element_fp2< underlying_field_type > underlying_element_type
Definition: element_fp4.hpp:547
void generate_r1cs_witness()
Definition: element_fp4.hpp:630
std::shared_ptr< element_fp2_squared< underlying_field_type > > compute_c1_expr
Definition: element_fp4.hpp:566
blueprint_linear_combination< base_field_type > A_c0_plus_A_c1_c0
Definition: element_fp4.hpp:559
blueprint_linear_combination< base_field_type > c0_expr_c1
Definition: element_fp4.hpp:555
blueprint_linear_combination< base_field_type > c1_expr_c0
Definition: element_fp4.hpp:563
std::shared_ptr< underlying_element_type > c1_expr
Definition: element_fp4.hpp:565
typename field_type::underlying_field_type underlying_field_type
Definition: element_fp4.hpp:545
element_fp4< field_type > result
Definition: element_fp4.hpp:552
typename base_field_type::value_type base_field_value_type
Definition: element_fp4.hpp:549
blueprint_linear_combination< base_field_type > c0_expr_c0
Definition: element_fp4.hpp:554
std::shared_ptr< underlying_element_type > c0_expr
Definition: element_fp4.hpp:556
element_fp4< field_type > A
Definition: element_fp4.hpp:551
element_fp4< field_type > B
Definition: element_fp4.hpp:252
typename field_type::underlying_field_type underlying_field_type
Definition: element_fp4.hpp:245
Fp4T field_type
Definition: element_fp4.hpp:243
typename field_type::base_field_type base_field_type
Definition: element_fp4.hpp:244
void generate_r1cs_witness()
Definition: element_fp4.hpp:397
void generate_r1cs_constraints()
Definition: element_fp4.hpp:327
blueprint_variable< base_field_type > v2
Definition: element_fp4.hpp:256
element_fp4< field_type > result
Definition: element_fp4.hpp:253
typename base_field_type::value_type base_field_value_type
Definition: element_fp4.hpp:249
blueprint_variable< base_field_type > v1
Definition: element_fp4.hpp:255
element_fp4_direct_mul(blueprint< base_field_type > &bp, const element_fp4< field_type > &A, const element_fp4< field_type > &B, const element_fp4< field_type > &result)
Definition: element_fp4.hpp:259
element_fp4< field_type > A
Definition: element_fp4.hpp:251
blueprint_variable< base_field_type > v6
Definition: element_fp4.hpp:257
std::shared_ptr< element_fp2_squared< underlying_field_type > > compute_v0
Definition: element_fp4.hpp:452
blueprint_linear_combination< base_field_type > v0_c1
Definition: element_fp4.hpp:449
Fp4T field_type
Definition: element_fp4.hpp:437
typename field_type::base_field_type base_field_type
Definition: element_fp4.hpp:438
std::shared_ptr< underlying_element_type > result_c1_plus_v0_plus_v1
Definition: element_fp4.hpp:462
blueprint_linear_combination< base_field_type > result_c1_plus_v0_plus_v1_c0
Definition: element_fp4.hpp:459
std::shared_ptr< element_fp2_squared< underlying_field_type > > compute_result_c1
Definition: element_fp4.hpp:464
std::shared_ptr< underlying_element_type > Ac0_plus_Ac1
Definition: element_fp4.hpp:457
std::shared_ptr< underlying_element_type > v1
Definition: element_fp4.hpp:446
element_fp4< field_type > result
Definition: element_fp4.hpp:444
blueprint_linear_combination< base_field_type > result_c1_plus_v0_plus_v1_c1
Definition: element_fp4.hpp:460
void generate_r1cs_witness()
Definition: element_fp4.hpp:518
element_fp4< field_type > A
Definition: element_fp4.hpp:443
element_fp2< underlying_field_type > underlying_element_type
Definition: element_fp4.hpp:441
void generate_r1cs_constraints()
Definition: element_fp4.hpp:512
std::shared_ptr< element_fp2_squared< underlying_field_type > > compute_v1
Definition: element_fp4.hpp:453
std::shared_ptr< underlying_element_type > v0
Definition: element_fp4.hpp:450
blueprint_linear_combination< base_field_type > Ac0_plus_Ac1_c1
Definition: element_fp4.hpp:456
blueprint_linear_combination< base_field_type > Ac0_plus_Ac1_c0
Definition: element_fp4.hpp:455
element_fp4_squared(blueprint< base_field_type > &bp, const element_fp4< field_type > &A, const element_fp4< field_type > &result)
Definition: element_fp4.hpp:466
typename field_type::underlying_field_type underlying_field_type
Definition: element_fp4.hpp:439
blueprint_linear_combination< base_field_type > v0_c0
Definition: element_fp4.hpp:448
std::shared_ptr< underlying_element_type > v1
Definition: element_fp4.hpp:143
element_fp4< field_type > A
Definition: element_fp4.hpp:131
void generate_r1cs_constraints()
Definition: element_fp4.hpp:209
std::shared_ptr< underlying_element_type > v0
Definition: element_fp4.hpp:142
element_fp4_tower_mul(blueprint< base_field_type > &bp, const element_fp4< field_type > &A, const element_fp4< field_type > &B, const element_fp4< field_type > &result)
Definition: element_fp4.hpp:158
blueprint_linear_combination< base_field_type > v0_c0
Definition: element_fp4.hpp:135
std::shared_ptr< element_fp2_mul< underlying_field_type > > compute_v1
Definition: element_fp4.hpp:155
blueprint_linear_combination< base_field_type > result_c1_plus_v0_plus_v1_c0
Definition: element_fp4.hpp:149
blueprint_linear_combination< base_field_type > Ac0_plus_Ac1_c0
Definition: element_fp4.hpp:138
std::shared_ptr< element_fp2_mul< underlying_field_type > > compute_v0
Definition: element_fp4.hpp:154
std::shared_ptr< underlying_element_type > result_c1_plus_v0_plus_v1
Definition: element_fp4.hpp:152
blueprint_linear_combination< base_field_type > v0_c1
Definition: element_fp4.hpp:136
element_fp4< field_type > B
Definition: element_fp4.hpp:132
Fp4T field_type
Definition: element_fp4.hpp:125
blueprint_linear_combination< base_field_type > Bc0_plus_Bc1_c1
Definition: element_fp4.hpp:146
blueprint_linear_combination< base_field_type > Ac0_plus_Ac1_c1
Definition: element_fp4.hpp:139
blueprint_linear_combination< base_field_type > Bc0_plus_Bc1_c0
Definition: element_fp4.hpp:145
element_fp2< underlying_field_type > underlying_element_type
Definition: element_fp4.hpp:129
std::shared_ptr< underlying_element_type > Bc0_plus_Bc1
Definition: element_fp4.hpp:147
std::shared_ptr< element_fp2_mul< underlying_field_type > > compute_result_c1
Definition: element_fp4.hpp:156
typename field_type::underlying_field_type underlying_field_type
Definition: element_fp4.hpp:127
std::shared_ptr< underlying_element_type > Ac0_plus_Ac1
Definition: element_fp4.hpp:140
blueprint_linear_combination< base_field_type > result_c1_plus_v0_plus_v1_c1
Definition: element_fp4.hpp:150
void generate_r1cs_witness()
Definition: element_fp4.hpp:215
element_fp4< field_type > result
Definition: element_fp4.hpp:133
typename field_type::base_field_type base_field_type
Definition: element_fp4.hpp:126
nil::crypto3::math::expressions::detail::parser::power_ power
Definition: pair.hpp:31
Definition: element_fp2.hpp:199
Definition: element_fp2.hpp:52
Definition: element_fp4.hpp:50
element_fp2< underlying_field_type > underlying_element_type
Definition: element_fp4.hpp:56
typename field_type::base_field_type base_field_type
Definition: element_fp4.hpp:53
std::array< underlying_element_type, field_type::arity/underlying_field_type::arity > data_type
Definition: element_fp4.hpp:59
void generate_r1cs_witness(const typename field_type::value_type &el)
Definition: element_fp4.hpp:84
void evaluate() const
Definition: element_fp4.hpp:111
typename field_type::underlying_field_type underlying_field_type
Definition: element_fp4.hpp:54
field_type::value_type get_element()
Definition: element_fp4.hpp:89
element_fp4< field_type > Frobenius_map(const std::size_t power) const
Definition: element_fp4.hpp:96
element_fp4(blueprint< base_field_type > &bp)
Definition: element_fp4.hpp:63
element_fp4(blueprint< base_field_type > &bp, const typename field_type::value_type &el)
Definition: element_fp4.hpp:68
element_fp4(blueprint< base_field_type > &bp, const underlying_element_type &in_data0, const underlying_element_type &in_data1)
Definition: element_fp4.hpp:73
Fp4T field_type
Definition: element_fp4.hpp:52
data_type data
Definition: element_fp4.hpp:61
void generate_r1cs_equals_const_constraints(const typename field_type::value_type &el)
Definition: element_fp4.hpp:79