2 *****************************************************************************
3 Implementation of interfaces for a ppzkSNARK for USCS.
5 See uscs_ppzksnark.hpp .
6 *****************************************************************************
7 * @author This file is part of libsnark, developed by SCIPR Lab
8 * and contributors (see AUTHORS).
9 * @copyright MIT license (see LICENSE file)
10 *****************************************************************************/
12 #ifndef USCS_PPZKSNARK_TCC_
13 #define USCS_PPZKSNARK_TCC_
19 #include <libff/algebra/scalar_multiplication/multiexp.hpp>
20 #include <libff/common/profiling.hpp>
21 #include <libff/common/utils.hpp>
28 #include <libsnark/reductions/uscs_to_ssp/uscs_to_ssp.hpp>
29 #include <libsnark/relations/arithmetic_programs/ssp/ssp.hpp>
34 template<typename ppT>
35 bool uscs_ppzksnark_proving_key<ppT>::operator==(
36 const uscs_ppzksnark_proving_key<ppT> &other) const
39 this->V_g1_query == other.V_g1_query &&
40 this->alpha_V_g1_query == other.alpha_V_g1_query &&
41 this->H_g1_query == other.H_g1_query &&
42 this->V_g2_query == other.V_g2_query &&
43 this->constraint_system == other.constraint_system);
46 template<typename ppT>
47 std::ostream &operator<<(
48 std::ostream &out, const uscs_ppzksnark_proving_key<ppT> &pk)
51 out << pk.alpha_V_g1_query;
54 out << pk.constraint_system;
59 template<typename ppT>
60 std::istream &operator>>(std::istream &in, uscs_ppzksnark_proving_key<ppT> &pk)
63 in >> pk.alpha_V_g1_query;
66 in >> pk.constraint_system;
71 template<typename ppT>
72 bool uscs_ppzksnark_verification_key<ppT>::operator==(
73 const uscs_ppzksnark_verification_key<ppT> &other) const
76 this->tilde_g2 == other.tilde_g2 &&
77 this->alpha_tilde_g2 == other.alpha_tilde_g2 &&
78 this->Z_g2 == other.Z_g2 &&
79 this->encoded_IC_query == other.encoded_IC_query);
82 template<typename ppT>
83 std::ostream &operator<<(
84 std::ostream &out, const uscs_ppzksnark_verification_key<ppT> &vk)
86 out << vk.tilde_g2 << OUTPUT_NEWLINE;
87 out << vk.alpha_tilde_g2 << OUTPUT_NEWLINE;
88 out << vk.Z_g2 << OUTPUT_NEWLINE;
89 out << vk.encoded_IC_query << OUTPUT_NEWLINE;
94 template<typename ppT>
95 std::istream &operator>>(
96 std::istream &in, uscs_ppzksnark_verification_key<ppT> &vk)
99 libff::consume_OUTPUT_NEWLINE(in);
100 in >> vk.alpha_tilde_g2;
101 libff::consume_OUTPUT_NEWLINE(in);
103 libff::consume_OUTPUT_NEWLINE(in);
104 in >> vk.encoded_IC_query;
105 libff::consume_OUTPUT_NEWLINE(in);
110 template<typename ppT>
111 bool uscs_ppzksnark_processed_verification_key<ppT>::operator==(
112 const uscs_ppzksnark_processed_verification_key<ppT> &other) const
115 this->pp_G1_one_precomp == other.pp_G1_one_precomp &&
116 this->pp_G2_one_precomp == other.pp_G2_one_precomp &&
117 this->vk_tilde_g2_precomp == other.vk_tilde_g2_precomp &&
118 this->vk_alpha_tilde_g2_precomp == other.vk_alpha_tilde_g2_precomp &&
119 this->vk_Z_g2_precomp == other.vk_Z_g2_precomp &&
120 this->pairing_of_g1_and_g2 == other.pairing_of_g1_and_g2 &&
121 this->encoded_IC_query == other.encoded_IC_query);
124 template<typename ppT>
125 std::ostream &operator<<(
127 const uscs_ppzksnark_processed_verification_key<ppT> &pvk)
129 out << pvk.pp_G1_one_precomp << OUTPUT_NEWLINE;
130 out << pvk.pp_G2_one_precomp << OUTPUT_NEWLINE;
131 out << pvk.vk_tilde_g2_precomp << OUTPUT_NEWLINE;
132 out << pvk.vk_alpha_tilde_g2_precomp << OUTPUT_NEWLINE;
133 out << pvk.vk_Z_g2_precomp << OUTPUT_NEWLINE;
134 out << pvk.pairing_of_g1_and_g2 << OUTPUT_NEWLINE;
135 out << pvk.encoded_IC_query << OUTPUT_NEWLINE;
140 template<typename ppT>
141 std::istream &operator>>(
142 std::istream &in, uscs_ppzksnark_processed_verification_key<ppT> &pvk)
144 in >> pvk.pp_G1_one_precomp;
145 libff::consume_OUTPUT_NEWLINE(in);
146 in >> pvk.pp_G2_one_precomp;
147 libff::consume_OUTPUT_NEWLINE(in);
148 in >> pvk.vk_tilde_g2_precomp;
149 libff::consume_OUTPUT_NEWLINE(in);
150 in >> pvk.vk_alpha_tilde_g2_precomp;
151 libff::consume_OUTPUT_NEWLINE(in);
152 in >> pvk.vk_Z_g2_precomp;
153 libff::consume_OUTPUT_NEWLINE(in);
154 in >> pvk.pairing_of_g1_and_g2;
155 libff::consume_OUTPUT_NEWLINE(in);
156 in >> pvk.encoded_IC_query;
157 libff::consume_OUTPUT_NEWLINE(in);
162 template<typename ppT>
163 bool uscs_ppzksnark_proof<ppT>::operator==(
164 const uscs_ppzksnark_proof<ppT> &other) const
167 this->V_g1 == other.V_g1 && this->alpha_V_g1 == other.alpha_V_g1 &&
168 this->H_g1 == other.H_g1 && this->V_g2 == other.V_g2);
171 template<typename ppT>
172 std::ostream &operator<<(
173 std::ostream &out, const uscs_ppzksnark_proof<ppT> &proof)
175 out << proof.V_g1 << OUTPUT_NEWLINE;
176 out << proof.alpha_V_g1 << OUTPUT_NEWLINE;
177 out << proof.H_g1 << OUTPUT_NEWLINE;
178 out << proof.V_g2 << OUTPUT_NEWLINE;
183 template<typename ppT>
184 std::istream &operator>>(std::istream &in, uscs_ppzksnark_proof<ppT> &proof)
187 libff::consume_OUTPUT_NEWLINE(in);
188 in >> proof.alpha_V_g1;
189 libff::consume_OUTPUT_NEWLINE(in);
191 libff::consume_OUTPUT_NEWLINE(in);
193 libff::consume_OUTPUT_NEWLINE(in);
198 template<typename ppT>
199 uscs_ppzksnark_verification_key<ppT> uscs_ppzksnark_verification_key<
200 ppT>::dummy_verification_key(const size_t input_size)
202 uscs_ppzksnark_verification_key<ppT> result;
203 result.tilde_g2 = libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
204 result.alpha_tilde_g2 =
205 libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
206 result.Z_g2 = libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
208 libff::G1<ppT> base =
209 libff::Fr<ppT>::random_element() * libff::G1<ppT>::one();
210 libff::G1_vector<ppT> v;
211 for (size_t i = 0; i < input_size; ++i) {
213 libff::Fr<ppT>::random_element() * libff::G1<ppT>::one());
216 result.encoded_IC_query = accumulation_vector<libff::G1<ppT>>(v);
221 template<typename ppT, libff::multi_exp_base_form BaseForm>
222 uscs_ppzksnark_keypair<ppT> uscs_ppzksnark_generator(
223 const uscs_ppzksnark_constraint_system<ppT> &cs)
225 libff::enter_block("Call to uscs_ppzksnark_generator");
227 /* draw random element at which the SSP is evaluated */
229 const libff::Fr<ppT> t = libff::Fr<ppT>::random_element();
231 /* perform USCS-to-SSP reduction */
233 ssp_instance_evaluation<libff::Fr<ppT>> ssp_inst =
234 uscs_to_ssp_instance_map_with_evaluation(cs, t);
236 libff::print_indent();
237 printf("* SSP number of variables: %zu\n", ssp_inst.num_variables());
238 libff::print_indent();
239 printf("* SSP pre degree: %zu\n", cs.num_constraints());
240 libff::print_indent();
241 printf("* SSP degree: %zu\n", ssp_inst.degree());
242 libff::print_indent();
243 printf("* SSP number of input variables: %zu\n", ssp_inst.num_inputs());
245 /* construct various tables of FieldT elements */
247 libff::Fr_vector<ppT> Vt_table =
248 std::move(ssp_inst.Vt); // ssp_inst.Vt is now in unspecified state, but
249 // we do not use it later
250 libff::Fr_vector<ppT> Ht_table =
251 std::move(ssp_inst.Ht); // ssp_inst.Ht is now in unspecified state, but
252 // we do not use it later
254 Vt_table.emplace_back(ssp_inst.Zt);
256 libff::Fr_vector<ppT> Xt_table = libff::Fr_vector<ppT>(
257 Vt_table.begin(), Vt_table.begin() + ssp_inst.num_inputs() + 1);
258 libff::Fr_vector<ppT> Vt_table_minus_Xt_table = libff::Fr_vector<ppT>(
259 Vt_table.begin() + ssp_inst.num_inputs() + 1, Vt_table.end());
263 assert(Vt_table.size() == ssp_inst.num_variables() + 2);
265 "Ht_table.size() = %zu, ssp_inst.degree() + 1 = %zu\n",
267 ssp_inst.degree() + 1);
268 assert(Ht_table.size() == ssp_inst.degree() + 1);
269 assert(Xt_table.size() == ssp_inst.num_inputs() + 1);
271 Vt_table_minus_Xt_table.size() ==
272 ssp_inst.num_variables() + 2 - ssp_inst.num_inputs() - 1);
273 for (size_t i = 0; i < ssp_inst.num_inputs() + 1; ++i) {
274 assert(!Xt_table[i].is_zero());
277 const libff::Fr<ppT> alpha = libff::Fr<ppT>::random_element();
279 libff::enter_block("Generate USCS proving key");
281 const size_t g1_exp_count =
282 Vt_table.size() + Vt_table_minus_Xt_table.size() + Ht_table.size();
283 const size_t g2_exp_count = Vt_table_minus_Xt_table.size();
285 size_t g1_window = libff::get_exp_window_size<libff::G1<ppT>>(g1_exp_count);
286 size_t g2_window = libff::get_exp_window_size<libff::G2<ppT>>(g2_exp_count);
288 libff::print_indent();
289 printf("* G1 window: %zu\n", g1_window);
290 libff::print_indent();
291 printf("* G2 window: %zu\n", g2_window);
293 libff::enter_block("Generating G1 multiexp table");
294 libff::window_table<libff::G1<ppT>> g1_table = get_window_table(
295 libff::Fr<ppT>::size_in_bits(), g1_window, libff::G1<ppT>::one());
296 libff::leave_block("Generating G1 multiexp table");
298 libff::enter_block("Generating G2 multiexp table");
299 libff::window_table<libff::G2<ppT>> g2_table = get_window_table(
300 libff::Fr<ppT>::size_in_bits(), g2_window, libff::G2<ppT>::one());
301 libff::leave_block("Generating G2 multiexp table");
303 libff::enter_block("Generate proof components");
305 libff::enter_block("Compute the query for V_g1", false);
306 libff::G1_vector<ppT> V_g1_query = batch_exp(
307 libff::Fr<ppT>::size_in_bits(),
310 Vt_table_minus_Xt_table);
311 if (BaseForm == libff::multi_exp_base_form_special) {
312 libff::batch_to_special<libff::G1<ppT>>(V_g1_query);
314 libff::leave_block("Compute the query for V_g1", false);
316 libff::enter_block("Compute the query for alpha_V_g1", false);
317 libff::G1_vector<ppT> alpha_V_g1_query = batch_exp_with_coeff(
318 libff::Fr<ppT>::size_in_bits(),
322 Vt_table_minus_Xt_table);
323 if (BaseForm == libff::multi_exp_base_form_special) {
324 libff::batch_to_special<libff::G1<ppT>>(alpha_V_g1_query);
326 libff::leave_block("Compute the query for alpha_V_g1", false);
328 libff::enter_block("Compute the query for H_g1", false);
329 libff::G1_vector<ppT> H_g1_query = batch_exp(
330 libff::Fr<ppT>::size_in_bits(), g1_window, g1_table, Ht_table);
331 if (BaseForm == libff::multi_exp_base_form_special) {
332 libff::batch_to_special<libff::G1<ppT>>(H_g1_query);
334 libff::leave_block("Compute the query for H_g1", false);
336 libff::enter_block("Compute the query for V_g2", false);
337 libff::G2_vector<ppT> V_g2_query = batch_exp(
338 libff::Fr<ppT>::size_in_bits(), g2_window, g2_table, Vt_table);
339 if (BaseForm == libff::multi_exp_base_form_special) {
340 libff::batch_to_special<libff::G2<ppT>>(V_g2_query);
342 libff::leave_block("Compute the query for V_g2", false);
344 libff::leave_block("Generate proof components");
346 libff::leave_block("Generate USCS proving key");
348 libff::enter_block("Generate USCS verification key");
350 const libff::Fr<ppT> tilde = libff::Fr<ppT>::random_element();
351 libff::G2<ppT> tilde_g2 = tilde * libff::G2<ppT>::one();
352 libff::G2<ppT> alpha_tilde_g2 = (alpha * tilde) * libff::G2<ppT>::one();
353 libff::G2<ppT> Z_g2 = ssp_inst.Zt * libff::G2<ppT>::one();
355 libff::enter_block("Encode IC query for USCS verification key");
356 libff::G1<ppT> encoded_IC_base = Xt_table[0] * libff::G1<ppT>::one();
357 libff::G1_vector<ppT> encoded_IC_values = batch_exp(
358 libff::Fr<ppT>::size_in_bits(),
361 libff::Fr_vector<ppT>(Xt_table.begin() + 1, Xt_table.end()));
362 libff::leave_block("Encode IC query for USCS verification key");
364 libff::leave_block("Generate USCS verification key");
366 libff::leave_block("Call to uscs_ppzksnark_generator");
368 accumulation_vector<libff::G1<ppT>> encoded_IC_query(
369 std::move(encoded_IC_base), std::move(encoded_IC_values));
371 uscs_ppzksnark_verification_key<ppT> vk =
372 uscs_ppzksnark_verification_key<ppT>(
373 tilde_g2, alpha_tilde_g2, Z_g2, encoded_IC_query);
375 uscs_ppzksnark_constraint_system<ppT> cs_copy = cs;
376 uscs_ppzksnark_proving_key<ppT> pk = uscs_ppzksnark_proving_key<ppT>(
377 std::move(V_g1_query),
378 std::move(alpha_V_g1_query),
379 std::move(H_g1_query),
380 std::move(V_g2_query),
386 return uscs_ppzksnark_keypair<ppT>(std::move(pk), std::move(vk));
391 libff::multi_exp_method Method,
392 libff::multi_exp_base_form BaseForm>
393 uscs_ppzksnark_proof<ppT> uscs_ppzksnark_prover(
394 const uscs_ppzksnark_proving_key<ppT> &pk,
395 const uscs_ppzksnark_primary_input<ppT> &primary_input,
396 const uscs_ppzksnark_auxiliary_input<ppT> &auxiliary_input)
398 libff::enter_block("Call to uscs_ppzksnark_prover");
400 const libff::Fr<ppT> d = libff::Fr<ppT>::random_element();
402 libff::enter_block("Compute the polynomial H");
403 const ssp_witness<libff::Fr<ppT>> ssp_wit = uscs_to_ssp_witness_map(
404 pk.constraint_system, primary_input, auxiliary_input, d);
405 libff::leave_block("Compute the polynomial H");
408 assert(pk.constraint_system.is_satisfied(primary_input, auxiliary_input));
410 pk.V_g1_query.size() ==
411 ssp_wit.num_variables() + 2 - ssp_wit.num_inputs() - 1);
413 pk.alpha_V_g1_query.size() ==
414 ssp_wit.num_variables() + 2 - ssp_wit.num_inputs() - 1);
415 assert(pk.H_g1_query.size() == ssp_wit.degree() + 1);
416 assert(pk.V_g2_query.size() == ssp_wit.num_variables() + 2);
419 const libff::Fr<ppT> t = libff::Fr<ppT>::random_element();
420 ssp_instance_evaluation<libff::Fr<ppT>> ssp_inst =
421 uscs_to_ssp_instance_map_with_evaluation(pk.constraint_system, t);
422 assert(ssp_inst.is_satisfied(ssp_wit));
425 libff::G1<ppT> V_g1 = ssp_wit.d * pk.V_g1_query[pk.V_g1_query.size() - 1];
426 libff::G1<ppT> alpha_V_g1 =
427 ssp_wit.d * pk.alpha_V_g1_query[pk.alpha_V_g1_query.size() - 1];
428 libff::G1<ppT> H_g1 = libff::G1<ppT>::zero();
429 libff::G2<ppT> V_g2 =
430 pk.V_g2_query[0] + ssp_wit.d * pk.V_g2_query[pk.V_g2_query.size() - 1];
433 const size_t chunks =
434 omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or
435 // call omp_set_num_threads()
437 const size_t chunks = 1;
440 // MAYBE LATER: do queries 1,2,4 at once for slightly better speed
442 libff::enter_block("Compute the proof");
444 libff::enter_block("Compute V_g1, the 1st component of the proof", false);
446 libff::multi_exp_filter_one_zero<
451 pk.V_g1_query.begin(),
452 pk.V_g1_query.begin() +
453 (ssp_wit.num_variables() - ssp_wit.num_inputs()),
454 ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_inputs(),
455 ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_variables(),
457 libff::leave_block("Compute V_g1, the 1st component of the proof", false);
460 "Compute alpha_V_g1, the 2nd component of the proof", false);
463 libff::multi_exp_filter_one_zero<
468 pk.alpha_V_g1_query.begin(),
469 pk.alpha_V_g1_query.begin() +
470 (ssp_wit.num_variables() - ssp_wit.num_inputs()),
471 ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_inputs(),
472 ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_variables(),
475 "Compute alpha_V_g1, the 2nd component of the proof", false);
477 libff::enter_block("Compute H_g1, the 3rd component of the proof", false);
479 libff::multi_exp<libff::G1<ppT>, libff::Fr<ppT>, Method, BaseForm>(
480 pk.H_g1_query.begin(),
481 pk.H_g1_query.begin() + ssp_wit.degree() + 1,
482 ssp_wit.coefficients_for_H.begin(),
483 ssp_wit.coefficients_for_H.begin() + ssp_wit.degree() + 1,
485 libff::leave_block("Compute H_g1, the 3rd component of the proof", false);
487 libff::enter_block("Compute V_g2, the 4th component of the proof", false);
489 libff::multi_exp<libff::G2<ppT>, libff::Fr<ppT>, Method, BaseForm>(
490 pk.V_g2_query.begin() + 1,
491 pk.V_g2_query.begin() + ssp_wit.num_variables() + 1,
492 ssp_wit.coefficients_for_Vs.begin(),
493 ssp_wit.coefficients_for_Vs.begin() + ssp_wit.num_variables(),
495 libff::leave_block("Compute V_g2, the 4th component of the proof", false);
497 libff::leave_block("Compute the proof");
499 libff::leave_block("Call to uscs_ppzksnark_prover");
501 uscs_ppzksnark_proof<ppT> proof = uscs_ppzksnark_proof<ppT>(
503 std::move(alpha_V_g1),
512 template<typename ppT>
513 uscs_ppzksnark_processed_verification_key<ppT> uscs_ppzksnark_verifier_process_vk(
514 const uscs_ppzksnark_verification_key<ppT> &vk)
516 libff::enter_block("Call to uscs_ppzksnark_verifier_process_vk");
518 uscs_ppzksnark_processed_verification_key<ppT> pvk;
520 pvk.pp_G1_one_precomp = ppT::precompute_G1(libff::G1<ppT>::one());
521 pvk.pp_G2_one_precomp = ppT::precompute_G2(libff::G2<ppT>::one());
523 pvk.vk_tilde_g2_precomp = ppT::precompute_G2(vk.tilde_g2);
524 pvk.vk_alpha_tilde_g2_precomp = ppT::precompute_G2(vk.alpha_tilde_g2);
525 pvk.vk_Z_g2_precomp = ppT::precompute_G2(vk.Z_g2);
527 pvk.pairing_of_g1_and_g2 =
528 ppT::miller_loop(pvk.pp_G1_one_precomp, pvk.pp_G2_one_precomp);
530 pvk.encoded_IC_query = vk.encoded_IC_query;
532 libff::leave_block("Call to uscs_ppzksnark_verifier_process_vk");
537 template<typename ppT>
538 bool uscs_ppzksnark_online_verifier_weak_IC(
539 const uscs_ppzksnark_processed_verification_key<ppT> &pvk,
540 const uscs_ppzksnark_primary_input<ppT> &primary_input,
541 const uscs_ppzksnark_proof<ppT> &proof)
543 libff::enter_block("Call to uscs_ppzksnark_online_verifier_weak_IC");
544 assert(pvk.encoded_IC_query.domain_size() >= primary_input.size());
546 libff::enter_block("Compute input-dependent part of V");
547 const accumulation_vector<libff::G1<ppT>> accumulated_IC =
548 pvk.encoded_IC_query.template accumulate_chunk<libff::Fr<ppT>>(
549 primary_input.begin(), primary_input.end(), 0);
550 assert(accumulated_IC.is_fully_accumulated());
551 const libff::G1<ppT> &acc = accumulated_IC.first;
552 libff::leave_block("Compute input-dependent part of V");
556 libff::enter_block("Check if the proof is well-formed");
557 if (!proof.is_well_formed()) {
558 if (!libff::inhibit_profiling_info) {
559 libff::print_indent();
561 "At least one of the proof components is not well-formed.\n");
565 libff::leave_block("Check if the proof is well-formed");
567 libff::enter_block("Online pairing computations");
569 libff::enter_block("Check knowledge commitment for V is valid");
570 libff::G1_precomp<ppT> proof_V_g1_with_acc_precomp =
571 ppT::precompute_G1(proof.V_g1 + acc);
572 libff::G2_precomp<ppT> proof_V_g2_precomp = ppT::precompute_G2(proof.V_g2);
573 libff::Fqk<ppT> V_1 =
574 ppT::miller_loop(proof_V_g1_with_acc_precomp, pvk.pp_G2_one_precomp);
575 libff::Fqk<ppT> V_2 =
576 ppT::miller_loop(pvk.pp_G1_one_precomp, proof_V_g2_precomp);
577 libff::GT<ppT> V = ppT::final_exponentiation(V_1 * V_2.unitary_inverse());
578 if (V != libff::GT<ppT>::one()) {
579 if (!libff::inhibit_profiling_info) {
580 libff::print_indent();
581 printf("Knowledge commitment for V invalid.\n");
585 libff::leave_block("Check knowledge commitment for V is valid");
587 libff::enter_block("Check SSP divisibility"); // i.e., check that V^2=H*Z+1
588 libff::G1_precomp<ppT> proof_H_g1_precomp = ppT::precompute_G1(proof.H_g1);
589 libff::Fqk<ppT> SSP_1 =
590 ppT::miller_loop(proof_V_g1_with_acc_precomp, proof_V_g2_precomp);
591 libff::Fqk<ppT> SSP_2 =
592 ppT::miller_loop(proof_H_g1_precomp, pvk.vk_Z_g2_precomp);
593 libff::GT<ppT> SSP = ppT::final_exponentiation(
594 SSP_1.unitary_inverse() * SSP_2 * pvk.pairing_of_g1_and_g2);
595 if (SSP != libff::GT<ppT>::one()) {
596 if (!libff::inhibit_profiling_info) {
597 libff::print_indent();
598 printf("SSP divisibility check failed.\n");
602 libff::leave_block("Check SSP divisibility");
604 libff::enter_block("Check same coefficients were used");
605 libff::G1_precomp<ppT> proof_V_g1_precomp = ppT::precompute_G1(proof.V_g1);
606 libff::G1_precomp<ppT> proof_alpha_V_g1_precomp =
607 ppT::precompute_G1(proof.alpha_V_g1);
608 libff::Fqk<ppT> alpha_V_1 =
609 ppT::miller_loop(proof_V_g1_precomp, pvk.vk_alpha_tilde_g2_precomp);
610 libff::Fqk<ppT> alpha_V_2 =
611 ppT::miller_loop(proof_alpha_V_g1_precomp, pvk.vk_tilde_g2_precomp);
612 libff::GT<ppT> alpha_V =
613 ppT::final_exponentiation(alpha_V_1 * alpha_V_2.unitary_inverse());
614 if (alpha_V != libff::GT<ppT>::one()) {
615 if (!libff::inhibit_profiling_info) {
616 libff::print_indent();
617 printf("Same-coefficient check failed.\n");
621 libff::leave_block("Check same coefficients were used");
623 libff::leave_block("Online pairing computations");
625 libff::leave_block("Call to uscs_ppzksnark_online_verifier_weak_IC");
630 template<typename ppT>
631 bool uscs_ppzksnark_verifier_weak_IC(
632 const uscs_ppzksnark_verification_key<ppT> &vk,
633 const uscs_ppzksnark_primary_input<ppT> &primary_input,
634 const uscs_ppzksnark_proof<ppT> &proof)
636 libff::enter_block("Call to uscs_ppzksnark_verifier_weak_IC");
637 uscs_ppzksnark_processed_verification_key<ppT> pvk =
638 uscs_ppzksnark_verifier_process_vk<ppT>(vk);
640 uscs_ppzksnark_online_verifier_weak_IC<ppT>(pvk, primary_input, proof);
641 libff::leave_block("Call to uscs_ppzksnark_verifier_weak_IC");
645 template<typename ppT>
646 bool uscs_ppzksnark_online_verifier_strong_IC(
647 const uscs_ppzksnark_processed_verification_key<ppT> &pvk,
648 const uscs_ppzksnark_primary_input<ppT> &primary_input,
649 const uscs_ppzksnark_proof<ppT> &proof)
652 libff::enter_block("Call to uscs_ppzksnark_online_verifier_strong_IC");
654 if (pvk.encoded_IC_query.domain_size() != primary_input.size()) {
655 libff::print_indent();
657 "Input length differs from expected (got %zu, expected %zu).\n",
658 primary_input.size(),
659 pvk.encoded_IC_query.domain_size());
663 uscs_ppzksnark_online_verifier_weak_IC(pvk, primary_input, proof);
666 libff::leave_block("Call to uscs_ppzksnark_online_verifier_strong_IC");
670 template<typename ppT>
671 bool uscs_ppzksnark_verifier_strong_IC(
672 const uscs_ppzksnark_verification_key<ppT> &vk,
673 const uscs_ppzksnark_primary_input<ppT> &primary_input,
674 const uscs_ppzksnark_proof<ppT> &proof)
676 libff::enter_block("Call to uscs_ppzksnark_verifier_strong_IC");
677 uscs_ppzksnark_processed_verification_key<ppT> pvk =
678 uscs_ppzksnark_verifier_process_vk<ppT>(vk);
679 bool result = uscs_ppzksnark_online_verifier_strong_IC<ppT>(
680 pvk, primary_input, proof);
681 libff::leave_block("Call to uscs_ppzksnark_verifier_strong_IC");
685 } // namespace libsnark
687 #endif // USCS_PPZKSNARK_TCC_