2 *****************************************************************************
3 * @author This file is part of libsnark, developed by Clearmatics Ltd
4 * (originally developed by SCIPR Lab) and contributors
6 * @copyright MIT license (see LICENSE file)
7 *****************************************************************************/
9 #ifndef LIBSNARK_GADGETLIB1_GADGETS_VERFIERS_R1CS_GG_PPZKSNARK_VERIFIER_GADGET_TCC_
10 #define LIBSNARK_GADGETLIB1_GADGETS_VERFIERS_R1CS_GG_PPZKSNARK_VERIFIER_GADGET_TCC_
12 #include "libsnark/gadgetlib1/constraint_profiling.hpp"
13 #include "libsnark/gadgetlib1/gadgets/verifiers/r1cs_gg_ppzksnark_verifier_gadget.hpp"
18 template<typename ppT>
19 r1cs_gg_ppzksnark_proof_variable<ppT>::r1cs_gg_ppzksnark_proof_variable(
20 protoboard<FieldT> &pb, const std::string &annotation_prefix)
21 : gadget<FieldT>(pb, annotation_prefix)
25 const size_t num_G1 = 2;
27 const size_t num_G2 = 1;
30 _g_A.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_A")));
31 _g_B.reset(new G2_variable<ppT>(pb, FMT(annotation_prefix, " g_B")));
32 _g_C.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " g_C")));
34 _all_G1_vars = {_g_A, _g_C};
35 _all_G2_vars = {_g_B};
37 _all_G1_checkers.resize(_all_G1_vars.size());
39 for (size_t i = 0; i < _all_G1_vars.size(); ++i) {
40 _all_G1_checkers[i].reset(new G1_checker<ppT>(
43 FMT(annotation_prefix, " all_G1_checkers_%zu", i)));
47 new G2_checker<ppT>(pb, *_g_B, FMT(annotation_prefix, " G2_checker")));
49 assert(_all_G1_vars.size() == num_G1);
50 assert(_all_G2_vars.size() == num_G2);
53 template<typename ppT>
54 void r1cs_gg_ppzksnark_proof_variable<ppT>::generate_r1cs_constraints()
56 for (auto &G1_checker : _all_G1_checkers) {
57 G1_checker->generate_r1cs_constraints();
60 _G2_checker->generate_r1cs_constraints();
63 template<typename ppT>
64 void r1cs_gg_ppzksnark_proof_variable<ppT>::generate_r1cs_witness(
65 const r1cs_gg_ppzksnark_proof<other_curve<ppT>> &proof)
67 std::vector<libff::G1<other_curve<ppT>>> G1_elems;
68 std::vector<libff::G2<other_curve<ppT>>> G2_elems;
70 G1_elems = {proof.g_A, proof.g_C};
71 G2_elems = {proof.g_B};
73 assert(G1_elems.size() == _all_G1_vars.size());
74 assert(G2_elems.size() == _all_G2_vars.size());
76 for (size_t i = 0; i < G1_elems.size(); ++i) {
77 _all_G1_vars[i]->generate_r1cs_witness(G1_elems[i]);
80 for (size_t i = 0; i < G2_elems.size(); ++i) {
81 _all_G2_vars[i]->generate_r1cs_witness(G2_elems[i]);
84 for (auto &G1_checker : _all_G1_checkers) {
85 G1_checker->generate_r1cs_witness();
88 _G2_checker->generate_r1cs_witness();
91 template<typename ppT> size_t r1cs_gg_ppzksnark_proof_variable<ppT>::size()
93 const size_t num_G1 = 2;
94 const size_t num_G2 = 1;
96 num_G1 * G1_variable<ppT>::num_field_elems +
97 num_G2 * G2_variable<ppT>::num_field_elems);
100 template<typename ppT>
101 r1cs_gg_ppzksnark_verification_key_variable<ppT>::
102 r1cs_gg_ppzksnark_verification_key_variable(
103 protoboard<libff::Fr<ppT>> &pb,
104 const size_t num_primary_inputs,
105 const std::string &annotation_prefix)
106 : gadget<FieldT>(pb, annotation_prefix)
107 , _alpha_g1(pb, FMT(annotation_prefix, " alpha_g1"))
108 , _beta_g2(pb, FMT(annotation_prefix, " beta_g2"))
109 , _delta_g2(pb, FMT(annotation_prefix, " delta_g2"))
111 new G1_variable<ppT>(pb, FMT(annotation_prefix, " encoded_ABC_base")))
112 , _num_primary_inputs(num_primary_inputs)
114 // Populate _all_vars with alpha, beta, gamma and ABC_base variables.
116 _all_vars.end(), _alpha_g1.all_vars.begin(), _alpha_g1.all_vars.end());
118 _all_vars.end(), _beta_g2.all_vars.begin(), _beta_g2.all_vars.end());
120 _all_vars.end(), _delta_g2.all_vars.begin(), _delta_g2.all_vars.end());
123 _encoded_ABC_base->all_vars.begin(),
124 _encoded_ABC_base->all_vars.end());
126 // Allocate variables for ABC_g1 elements, and populate _all_vars with each
128 _ABC_g1.reserve(_num_primary_inputs);
129 for (size_t i = 0; i < _num_primary_inputs; ++i) {
130 _ABC_g1.emplace_back(new G1_variable<ppT>(
131 pb, FMT(annotation_prefix, " ABC_g1[%zu]", i)));
132 const G1_variable<ppT> &ivar = *(_ABC_g1.back());
134 _all_vars.end(), ivar.all_vars.begin(), ivar.all_vars.end());
138 template<typename ppT>
139 void r1cs_gg_ppzksnark_verification_key_variable<
140 ppT>::generate_r1cs_constraints()
144 template<typename ppT>
145 void r1cs_gg_ppzksnark_verification_key_variable<ppT>::generate_r1cs_witness(
146 const r1cs_gg_ppzksnark_verification_key<other_curve<ppT>> &vk)
148 assert(vk.ABC_g1.rest.size() == _num_primary_inputs);
149 _alpha_g1.generate_r1cs_witness(vk.alpha_g1);
150 _beta_g2.generate_r1cs_witness(vk.beta_g2);
151 _delta_g2.generate_r1cs_witness(vk.delta_g2);
152 _encoded_ABC_base->generate_r1cs_witness(vk.ABC_g1.first);
153 for (size_t i = 0; i < _num_primary_inputs; ++i) {
154 assert(vk.ABC_g1.rest.indices[i] == i);
155 _ABC_g1[i]->generate_r1cs_witness(vk.ABC_g1.rest.values[i]);
159 template<typename ppT>
160 size_t r1cs_gg_ppzksnark_verification_key_variable<ppT>::num_primary_inputs()
163 return _num_primary_inputs;
166 template<typename ppT>
167 const pb_linear_combination_array<libff::Fr<ppT>>
168 &r1cs_gg_ppzksnark_verification_key_variable<ppT>::get_all_vars() const
173 template<typename ppT>
174 std::vector<libff::Fr<ppT>> r1cs_gg_ppzksnark_verification_key_variable<ppT>::
175 get_verification_key_scalars(
176 const r1cs_gg_ppzksnark_verification_key<other_curve<ppT>> &r1cs_vk)
178 // TODO: It would be much more efficient to simply iterate through the
179 // field elements of r1cs_vk, replicating the order in the constructor. For
180 // now, to avoid replicating that order (which also depends on the G1 and
181 // G2 variable gadgets), we instantiate this gadget and extract the values
184 const size_t num_primary_inputs = r1cs_vk.ABC_g1.rest.indices.size();
186 protoboard<FieldT> pb;
187 r1cs_gg_ppzksnark_verification_key_variable<ppT> vk(
188 pb, num_primary_inputs, "vk");
189 vk.generate_r1cs_witness(r1cs_vk);
190 const pb_linear_combination_array<FieldT> &vk_vars = vk.get_all_vars();
192 std::vector<FieldT> scalar_values;
193 scalar_values.reserve(vk_vars.size());
194 for (const pb_linear_combination<FieldT> &lc : vk_vars) {
195 scalar_values.push_back(pb.lc_val(lc));
198 return scalar_values;
201 template<typename ppT>
202 r1cs_gg_ppzksnark_preprocessed_verification_key_variable<
203 ppT>::r1cs_gg_ppzksnark_preprocessed_verification_key_variable()
205 // will be allocated outside
208 template<typename ppT>
209 r1cs_gg_ppzksnark_preprocessed_verification_key_variable<ppT>::
210 r1cs_gg_ppzksnark_preprocessed_verification_key_variable(
211 protoboard<FieldT> &pb,
212 const r1cs_gg_ppzksnark_verification_key<other_curve<ppT>> &r1cs_vk,
213 const std::string &annotation_prefix)
215 _encoded_ABC_base.reset(new G1_variable<ppT>(
216 pb, r1cs_vk.ABC_g1.first, FMT(annotation_prefix, " encoded_ABC_base")));
217 _ABC_g1.resize(r1cs_vk.ABC_g1.rest.indices.size());
218 for (size_t i = 0; i < r1cs_vk.ABC_g1.rest.indices.size(); ++i) {
219 assert(r1cs_vk.ABC_g1.rest.indices[i] == i);
220 _ABC_g1[i].reset(new G1_variable<ppT>(
222 r1cs_vk.ABC_g1.rest.values[i],
223 FMT(annotation_prefix, " ABC_g1[%zu]", i)));
226 _vk_alpha_g1_precomp.reset(new G1_precomputation<ppT>(
227 pb, r1cs_vk.alpha_g1, FMT(annotation_prefix, " vk_alpha_g1_precomp")));
229 _vk_generator_g2_precomp.reset(new G2_precomputation<ppT>(
231 libff::G2<other_curve<ppT>>::one(),
232 FMT(annotation_prefix, " vk_generator_g2_precomp")));
233 _vk_beta_g2_precomp.reset(new G2_precomputation<ppT>(
234 pb, r1cs_vk.beta_g2, FMT(annotation_prefix, " vk_beta_g2_precomp")));
235 _vk_delta_g2_precomp.reset(new G2_precomputation<ppT>(
236 pb, r1cs_vk.delta_g2, FMT(annotation_prefix, " vk_delta_g2_precomp")));
239 template<typename ppT>
240 r1cs_gg_ppzksnark_verifier_process_vk_gadget<ppT>::
241 r1cs_gg_ppzksnark_verifier_process_vk_gadget(
242 protoboard<FieldT> &pb,
243 const r1cs_gg_ppzksnark_verification_key_variable<ppT> &vk,
244 r1cs_gg_ppzksnark_preprocessed_verification_key_variable<ppT> &pvk,
245 const std::string &annotation_prefix)
246 : gadget<FieldT>(pb, annotation_prefix), _vk(vk), _pvk(pvk)
248 _pvk._encoded_ABC_base = vk._encoded_ABC_base;
249 _pvk._ABC_g1 = vk._ABC_g1;
251 _pvk._vk_alpha_g1_precomp.reset(new G1_precomputation<ppT>());
253 _pvk._vk_generator_g2_precomp.reset(new G2_precomputation<ppT>());
254 _pvk._vk_beta_g2_precomp.reset(new G2_precomputation<ppT>());
255 _pvk._vk_delta_g2_precomp.reset(new G2_precomputation<ppT>());
257 _compute_vk_alpha_g1_precomp.reset(new precompute_G1_gadget<ppT>(
260 *pvk._vk_alpha_g1_precomp,
261 FMT(annotation_prefix, " compute_vk_alpha_g1_precomp")));
263 _pvk._vk_generator_g2_precomp.reset(new G2_precomputation<ppT>(
265 libff::G2<other_curve<ppT>>::one(),
266 FMT(annotation_prefix, " vk_generator_g2_precomp")));
267 _compute_vk_beta_g2_precomp.reset(new precompute_G2_gadget<ppT>(
270 *pvk._vk_beta_g2_precomp,
271 FMT(annotation_prefix, " compute_vk_beta_g2_precomp")));
272 _compute_vk_delta_g2_precomp.reset(new precompute_G2_gadget<ppT>(
275 *pvk._vk_delta_g2_precomp,
276 FMT(annotation_prefix, " compute_vk_delta_g2_precomp")));
279 template<typename ppT>
280 void r1cs_gg_ppzksnark_verifier_process_vk_gadget<
281 ppT>::generate_r1cs_constraints()
283 _compute_vk_alpha_g1_precomp->generate_r1cs_constraints();
285 _compute_vk_beta_g2_precomp->generate_r1cs_constraints();
286 _compute_vk_delta_g2_precomp->generate_r1cs_constraints();
289 template<typename ppT>
290 void r1cs_gg_ppzksnark_verifier_process_vk_gadget<ppT>::generate_r1cs_witness()
292 _compute_vk_alpha_g1_precomp->generate_r1cs_witness();
294 _compute_vk_beta_g2_precomp->generate_r1cs_witness();
295 _compute_vk_delta_g2_precomp->generate_r1cs_witness();
298 template<typename ppT>
299 r1cs_gg_ppzksnark_online_verifier_gadget<ppT>::
300 r1cs_gg_ppzksnark_online_verifier_gadget(
301 protoboard<FieldT> &pb,
302 const r1cs_gg_ppzksnark_preprocessed_verification_key_variable<ppT>
304 const pb_variable_array<FieldT> &input,
305 const size_t elt_size,
306 const r1cs_gg_ppzksnark_proof_variable<ppT> &proof,
307 const pb_variable<FieldT> &result_QAP_valid,
308 const std::string &annotation_prefix)
309 : gadget<FieldT>(pb, annotation_prefix)
312 , _elt_size(elt_size)
314 , _result(result_QAP_valid)
315 , _input_len(input.size())
317 // 1. Accumulate input and store base in acc
319 // https://github.com/clearmatics/libsnark/blob/master/libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/r1cs_gg_ppzksnark.tcc#L568-L571
320 _acc.reset(new G1_variable<ppT>(pb, FMT(annotation_prefix, " acc")));
321 std::vector<G1_variable<ppT>> IC_terms;
322 for (size_t i = 0; i < _pvk._ABC_g1.size(); ++i) {
323 IC_terms.emplace_back(*(_pvk._ABC_g1[i]));
325 _accumulate_input.reset(new G1_multiscalar_mul_gadget<ppT>(
327 *(_pvk._encoded_ABC_base),
332 FMT(annotation_prefix, " accumulate_input")));
334 // 2. Do the precomputations on the inputs of the pairings
336 // https://github.com/clearmatics/libsnark/blob/master/libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/r1cs_gg_ppzksnark.tcc#L588-L591
338 // 2.1 Allocate the results of the precomputations
339 _proof_g_A_precomp.reset(new G1_precomputation<ppT>());
340 _proof_g_B_precomp.reset(new G2_precomputation<ppT>());
341 _proof_g_C_precomp.reset(new G1_precomputation<ppT>());
342 _acc_precomp.reset(new G1_precomputation<ppT>());
343 // 2.2 Do the precomputations
344 _compute_proof_g_A_precomp.reset(new precompute_G1_gadget<ppT>(
348 FMT(annotation_prefix, " compute_proof_g_A_precomp")));
349 _compute_proof_g_B_precomp.reset(new precompute_G2_gadget<ppT>(
353 FMT(annotation_prefix, " compute_proof_g_B_precomp")));
354 _compute_proof_g_C_precomp.reset(new precompute_G1_gadget<ppT>(
358 FMT(annotation_prefix, " compute_proof_g_C_precomp")));
359 _compute_acc_precomp.reset(new precompute_G1_gadget<ppT>(
363 FMT(annotation_prefix, " compute_acc_precomp")));
365 // 3. Carry out the pairing checks to check QAP equation
366 _check_QAP_valid.reset(new check_e_equals_eee_gadget<ppT>(
372 *(pvk._vk_alpha_g1_precomp),
373 *(pvk._vk_beta_g2_precomp),
375 *(pvk._vk_generator_g2_precomp),
376 *(_proof_g_C_precomp),
377 *(pvk._vk_delta_g2_precomp),
378 // Result of pairing check (allocated outside of this circuit)
380 FMT(annotation_prefix, " check_QAP_valid")));
383 template<typename ppT>
384 void r1cs_gg_ppzksnark_online_verifier_gadget<ppT>::generate_r1cs_constraints()
386 // For the macros below
387 using namespace libsnark;
389 PROFILE_CONSTRAINTS(this->pb, "accumulate verifier input")
391 libff::print_indent();
393 "* Number of bits as an input to verifier gadget: %zu\n",
395 _accumulate_input->generate_r1cs_constraints();
398 PROFILE_CONSTRAINTS(this->pb, "rest of the verifier")
400 _compute_proof_g_A_precomp->generate_r1cs_constraints();
401 _compute_proof_g_B_precomp->generate_r1cs_constraints();
402 _compute_proof_g_C_precomp->generate_r1cs_constraints();
403 _compute_acc_precomp->generate_r1cs_constraints();
405 _check_QAP_valid->generate_r1cs_constraints();
409 template<typename ppT>
410 void r1cs_gg_ppzksnark_online_verifier_gadget<ppT>::generate_r1cs_witness()
412 _accumulate_input->generate_r1cs_witness();
414 _compute_proof_g_A_precomp->generate_r1cs_witness();
415 _compute_proof_g_B_precomp->generate_r1cs_witness();
416 _compute_proof_g_C_precomp->generate_r1cs_witness();
417 _compute_acc_precomp->generate_r1cs_witness();
419 _check_QAP_valid->generate_r1cs_witness();
422 template<typename ppT>
423 r1cs_gg_ppzksnark_verifier_gadget<ppT>::r1cs_gg_ppzksnark_verifier_gadget(
424 protoboard<FieldT> &pb,
425 const r1cs_gg_ppzksnark_verification_key_variable<ppT> &vk,
426 const pb_variable_array<FieldT> &input,
427 const size_t elt_size,
428 const r1cs_gg_ppzksnark_proof_variable<ppT> &proof,
429 const pb_variable<FieldT> &result,
430 const std::string &annotation_prefix)
431 : gadget<FieldT>(pb, annotation_prefix)
434 new r1cs_gg_ppzksnark_preprocessed_verification_key_variable<ppT>());
435 _compute_pvk.reset(new r1cs_gg_ppzksnark_verifier_process_vk_gadget<ppT>(
436 pb, vk, *_pvk, FMT(annotation_prefix, " compute_pvk")));
437 _online_verifier.reset(new r1cs_gg_ppzksnark_online_verifier_gadget<ppT>(
444 FMT(annotation_prefix, " online_verifier")));
447 template<typename ppT>
448 void r1cs_gg_ppzksnark_verifier_gadget<ppT>::generate_r1cs_constraints()
450 // For the macros below
451 using namespace libsnark;
453 PROFILE_CONSTRAINTS(this->pb, "precompute pvk")
455 _compute_pvk->generate_r1cs_constraints();
458 PROFILE_CONSTRAINTS(this->pb, "online verifier")
460 _online_verifier->generate_r1cs_constraints();
464 template<typename ppT>
465 void r1cs_gg_ppzksnark_verifier_gadget<ppT>::generate_r1cs_witness()
467 _compute_pvk->generate_r1cs_witness();
468 _online_verifier->generate_r1cs_witness();
471 } // namespace libsnark
473 #endif // LIBSNARK_GADGETLIB1_GADGETS_VERFIERS_R1CS_GG_PPZKSNARK_VERIFIER_GADGET_TCC_