2 *****************************************************************************
4 Implementation of interfaces for the exponentiation gadget.
6 See exponentiation_gadget.hpp .
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 *****************************************************************************/
14 #ifndef EXPONENTIATION_GADGET_TCC_
15 #define EXPONENTIATION_GADGET_TCC_
25 class Fpk_mul_gadgetT,
27 class Fpk_sqr_gadgetT,
29 exponentiation_gadget<
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)
46 NAF = find_wnaf(1, power);
53 bool found_nonzero = false;
54 for (long i = NAF.size() - 1; i >= 0; --i) {
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)));
80 addition_steps.resize(add_count);
81 subtraction_steps.resize(sub_count);
82 doubling_steps.resize(dbl_count);
84 found_nonzero = false;
86 size_t dbl_id = 0, add_id = 0, sub_id = 0, intermed_id = 0;
88 for (long i = NAF.size() - 1; i >= 0; --i) {
90 doubling_steps[dbl_id].reset(new Fpk_sqr_gadgetT<FpkT>(
92 *intermediate[intermed_id],
93 (intermed_id + 1 == intermed_count
95 : *intermediate[intermed_id + 1]),
96 FMT(annotation_prefix, " doubling_steps_%zu", dbl_count)));
102 found_nonzero = true;
105 /* next = cur * elt */
106 addition_steps[add_id].reset(new Fpk_mul_gadgetT<FpkT>(
108 *intermediate[intermed_id],
110 (intermed_id + 1 == intermed_count
112 : *intermediate[intermed_id + 1]),
113 FMT(annotation_prefix, " addition_steps_%zu", dbl_count)));
117 /* next = cur / elt, i.e. next * elt = cur */
118 subtraction_steps[sub_id].reset(new Fpk_mul_gadgetT<FpkT>(
120 (intermed_id + 1 == intermed_count
122 : *intermediate[intermed_id + 1]),
124 *intermediate[intermed_id],
125 FMT(annotation_prefix,
126 " subtraction_steps_%zu",
140 class Fpk_mul_gadgetT,
142 class Fpk_sqr_gadgetT,
144 void exponentiation_gadget<
149 m>::generate_r1cs_constraints()
151 for (size_t i = 0; i < add_count; ++i) {
152 addition_steps[i]->generate_r1cs_constraints();
155 for (size_t i = 0; i < sub_count; ++i) {
156 subtraction_steps[i]->generate_r1cs_constraints();
159 for (size_t i = 0; i < dbl_count; ++i) {
160 doubling_steps[i]->generate_r1cs_constraints();
169 class Fpk_mul_gadgetT,
171 class Fpk_sqr_gadgetT,
173 void exponentiation_gadget<
178 m>::generate_r1cs_witness()
180 intermediate[0]->generate_r1cs_witness(FpkT::one());
182 bool found_nonzero = false;
183 size_t dbl_id = 0, add_id = 0, sub_id = 0, intermed_id = 0;
185 for (long i = NAF.size() - 1; i >= 0; --i) {
187 doubling_steps[dbl_id]->generate_r1cs_witness();
193 found_nonzero = true;
196 addition_steps[add_id]->generate_r1cs_witness();
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();
204 (intermed_id + 1 == intermed_count
206 : *intermediate[intermed_id + 1])
207 .generate_r1cs_witness(next_val);
209 subtraction_steps[sub_id]->generate_r1cs_witness();
223 class Fpk_mul_gadgetT,
225 class Fpk_sqr_gadgetT,
227 void test_exponentiation_gadget(
228 const libff::bigint<m> &power, const std::string &annotation)
230 typedef typename FpkT::my_Fp FieldT;
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<
241 exp_gadget(pb, x, power, x_to_power, "exp_gadget");
242 exp_gadget.generate_r1cs_constraints();
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));
252 "number of constraints for %s_exp = %zu\n",
254 pb.num_constraints());
255 printf("exponent was: ");
259 } // namespace libsnark
261 #endif // EXPONENTIATION_GADGET_TCC_