blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.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 the exponentiation component.
26 //---------------------------------------------------------------------------//
27 
28 #ifndef CRYPTO3_ZK_BLUEPRINT_EXPONENTIATION_COMPONENT_HPP
29 #define CRYPTO3_ZK_BLUEPRINT_EXPONENTIATION_COMPONENT_HPP
30 
31 #include <memory>
32 #include <vector>
33 
34 #include <nil/crypto3/multiprecision/wnaf.hpp>
35 
37 
38 namespace nil {
39  namespace crypto3 {
40  namespace zk {
41  namespace components {
42 
48  template<typename FpkT,
49  template<class>
50  class Fpk_variableT,
51  template<class>
52  class Fpk_mul_componentT,
53  template<class>
54  class Fpk_sqr_componentT,
55  typename NumberType = typename FpkT::integral_type>
56  class exponentiation_component : component<typename FpkT::base_field_type> {
57  public:
58  typedef typename FpkT::base_field_type FieldType;
59  typedef NumberType integral_type;
60  std::vector<long> NAF;
61 
62  std::vector<std::shared_ptr<Fpk_variableT<FpkT>>> intermediate;
63  std::vector<std::shared_ptr<Fpk_mul_componentT<FpkT>>> addition_steps;
64  std::vector<std::shared_ptr<Fpk_mul_componentT<FpkT>>> subtraction_steps;
65  std::vector<std::shared_ptr<Fpk_sqr_componentT<FpkT>>> doubling_steps;
66 
67  Fpk_variableT<FpkT> elt;
69  Fpk_variableT<FpkT> result;
70 
71  std::size_t intermed_count;
72  std::size_t add_count;
73  std::size_t sub_count;
74  std::size_t dbl_count;
75 
76  template<typename Backend, typename multiprecision::expression_template_option ExpressionTemplates>
78  const Fpk_variableT<FpkT> &elt,
79  const multiprecision::number<Backend, ExpressionTemplates> &power,
80  const Fpk_variableT<FpkT> &result) :
83  NAF = multiprecision::find_wnaf(1, power);
84 
85  intermed_count = 0;
86  add_count = 0;
87  sub_count = 0;
88  dbl_count = 0;
89 
90  bool found_nonzero = false;
91  for (long i = NAF.size() - 1; i >= 0; --i) {
92  if (found_nonzero) {
93  ++dbl_count;
95  }
96 
97  if (NAF[i] != 0) {
98  found_nonzero = true;
99 
100  if (NAF[i] > 0) {
101  ++add_count;
102  ++intermed_count;
103  } else {
104  ++sub_count;
105  ++intermed_count;
106  }
107  }
108  }
109 
111  intermediate[0].reset(new Fpk_variableT<FpkT>(bp, FpkT::value_type::one()));
112  for (std::size_t i = 1; i < intermed_count; ++i) {
113  intermediate[i].reset(new Fpk_variableT<FpkT>(bp));
114  }
115  addition_steps.resize(add_count);
117  doubling_steps.resize(dbl_count);
118 
119  found_nonzero = false;
120 
121  std::size_t dbl_id = 0, add_id = 0, sub_id = 0, intermed_id = 0;
122 
123  for (long i = NAF.size() - 1; i >= 0; --i) {
124  if (found_nonzero) {
125  doubling_steps[dbl_id].reset(new Fpk_sqr_componentT<FpkT>(
126  bp,
127  *intermediate[intermed_id],
128  (intermed_id + 1 == intermed_count ? result : *intermediate[intermed_id + 1])));
129  ++intermed_id;
130  ++dbl_id;
131  }
132 
133  if (NAF[i] != 0) {
134  found_nonzero = true;
135 
136  if (NAF[i] > 0) {
137  /* next = cur * elt */
138  addition_steps[add_id].reset(new Fpk_mul_componentT<FpkT>(
139  bp,
140  *intermediate[intermed_id],
141  elt,
142  (intermed_id + 1 == intermed_count ? result : *intermediate[intermed_id + 1])));
143  ++add_id;
144  ++intermed_id;
145  } else {
146  /* next = cur / elt, i.e. next * elt = cur */
147  subtraction_steps[sub_id].reset(new Fpk_mul_componentT<FpkT>(
148  bp,
149  (intermed_id + 1 == intermed_count ? result : *intermediate[intermed_id + 1]),
150  elt,
151  *intermediate[intermed_id]));
152  ++sub_id;
153  ++intermed_id;
154  }
155  }
156  }
157  }
159  for (std::size_t i = 0; i < add_count; ++i) {
160  addition_steps[i]->generate_r1cs_constraints();
161  }
162 
163  for (std::size_t i = 0; i < sub_count; ++i) {
164  subtraction_steps[i]->generate_r1cs_constraints();
165  }
166 
167  for (std::size_t i = 0; i < dbl_count; ++i) {
168  doubling_steps[i]->generate_r1cs_constraints();
169  }
170  }
172  intermediate[0]->generate_r1cs_witness(FpkT::value_type::one());
173 
174  bool found_nonzero = false;
175  std::size_t dbl_id = 0, add_id = 0, sub_id = 0, intermed_id = 0;
176 
177  for (long i = NAF.size() - 1; i >= 0; --i) {
178  if (found_nonzero) {
179  doubling_steps[dbl_id]->generate_r1cs_witness();
180  ++intermed_id;
181  ++dbl_id;
182  }
183 
184  if (NAF[i] != 0) {
185  found_nonzero = true;
186 
187  if (NAF[i] > 0) {
188  addition_steps[add_id]->generate_r1cs_witness();
189  ++intermed_id;
190  ++add_id;
191  } else {
192  const typename FpkT::value_type cur_val = intermediate[intermed_id]->get_element();
193  const typename FpkT::value_type elt_val = elt.get_element();
194  const typename FpkT::value_type next_val = cur_val * elt_val.inversed();
195 
196  (intermed_id + 1 == intermed_count ? result : *intermediate[intermed_id + 1])
197  .generate_r1cs_witness(next_val);
198 
199  subtraction_steps[sub_id]->generate_r1cs_witness();
200 
201  ++intermed_id;
202  ++sub_id;
203  }
204  }
205  }
206  }
207  };
208  } // namespace components
209  } // namespace zk
210  } // namespace crypto3
211 } // namespace nil
212 
213 #endif // CRYPTO3_ZK_BLUEPRINT_EXPONENTIATION_COMPONENT_HPP
Definition: blueprint.hpp:46
Definition: component.hpp:37
blueprint< FpkT::base_field_type > & bp
Definition: component.hpp:39
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:56
FpkT::base_field_type FieldType
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:58
void generate_r1cs_constraints()
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:158
std::size_t add_count
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:72
Fpk_variableT< FpkT > result
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:69
std::size_t dbl_count
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:74
std::vector< long > NAF
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:60
integral_type power
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:68
std::vector< std::shared_ptr< Fpk_mul_componentT< FpkT > > > addition_steps
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:63
std::vector< std::shared_ptr< Fpk_sqr_componentT< FpkT > > > doubling_steps
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:65
std::size_t sub_count
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:73
void generate_r1cs_witness()
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:171
exponentiation_component(blueprint< FieldType > &bp, const Fpk_variableT< FpkT > &elt, const multiprecision::number< Backend, ExpressionTemplates > &power, const Fpk_variableT< FpkT > &result)
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:77
Fpk_variableT< FpkT > elt
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:67
NumberType integral_type
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:59
std::vector< std::shared_ptr< Fpk_variableT< FpkT > > > intermediate
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:62
std::size_t intermed_count
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:71
std::vector< std::shared_ptr< Fpk_mul_componentT< FpkT > > > subtraction_steps
Definition: blueprint/include/nil/crypto3/zk/components/algebra/fields/exponentiation.hpp:64
Definition: pair.hpp:31