Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
exponentiation_gadget.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of interfaces for the exponentiation gadget.
5 
6  See exponentiation_gadget.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 EXPONENTIATION_GADGET_TCC_
15 #define EXPONENTIATION_GADGET_TCC_
16 
17 namespace libsnark
18 {
19 
20 template<
21  typename FpkT,
22  template<class>
23  class Fpk_variableT,
24  template<class>
25  class Fpk_mul_gadgetT,
26  template<class>
27  class Fpk_sqr_gadgetT,
28  mp_size_t m>
29 exponentiation_gadget<
30  FpkT,
31  Fpk_variableT,
32  Fpk_mul_gadgetT,
33  Fpk_sqr_gadgetT,
34  m>::
35  exponentiation_gadget(
36  protoboard<FieldT> &pb,
37  const Fpk_variableT<FpkT> &elt,
38  const libff::bigint<m> &power,
39  const Fpk_variableT<FpkT> &result,
40  const std::string &annotation_prefix)
41  : gadget<FieldT>(pb, annotation_prefix)
42  , elt(elt)
43  , power(power)
44  , result(result)
45 {
46  NAF = find_wnaf(1, power);
47 
48  intermed_count = 0;
49  add_count = 0;
50  sub_count = 0;
51  dbl_count = 0;
52 
53  bool found_nonzero = false;
54  for (long i = NAF.size() - 1; i >= 0; --i) {
55  if (found_nonzero) {
56  ++dbl_count;
57  ++intermed_count;
58  }
59 
60  if (NAF[i] != 0) {
61  found_nonzero = true;
62 
63  if (NAF[i] > 0) {
64  ++add_count;
65  ++intermed_count;
66  } else {
67  ++sub_count;
68  ++intermed_count;
69  }
70  }
71  }
72 
73  intermediate.resize(intermed_count);
74  intermediate[0].reset(new Fpk_variableT<FpkT>(
75  pb, FpkT::one(), FMT(annotation_prefix, " intermediate_0")));
76  for (size_t i = 1; i < intermed_count; ++i) {
77  intermediate[i].reset(new Fpk_variableT<FpkT>(
78  pb, FMT(annotation_prefix, " intermediate_%zu", i)));
79  }
80  addition_steps.resize(add_count);
81  subtraction_steps.resize(sub_count);
82  doubling_steps.resize(dbl_count);
83 
84  found_nonzero = false;
85 
86  size_t dbl_id = 0, add_id = 0, sub_id = 0, intermed_id = 0;
87 
88  for (long i = NAF.size() - 1; i >= 0; --i) {
89  if (found_nonzero) {
90  doubling_steps[dbl_id].reset(new Fpk_sqr_gadgetT<FpkT>(
91  pb,
92  *intermediate[intermed_id],
93  (intermed_id + 1 == intermed_count
94  ? result
95  : *intermediate[intermed_id + 1]),
96  FMT(annotation_prefix, " doubling_steps_%zu", dbl_count)));
97  ++intermed_id;
98  ++dbl_id;
99  }
100 
101  if (NAF[i] != 0) {
102  found_nonzero = true;
103 
104  if (NAF[i] > 0) {
105  /* next = cur * elt */
106  addition_steps[add_id].reset(new Fpk_mul_gadgetT<FpkT>(
107  pb,
108  *intermediate[intermed_id],
109  elt,
110  (intermed_id + 1 == intermed_count
111  ? result
112  : *intermediate[intermed_id + 1]),
113  FMT(annotation_prefix, " addition_steps_%zu", dbl_count)));
114  ++add_id;
115  ++intermed_id;
116  } else {
117  /* next = cur / elt, i.e. next * elt = cur */
118  subtraction_steps[sub_id].reset(new Fpk_mul_gadgetT<FpkT>(
119  pb,
120  (intermed_id + 1 == intermed_count
121  ? result
122  : *intermediate[intermed_id + 1]),
123  elt,
124  *intermediate[intermed_id],
125  FMT(annotation_prefix,
126  " subtraction_steps_%zu",
127  dbl_count)));
128  ++sub_id;
129  ++intermed_id;
130  }
131  }
132  }
133 }
134 
135 template<
136  typename FpkT,
137  template<class>
138  class Fpk_variableT,
139  template<class>
140  class Fpk_mul_gadgetT,
141  template<class>
142  class Fpk_sqr_gadgetT,
143  mp_size_t m>
144 void exponentiation_gadget<
145  FpkT,
146  Fpk_variableT,
147  Fpk_mul_gadgetT,
148  Fpk_sqr_gadgetT,
149  m>::generate_r1cs_constraints()
150 {
151  for (size_t i = 0; i < add_count; ++i) {
152  addition_steps[i]->generate_r1cs_constraints();
153  }
154 
155  for (size_t i = 0; i < sub_count; ++i) {
156  subtraction_steps[i]->generate_r1cs_constraints();
157  }
158 
159  for (size_t i = 0; i < dbl_count; ++i) {
160  doubling_steps[i]->generate_r1cs_constraints();
161  }
162 }
163 
164 template<
165  typename FpkT,
166  template<class>
167  class Fpk_variableT,
168  template<class>
169  class Fpk_mul_gadgetT,
170  template<class>
171  class Fpk_sqr_gadgetT,
172  mp_size_t m>
173 void exponentiation_gadget<
174  FpkT,
175  Fpk_variableT,
176  Fpk_mul_gadgetT,
177  Fpk_sqr_gadgetT,
178  m>::generate_r1cs_witness()
179 {
180  intermediate[0]->generate_r1cs_witness(FpkT::one());
181 
182  bool found_nonzero = false;
183  size_t dbl_id = 0, add_id = 0, sub_id = 0, intermed_id = 0;
184 
185  for (long i = NAF.size() - 1; i >= 0; --i) {
186  if (found_nonzero) {
187  doubling_steps[dbl_id]->generate_r1cs_witness();
188  ++intermed_id;
189  ++dbl_id;
190  }
191 
192  if (NAF[i] != 0) {
193  found_nonzero = true;
194 
195  if (NAF[i] > 0) {
196  addition_steps[add_id]->generate_r1cs_witness();
197  ++intermed_id;
198  ++add_id;
199  } else {
200  const FpkT cur_val = intermediate[intermed_id]->get_element();
201  const FpkT elt_val = elt.get_element();
202  const FpkT next_val = cur_val * elt_val.inverse();
203 
204  (intermed_id + 1 == intermed_count
205  ? result
206  : *intermediate[intermed_id + 1])
207  .generate_r1cs_witness(next_val);
208 
209  subtraction_steps[sub_id]->generate_r1cs_witness();
210 
211  ++intermed_id;
212  ++sub_id;
213  }
214  }
215  }
216 }
217 
218 template<
219  typename FpkT,
220  template<class>
221  class Fpk_variableT,
222  template<class>
223  class Fpk_mul_gadgetT,
224  template<class>
225  class Fpk_sqr_gadgetT,
226  mp_size_t m>
227 void test_exponentiation_gadget(
228  const libff::bigint<m> &power, const std::string &annotation)
229 {
230  typedef typename FpkT::my_Fp FieldT;
231 
232  protoboard<FieldT> pb;
233  Fpk_variableT<FpkT> x(pb, "x");
234  Fpk_variableT<FpkT> x_to_power(pb, "x_to_power");
235  exponentiation_gadget<
236  FpkT,
237  Fpk_variableT,
238  Fpk_mul_gadgetT,
239  Fpk_sqr_gadgetT,
240  m>
241  exp_gadget(pb, x, power, x_to_power, "exp_gadget");
242  exp_gadget.generate_r1cs_constraints();
243 
244  for (size_t i = 0; i < 10; ++i) {
245  const FpkT x_val = FpkT::random_element();
246  x.generate_r1cs_witness(x_val);
247  exp_gadget.generate_r1cs_witness();
248  assert(pb.is_satisfied());
249  assert(x_to_power.get_element() == (x_val ^ power));
250  }
251  printf(
252  "number of constraints for %s_exp = %zu\n",
253  annotation.c_str(),
254  pb.num_constraints());
255  printf("exponent was: ");
256  power.print();
257 }
258 
259 } // namespace libsnark
260 
261 #endif // EXPONENTIATION_GADGET_TCC_