2 *****************************************************************************
 
    4 Implementation of interfaces for a ppzkSNARK for R1CS.
 
    6 See r1cs_ppzksnark.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 R1CS_PPZKSNARK_TCC_
 
   15 #define R1CS_PPZKSNARK_TCC_
 
   21 #include <libff/algebra/scalar_multiplication/multiexp.hpp>
 
   22 #include <libff/common/profiling.hpp>
 
   23 #include <libff/common/utils.hpp>
 
   30 #include <libsnark/knowledge_commitment/kc_multiexp.hpp>
 
   31 #include <libsnark/reductions/r1cs_to_qap/r1cs_to_qap.hpp>
 
   36 template<typename ppT>
 
   37 bool r1cs_ppzksnark_proving_key<ppT>::operator==(
 
   38     const r1cs_ppzksnark_proving_key<ppT> &other) const
 
   41         this->A_query == other.A_query && this->B_query == other.B_query &&
 
   42         this->C_query == other.C_query && this->H_query == other.H_query &&
 
   43         this->K_query == other.K_query &&
 
   44         this->constraint_system == other.constraint_system);
 
   47 template<typename ppT>
 
   48 std::ostream &operator<<(
 
   49     std::ostream &out, const r1cs_ppzksnark_proving_key<ppT> &pk)
 
   56     out << pk.constraint_system;
 
   61 template<typename ppT>
 
   62 std::istream &operator>>(std::istream &in, r1cs_ppzksnark_proving_key<ppT> &pk)
 
   69     in >> pk.constraint_system;
 
   74 template<typename ppT>
 
   75 bool r1cs_ppzksnark_verification_key<ppT>::operator==(
 
   76     const r1cs_ppzksnark_verification_key<ppT> &other) const
 
   79         this->alphaA_g2 == other.alphaA_g2 &&
 
   80         this->alphaB_g1 == other.alphaB_g1 &&
 
   81         this->alphaC_g2 == other.alphaC_g2 &&
 
   82         this->gamma_g2 == other.gamma_g2 &&
 
   83         this->gamma_beta_g1 == other.gamma_beta_g1 &&
 
   84         this->gamma_beta_g2 == other.gamma_beta_g2 &&
 
   85         this->rC_Z_g2 == other.rC_Z_g2 &&
 
   86         this->encoded_IC_query == other.encoded_IC_query);
 
   89 template<typename ppT>
 
   90 std::ostream &operator<<(
 
   91     std::ostream &out, const r1cs_ppzksnark_verification_key<ppT> &vk)
 
   93     out << vk.alphaA_g2 << OUTPUT_NEWLINE;
 
   94     out << vk.alphaB_g1 << OUTPUT_NEWLINE;
 
   95     out << vk.alphaC_g2 << OUTPUT_NEWLINE;
 
   96     out << vk.gamma_g2 << OUTPUT_NEWLINE;
 
   97     out << vk.gamma_beta_g1 << OUTPUT_NEWLINE;
 
   98     out << vk.gamma_beta_g2 << OUTPUT_NEWLINE;
 
   99     out << vk.rC_Z_g2 << OUTPUT_NEWLINE;
 
  100     out << vk.encoded_IC_query << OUTPUT_NEWLINE;
 
  105 template<typename ppT>
 
  106 std::istream &operator>>(
 
  107     std::istream &in, r1cs_ppzksnark_verification_key<ppT> &vk)
 
  110     libff::consume_OUTPUT_NEWLINE(in);
 
  112     libff::consume_OUTPUT_NEWLINE(in);
 
  114     libff::consume_OUTPUT_NEWLINE(in);
 
  116     libff::consume_OUTPUT_NEWLINE(in);
 
  117     in >> vk.gamma_beta_g1;
 
  118     libff::consume_OUTPUT_NEWLINE(in);
 
  119     in >> vk.gamma_beta_g2;
 
  120     libff::consume_OUTPUT_NEWLINE(in);
 
  122     libff::consume_OUTPUT_NEWLINE(in);
 
  123     in >> vk.encoded_IC_query;
 
  124     libff::consume_OUTPUT_NEWLINE(in);
 
  129 template<typename ppT>
 
  130 bool r1cs_ppzksnark_processed_verification_key<ppT>::operator==(
 
  131     const r1cs_ppzksnark_processed_verification_key<ppT> &other) const
 
  134         this->pp_G2_one_precomp == other.pp_G2_one_precomp &&
 
  135         this->vk_alphaA_g2_precomp == other.vk_alphaA_g2_precomp &&
 
  136         this->vk_alphaB_g1_precomp == other.vk_alphaB_g1_precomp &&
 
  137         this->vk_alphaC_g2_precomp == other.vk_alphaC_g2_precomp &&
 
  138         this->vk_rC_Z_g2_precomp == other.vk_rC_Z_g2_precomp &&
 
  139         this->vk_gamma_g2_precomp == other.vk_gamma_g2_precomp &&
 
  140         this->vk_gamma_beta_g1_precomp == other.vk_gamma_beta_g1_precomp &&
 
  141         this->vk_gamma_beta_g2_precomp == other.vk_gamma_beta_g2_precomp &&
 
  142         this->encoded_IC_query == other.encoded_IC_query);
 
  145 template<typename ppT>
 
  146 std::ostream &operator<<(
 
  148     const r1cs_ppzksnark_processed_verification_key<ppT> &pvk)
 
  150     out << pvk.pp_G2_one_precomp << OUTPUT_NEWLINE;
 
  151     out << pvk.vk_alphaA_g2_precomp << OUTPUT_NEWLINE;
 
  152     out << pvk.vk_alphaB_g1_precomp << OUTPUT_NEWLINE;
 
  153     out << pvk.vk_alphaC_g2_precomp << OUTPUT_NEWLINE;
 
  154     out << pvk.vk_rC_Z_g2_precomp << OUTPUT_NEWLINE;
 
  155     out << pvk.vk_gamma_g2_precomp << OUTPUT_NEWLINE;
 
  156     out << pvk.vk_gamma_beta_g1_precomp << OUTPUT_NEWLINE;
 
  157     out << pvk.vk_gamma_beta_g2_precomp << OUTPUT_NEWLINE;
 
  158     out << pvk.encoded_IC_query << OUTPUT_NEWLINE;
 
  163 template<typename ppT>
 
  164 std::istream &operator>>(
 
  165     std::istream &in, r1cs_ppzksnark_processed_verification_key<ppT> &pvk)
 
  167     in >> pvk.pp_G2_one_precomp;
 
  168     libff::consume_OUTPUT_NEWLINE(in);
 
  169     in >> pvk.vk_alphaA_g2_precomp;
 
  170     libff::consume_OUTPUT_NEWLINE(in);
 
  171     in >> pvk.vk_alphaB_g1_precomp;
 
  172     libff::consume_OUTPUT_NEWLINE(in);
 
  173     in >> pvk.vk_alphaC_g2_precomp;
 
  174     libff::consume_OUTPUT_NEWLINE(in);
 
  175     in >> pvk.vk_rC_Z_g2_precomp;
 
  176     libff::consume_OUTPUT_NEWLINE(in);
 
  177     in >> pvk.vk_gamma_g2_precomp;
 
  178     libff::consume_OUTPUT_NEWLINE(in);
 
  179     in >> pvk.vk_gamma_beta_g1_precomp;
 
  180     libff::consume_OUTPUT_NEWLINE(in);
 
  181     in >> pvk.vk_gamma_beta_g2_precomp;
 
  182     libff::consume_OUTPUT_NEWLINE(in);
 
  183     in >> pvk.encoded_IC_query;
 
  184     libff::consume_OUTPUT_NEWLINE(in);
 
  189 template<typename ppT>
 
  190 bool r1cs_ppzksnark_proof<ppT>::operator==(
 
  191     const r1cs_ppzksnark_proof<ppT> &other) const
 
  194         this->g_A == other.g_A && this->g_B == other.g_B &&
 
  195         this->g_C == other.g_C && this->g_H == other.g_H &&
 
  196         this->g_K == other.g_K);
 
  199 template<typename ppT>
 
  200 std::ostream &operator<<(
 
  201     std::ostream &out, const r1cs_ppzksnark_proof<ppT> &proof)
 
  203     out << proof.g_A << OUTPUT_NEWLINE;
 
  204     out << proof.g_B << OUTPUT_NEWLINE;
 
  205     out << proof.g_C << OUTPUT_NEWLINE;
 
  206     out << proof.g_H << OUTPUT_NEWLINE;
 
  207     out << proof.g_K << OUTPUT_NEWLINE;
 
  212 template<typename ppT>
 
  213 std::istream &operator>>(std::istream &in, r1cs_ppzksnark_proof<ppT> &proof)
 
  216     libff::consume_OUTPUT_NEWLINE(in);
 
  218     libff::consume_OUTPUT_NEWLINE(in);
 
  220     libff::consume_OUTPUT_NEWLINE(in);
 
  222     libff::consume_OUTPUT_NEWLINE(in);
 
  224     libff::consume_OUTPUT_NEWLINE(in);
 
  229 template<typename ppT>
 
  230 r1cs_ppzksnark_verification_key<ppT> r1cs_ppzksnark_verification_key<
 
  231     ppT>::dummy_verification_key(const size_t input_size)
 
  233     r1cs_ppzksnark_verification_key<ppT> result;
 
  234     result.alphaA_g2 = libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
 
  235     result.alphaB_g1 = libff::Fr<ppT>::random_element() * libff::G1<ppT>::one();
 
  236     result.alphaC_g2 = libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
 
  237     result.gamma_g2 = libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
 
  238     result.gamma_beta_g1 =
 
  239         libff::Fr<ppT>::random_element() * libff::G1<ppT>::one();
 
  240     result.gamma_beta_g2 =
 
  241         libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
 
  242     result.rC_Z_g2 = libff::Fr<ppT>::random_element() * libff::G2<ppT>::one();
 
  244     libff::G1<ppT> base =
 
  245         libff::Fr<ppT>::random_element() * libff::G1<ppT>::one();
 
  246     libff::G1_vector<ppT> v;
 
  247     for (size_t i = 0; i < input_size; ++i) {
 
  249             libff::Fr<ppT>::random_element() * libff::G1<ppT>::one());
 
  252     result.encoded_IC_query =
 
  253         accumulation_vector<libff::G1<ppT>>(std::move(base), std::move(v));
 
  258 template<typename ppT, libff::multi_exp_base_form BaseForm>
 
  259 r1cs_ppzksnark_keypair<ppT> r1cs_ppzksnark_generator(
 
  260     const r1cs_ppzksnark_constraint_system<ppT> &cs)
 
  262     libff::enter_block("Call to r1cs_ppzksnark_generator");
 
  264     /* make the B_query "lighter" if possible */
 
  265     r1cs_ppzksnark_constraint_system<ppT> cs_copy(cs);
 
  266     cs_copy.swap_AB_if_beneficial();
 
  268     /* draw random element at which the QAP is evaluated */
 
  269     const libff::Fr<ppT> t = libff::Fr<ppT>::random_element();
 
  271     qap_instance_evaluation<libff::Fr<ppT>> qap_inst =
 
  272         r1cs_to_qap_instance_map_with_evaluation(cs_copy, t);
 
  274     libff::print_indent();
 
  275     printf("* QAP number of variables: %zu\n", qap_inst.num_variables());
 
  276     libff::print_indent();
 
  277     printf("* QAP pre degree: %zu\n", cs_copy.constraints.size());
 
  278     libff::print_indent();
 
  279     printf("* QAP degree: %zu\n", qap_inst.degree());
 
  280     libff::print_indent();
 
  281     printf("* QAP number of input variables: %zu\n", qap_inst.num_inputs());
 
  283     libff::enter_block("Compute query densities");
 
  284     size_t non_zero_At = 0, non_zero_Bt = 0, non_zero_Ct = 0, non_zero_Ht = 0;
 
  285     for (size_t i = 0; i < qap_inst.num_variables() + 1; ++i) {
 
  286         if (!qap_inst.At[i].is_zero()) {
 
  289         if (!qap_inst.Bt[i].is_zero()) {
 
  292         if (!qap_inst.Ct[i].is_zero()) {
 
  296     for (size_t i = 0; i < qap_inst.degree() + 1; ++i) {
 
  297         if (!qap_inst.Ht[i].is_zero()) {
 
  301     libff::leave_block("Compute query densities");
 
  303     libff::Fr_vector<ppT> At =
 
  304         std::move(qap_inst.At); // qap_inst.At is now in unspecified state, but
 
  305                                 // we do not use it later
 
  306     libff::Fr_vector<ppT> Bt =
 
  307         std::move(qap_inst.Bt); // qap_inst.Bt is now in unspecified state, but
 
  308                                 // we do not use it later
 
  309     libff::Fr_vector<ppT> Ct =
 
  310         std::move(qap_inst.Ct); // qap_inst.Ct is now in unspecified state, but
 
  311                                 // we do not use it later
 
  312     libff::Fr_vector<ppT> Ht =
 
  313         std::move(qap_inst.Ht); // qap_inst.Ht is now in unspecified state, but
 
  314                                 // we do not use it later
 
  316     /* append Zt to At,Bt,Ct with */
 
  317     At.emplace_back(qap_inst.Zt);
 
  318     Bt.emplace_back(qap_inst.Zt);
 
  319     Ct.emplace_back(qap_inst.Zt);
 
  321     const libff::Fr<ppT> alphaA = libff::Fr<ppT>::random_element(),
 
  322                          alphaB = libff::Fr<ppT>::random_element(),
 
  323                          alphaC = libff::Fr<ppT>::random_element(),
 
  324                          rA = libff::Fr<ppT>::random_element(),
 
  325                          rB = libff::Fr<ppT>::random_element(),
 
  326                          beta = libff::Fr<ppT>::random_element(),
 
  327                          gamma = libff::Fr<ppT>::random_element();
 
  328     const libff::Fr<ppT> rC = rA * rB;
 
  330     // consrtuct the same-coefficient-check query (must happen before zeroing
 
  331     // out the prefix of At)
 
  332     libff::Fr_vector<ppT> Kt;
 
  333     Kt.reserve(qap_inst.num_variables() + 4);
 
  334     for (size_t i = 0; i < qap_inst.num_variables() + 1; ++i) {
 
  335         Kt.emplace_back(beta * (rA * At[i] + rB * Bt[i] + rC * Ct[i]));
 
  337     Kt.emplace_back(beta * rA * qap_inst.Zt);
 
  338     Kt.emplace_back(beta * rB * qap_inst.Zt);
 
  339     Kt.emplace_back(beta * rC * qap_inst.Zt);
 
  341     /* zero out prefix of At and stick it into IC coefficients */
 
  342     libff::Fr_vector<ppT> IC_coefficients;
 
  343     IC_coefficients.reserve(qap_inst.num_inputs() + 1);
 
  344     for (size_t i = 0; i < qap_inst.num_inputs() + 1; ++i) {
 
  345         IC_coefficients.emplace_back(At[i]);
 
  346         assert(!IC_coefficients[i].is_zero());
 
  347         At[i] = libff::Fr<ppT>::zero();
 
  350     const size_t g1_exp_count =
 
  351         2 * (non_zero_At - qap_inst.num_inputs() + non_zero_Ct) + non_zero_Bt +
 
  352         non_zero_Ht + Kt.size();
 
  353     const size_t g2_exp_count = non_zero_Bt;
 
  355     size_t g1_window = libff::get_exp_window_size<libff::G1<ppT>>(g1_exp_count);
 
  356     size_t g2_window = libff::get_exp_window_size<libff::G2<ppT>>(g2_exp_count);
 
  357     libff::print_indent();
 
  358     printf("* G1 window: %zu\n", g1_window);
 
  359     libff::print_indent();
 
  360     printf("* G2 window: %zu\n", g2_window);
 
  363     const size_t chunks =
 
  364         omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or
 
  365                                // call omp_set_num_threads()
 
  367     const size_t chunks = 1;
 
  370     libff::enter_block("Generating G1 multiexp table");
 
  371     libff::window_table<libff::G1<ppT>> g1_table = get_window_table(
 
  372         libff::Fr<ppT>::size_in_bits(), g1_window, libff::G1<ppT>::one());
 
  373     libff::leave_block("Generating G1 multiexp table");
 
  375     libff::enter_block("Generating G2 multiexp table");
 
  376     libff::window_table<libff::G2<ppT>> g2_table = get_window_table(
 
  377         libff::Fr<ppT>::size_in_bits(), g2_window, libff::G2<ppT>::one());
 
  378     libff::leave_block("Generating G2 multiexp table");
 
  380     libff::enter_block("Generate R1CS proving key");
 
  382     libff::enter_block("Generate knowledge commitments");
 
  383     libff::enter_block("Compute the A-query", false);
 
  384     knowledge_commitment_vector<libff::G1<ppT>, libff::G1<ppT>> A_query =
 
  386             libff::Fr<ppT>::size_in_bits(),
 
  395             BaseForm == libff::multi_exp_base_form_special);
 
  396     libff::leave_block("Compute the A-query", false);
 
  398     libff::enter_block("Compute the B-query", false);
 
  399     knowledge_commitment_vector<libff::G2<ppT>, libff::G1<ppT>> B_query =
 
  401             libff::Fr<ppT>::size_in_bits(),
 
  410             BaseForm == libff::multi_exp_base_form_special);
 
  411     libff::leave_block("Compute the B-query", false);
 
  413     libff::enter_block("Compute the C-query", false);
 
  414     knowledge_commitment_vector<libff::G1<ppT>, libff::G1<ppT>> C_query =
 
  416             libff::Fr<ppT>::size_in_bits(),
 
  425             BaseForm == libff::multi_exp_base_form_special);
 
  426     libff::leave_block("Compute the C-query", false);
 
  428     libff::enter_block("Compute the H-query", false);
 
  429     libff::G1_vector<ppT> H_query =
 
  430         batch_exp(libff::Fr<ppT>::size_in_bits(), g1_window, g1_table, Ht);
 
  431     if (BaseForm == libff::multi_exp_base_form_special) {
 
  432         libff::batch_to_special<libff::G1<ppT>>(H_query);
 
  434     libff::leave_block("Compute the H-query", false);
 
  436     libff::enter_block("Compute the K-query", false);
 
  437     libff::G1_vector<ppT> K_query =
 
  438         batch_exp(libff::Fr<ppT>::size_in_bits(), g1_window, g1_table, Kt);
 
  439     if (BaseForm == libff::multi_exp_base_form_special) {
 
  440         libff::batch_to_special<libff::G1<ppT>>(K_query);
 
  442     libff::leave_block("Compute the K-query", false);
 
  444     libff::leave_block("Generate knowledge commitments");
 
  446     libff::leave_block("Generate R1CS proving key");
 
  448     libff::enter_block("Generate R1CS verification key");
 
  449     libff::G2<ppT> alphaA_g2 = alphaA * libff::G2<ppT>::one();
 
  450     libff::G1<ppT> alphaB_g1 = alphaB * libff::G1<ppT>::one();
 
  451     libff::G2<ppT> alphaC_g2 = alphaC * libff::G2<ppT>::one();
 
  452     libff::G2<ppT> gamma_g2 = gamma * libff::G2<ppT>::one();
 
  453     libff::G1<ppT> gamma_beta_g1 = (gamma * beta) * libff::G1<ppT>::one();
 
  454     libff::G2<ppT> gamma_beta_g2 = (gamma * beta) * libff::G2<ppT>::one();
 
  455     libff::G2<ppT> rC_Z_g2 = (rC * qap_inst.Zt) * libff::G2<ppT>::one();
 
  457     libff::enter_block("Encode IC query for R1CS verification key");
 
  458     libff::G1<ppT> encoded_IC_base =
 
  459         (rA * IC_coefficients[0]) * libff::G1<ppT>::one();
 
  460     libff::Fr_vector<ppT> multiplied_IC_coefficients;
 
  461     multiplied_IC_coefficients.reserve(qap_inst.num_inputs());
 
  462     for (size_t i = 1; i < qap_inst.num_inputs() + 1; ++i) {
 
  463         multiplied_IC_coefficients.emplace_back(rA * IC_coefficients[i]);
 
  465     libff::G1_vector<ppT> encoded_IC_values = batch_exp(
 
  466         libff::Fr<ppT>::size_in_bits(),
 
  469         multiplied_IC_coefficients);
 
  471     libff::leave_block("Encode IC query for R1CS verification key");
 
  472     libff::leave_block("Generate R1CS verification key");
 
  474     libff::leave_block("Call to r1cs_ppzksnark_generator");
 
  476     accumulation_vector<libff::G1<ppT>> encoded_IC_query(
 
  477         std::move(encoded_IC_base), std::move(encoded_IC_values));
 
  479     r1cs_ppzksnark_verification_key<ppT> vk =
 
  480         r1cs_ppzksnark_verification_key<ppT>(
 
  489     r1cs_ppzksnark_proving_key<ppT> pk = r1cs_ppzksnark_proving_key<ppT>(
 
  500     return r1cs_ppzksnark_keypair<ppT>(std::move(pk), std::move(vk));
 
  505     libff::multi_exp_method Method,
 
  506     libff::multi_exp_base_form BaseForm>
 
  507 r1cs_ppzksnark_proof<ppT> r1cs_ppzksnark_prover(
 
  508     const r1cs_ppzksnark_proving_key<ppT> &pk,
 
  509     const r1cs_ppzksnark_primary_input<ppT> &primary_input,
 
  510     const r1cs_ppzksnark_auxiliary_input<ppT> &auxiliary_input)
 
  512     libff::enter_block("Call to r1cs_ppzksnark_prover");
 
  515     assert(pk.constraint_system.is_satisfied(primary_input, auxiliary_input));
 
  518     const libff::Fr<ppT> d1 = libff::Fr<ppT>::random_element(),
 
  519                          d2 = libff::Fr<ppT>::random_element(),
 
  520                          d3 = libff::Fr<ppT>::random_element();
 
  522     libff::enter_block("Compute the polynomial H");
 
  523     const qap_witness<libff::Fr<ppT>> qap_wit = r1cs_to_qap_witness_map(
 
  524         pk.constraint_system, primary_input, auxiliary_input, d1, d2, d3);
 
  525     libff::leave_block("Compute the polynomial H");
 
  528     const libff::Fr<ppT> t = libff::Fr<ppT>::random_element();
 
  529     qap_instance_evaluation<libff::Fr<ppT>> qap_inst =
 
  530         r1cs_to_qap_instance_map_with_evaluation(pk.constraint_system, t);
 
  531     assert(qap_inst.is_satisfied(qap_wit));
 
  534     knowledge_commitment<libff::G1<ppT>, libff::G1<ppT>> g_A =
 
  535         pk.A_query[0] + qap_wit.d1 * pk.A_query[qap_wit.num_variables() + 1];
 
  536     knowledge_commitment<libff::G2<ppT>, libff::G1<ppT>> g_B =
 
  537         pk.B_query[0] + qap_wit.d2 * pk.B_query[qap_wit.num_variables() + 1];
 
  538     knowledge_commitment<libff::G1<ppT>, libff::G1<ppT>> g_C =
 
  539         pk.C_query[0] + qap_wit.d3 * pk.C_query[qap_wit.num_variables() + 1];
 
  541     libff::G1<ppT> g_H = libff::G1<ppT>::zero();
 
  543         (pk.K_query[0] + qap_wit.d1 * pk.K_query[qap_wit.num_variables() + 1] +
 
  544          qap_wit.d2 * pk.K_query[qap_wit.num_variables() + 2] +
 
  545          qap_wit.d3 * pk.K_query[qap_wit.num_variables() + 3]);
 
  548     for (size_t i = 0; i < qap_wit.num_inputs() + 1; ++i) {
 
  549         assert(pk.A_query[i].g == libff::G1<ppT>::zero());
 
  551     assert(pk.A_query.domain_size() == qap_wit.num_variables() + 2);
 
  552     assert(pk.B_query.domain_size() == qap_wit.num_variables() + 2);
 
  553     assert(pk.C_query.domain_size() == qap_wit.num_variables() + 2);
 
  554     assert(pk.H_query.size() == qap_wit.degree() + 1);
 
  555     assert(pk.K_query.size() == qap_wit.num_variables() + 4);
 
  559     const size_t chunks =
 
  560         omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or
 
  561                                // call omp_set_num_threads()
 
  563     const size_t chunks = 1;
 
  566     libff::enter_block("Compute the proof");
 
  568     libff::enter_block("Compute answer to A-query", false);
 
  570           kc_multi_exp_with_mixed_addition<
 
  578               1 + qap_wit.num_variables(),
 
  579               qap_wit.coefficients_for_ABCs.begin(),
 
  580               qap_wit.coefficients_for_ABCs.begin() + qap_wit.num_variables(),
 
  582     libff::leave_block("Compute answer to A-query", false);
 
  584     libff::enter_block("Compute answer to B-query", false);
 
  586           kc_multi_exp_with_mixed_addition<
 
  594               1 + qap_wit.num_variables(),
 
  595               qap_wit.coefficients_for_ABCs.begin(),
 
  596               qap_wit.coefficients_for_ABCs.begin() + qap_wit.num_variables(),
 
  598     libff::leave_block("Compute answer to B-query", false);
 
  600     libff::enter_block("Compute answer to C-query", false);
 
  602           kc_multi_exp_with_mixed_addition<
 
  610               1 + qap_wit.num_variables(),
 
  611               qap_wit.coefficients_for_ABCs.begin(),
 
  612               qap_wit.coefficients_for_ABCs.begin() + qap_wit.num_variables(),
 
  614     libff::leave_block("Compute answer to C-query", false);
 
  616     libff::enter_block("Compute answer to H-query", false);
 
  618           libff::multi_exp<libff::G1<ppT>, libff::Fr<ppT>, Method, BaseForm>(
 
  620               pk.H_query.begin() + qap_wit.degree() + 1,
 
  621               qap_wit.coefficients_for_H.begin(),
 
  622               qap_wit.coefficients_for_H.begin() + qap_wit.degree() + 1,
 
  624     libff::leave_block("Compute answer to H-query", false);
 
  626     libff::enter_block("Compute answer to K-query", false);
 
  628           libff::multi_exp_filter_one_zero<
 
  633               pk.K_query.begin() + 1,
 
  634               pk.K_query.begin() + 1 + qap_wit.num_variables(),
 
  635               qap_wit.coefficients_for_ABCs.begin(),
 
  636               qap_wit.coefficients_for_ABCs.begin() + qap_wit.num_variables(),
 
  638     libff::leave_block("Compute answer to K-query", false);
 
  640     libff::leave_block("Compute the proof");
 
  642     libff::leave_block("Call to r1cs_ppzksnark_prover");
 
  644     r1cs_ppzksnark_proof<ppT> proof = r1cs_ppzksnark_proof<ppT>(
 
  655 template<typename ppT>
 
  656 r1cs_ppzksnark_processed_verification_key<ppT> r1cs_ppzksnark_verifier_process_vk(
 
  657     const r1cs_ppzksnark_verification_key<ppT> &vk)
 
  659     libff::enter_block("Call to r1cs_ppzksnark_verifier_process_vk");
 
  661     r1cs_ppzksnark_processed_verification_key<ppT> pvk;
 
  662     pvk.pp_G2_one_precomp = ppT::precompute_G2(libff::G2<ppT>::one());
 
  663     pvk.vk_alphaA_g2_precomp = ppT::precompute_G2(vk.alphaA_g2);
 
  664     pvk.vk_alphaB_g1_precomp = ppT::precompute_G1(vk.alphaB_g1);
 
  665     pvk.vk_alphaC_g2_precomp = ppT::precompute_G2(vk.alphaC_g2);
 
  666     pvk.vk_rC_Z_g2_precomp = ppT::precompute_G2(vk.rC_Z_g2);
 
  667     pvk.vk_gamma_g2_precomp = ppT::precompute_G2(vk.gamma_g2);
 
  668     pvk.vk_gamma_beta_g1_precomp = ppT::precompute_G1(vk.gamma_beta_g1);
 
  669     pvk.vk_gamma_beta_g2_precomp = ppT::precompute_G2(vk.gamma_beta_g2);
 
  671     pvk.encoded_IC_query = vk.encoded_IC_query;
 
  673     libff::leave_block("Call to r1cs_ppzksnark_verifier_process_vk");
 
  678 template<typename ppT>
 
  679 bool r1cs_ppzksnark_online_verifier_weak_IC(
 
  680     const r1cs_ppzksnark_processed_verification_key<ppT> &pvk,
 
  681     const r1cs_ppzksnark_primary_input<ppT> &primary_input,
 
  682     const r1cs_ppzksnark_proof<ppT> &proof)
 
  684     libff::enter_block("Call to r1cs_ppzksnark_online_verifier_weak_IC");
 
  685     assert(pvk.encoded_IC_query.domain_size() >= primary_input.size());
 
  687     libff::enter_block("Compute input-dependent part of A");
 
  688     const accumulation_vector<libff::G1<ppT>> accumulated_IC =
 
  689         pvk.encoded_IC_query.template accumulate_chunk<libff::Fr<ppT>>(
 
  690             primary_input.begin(), primary_input.end(), 0);
 
  691     const libff::G1<ppT> &acc = accumulated_IC.first;
 
  692     libff::leave_block("Compute input-dependent part of A");
 
  696     libff::enter_block("Check if the proof is well-formed");
 
  697     if (!proof.is_well_formed()) {
 
  698         if (!libff::inhibit_profiling_info) {
 
  699             libff::print_indent();
 
  700             printf("At least one of the proof elements does not lie on the "
 
  705     libff::leave_block("Check if the proof is well-formed");
 
  707     libff::enter_block("Online pairing computations");
 
  708     libff::enter_block("Check knowledge commitment for A is valid");
 
  709     libff::G1_precomp<ppT> proof_g_A_g_precomp =
 
  710         ppT::precompute_G1(proof.g_A.g);
 
  711     libff::G1_precomp<ppT> proof_g_A_h_precomp =
 
  712         ppT::precompute_G1(proof.g_A.h);
 
  713     libff::Fqk<ppT> kc_A_1 =
 
  714         ppT::miller_loop(proof_g_A_g_precomp, pvk.vk_alphaA_g2_precomp);
 
  715     libff::Fqk<ppT> kc_A_2 =
 
  716         ppT::miller_loop(proof_g_A_h_precomp, pvk.pp_G2_one_precomp);
 
  717     libff::GT<ppT> kc_A =
 
  718         ppT::final_exponentiation(kc_A_1 * kc_A_2.unitary_inverse());
 
  719     if (kc_A != libff::GT<ppT>::one()) {
 
  720         if (!libff::inhibit_profiling_info) {
 
  721             libff::print_indent();
 
  722             printf("Knowledge commitment for A query incorrect.\n");
 
  726     libff::leave_block("Check knowledge commitment for A is valid");
 
  728     libff::enter_block("Check knowledge commitment for B is valid");
 
  729     libff::G2_precomp<ppT> proof_g_B_g_precomp =
 
  730         ppT::precompute_G2(proof.g_B.g);
 
  731     libff::G1_precomp<ppT> proof_g_B_h_precomp =
 
  732         ppT::precompute_G1(proof.g_B.h);
 
  733     libff::Fqk<ppT> kc_B_1 =
 
  734         ppT::miller_loop(pvk.vk_alphaB_g1_precomp, proof_g_B_g_precomp);
 
  735     libff::Fqk<ppT> kc_B_2 =
 
  736         ppT::miller_loop(proof_g_B_h_precomp, pvk.pp_G2_one_precomp);
 
  737     libff::GT<ppT> kc_B =
 
  738         ppT::final_exponentiation(kc_B_1 * kc_B_2.unitary_inverse());
 
  739     if (kc_B != libff::GT<ppT>::one()) {
 
  740         if (!libff::inhibit_profiling_info) {
 
  741             libff::print_indent();
 
  742             printf("Knowledge commitment for B query incorrect.\n");
 
  746     libff::leave_block("Check knowledge commitment for B is valid");
 
  748     libff::enter_block("Check knowledge commitment for C is valid");
 
  749     libff::G1_precomp<ppT> proof_g_C_g_precomp =
 
  750         ppT::precompute_G1(proof.g_C.g);
 
  751     libff::G1_precomp<ppT> proof_g_C_h_precomp =
 
  752         ppT::precompute_G1(proof.g_C.h);
 
  753     libff::Fqk<ppT> kc_C_1 =
 
  754         ppT::miller_loop(proof_g_C_g_precomp, pvk.vk_alphaC_g2_precomp);
 
  755     libff::Fqk<ppT> kc_C_2 =
 
  756         ppT::miller_loop(proof_g_C_h_precomp, pvk.pp_G2_one_precomp);
 
  757     libff::GT<ppT> kc_C =
 
  758         ppT::final_exponentiation(kc_C_1 * kc_C_2.unitary_inverse());
 
  759     if (kc_C != libff::GT<ppT>::one()) {
 
  760         if (!libff::inhibit_profiling_info) {
 
  761             libff::print_indent();
 
  762             printf("Knowledge commitment for C query incorrect.\n");
 
  766     libff::leave_block("Check knowledge commitment for C is valid");
 
  768     libff::enter_block("Check QAP divisibility");
 
  769     // check that g^((A+acc)*B)=g^(H*\Prod(t-\sigma)+C)
 
  770     // equivalently, via pairings, that e(g^(A+acc), g^B) = e(g^H, g^Z) + e(g^C,
 
  772     libff::G1_precomp<ppT> proof_g_A_g_acc_precomp =
 
  773         ppT::precompute_G1(proof.g_A.g + acc);
 
  774     libff::G1_precomp<ppT> proof_g_H_precomp = ppT::precompute_G1(proof.g_H);
 
  775     libff::Fqk<ppT> QAP_1 =
 
  776         ppT::miller_loop(proof_g_A_g_acc_precomp, proof_g_B_g_precomp);
 
  777     libff::Fqk<ppT> QAP_23 = ppT::double_miller_loop(
 
  779         pvk.vk_rC_Z_g2_precomp,
 
  781         pvk.pp_G2_one_precomp);
 
  783         ppT::final_exponentiation(QAP_1 * QAP_23.unitary_inverse());
 
  784     if (QAP != libff::GT<ppT>::one()) {
 
  785         if (!libff::inhibit_profiling_info) {
 
  786             libff::print_indent();
 
  787             printf("QAP divisibility check failed.\n");
 
  791     libff::leave_block("Check QAP divisibility");
 
  793     libff::enter_block("Check same coefficients were used");
 
  794     libff::G1_precomp<ppT> proof_g_K_precomp = ppT::precompute_G1(proof.g_K);
 
  795     libff::G1_precomp<ppT> proof_g_A_g_acc_C_precomp =
 
  796         ppT::precompute_G1((proof.g_A.g + acc) + proof.g_C.g);
 
  797     libff::Fqk<ppT> K_1 =
 
  798         ppT::miller_loop(proof_g_K_precomp, pvk.vk_gamma_g2_precomp);
 
  799     libff::Fqk<ppT> K_23 = ppT::double_miller_loop(
 
  800         proof_g_A_g_acc_C_precomp,
 
  801         pvk.vk_gamma_beta_g2_precomp,
 
  802         pvk.vk_gamma_beta_g1_precomp,
 
  803         proof_g_B_g_precomp);
 
  804     libff::GT<ppT> K = ppT::final_exponentiation(K_1 * K_23.unitary_inverse());
 
  805     if (K != libff::GT<ppT>::one()) {
 
  806         if (!libff::inhibit_profiling_info) {
 
  807             libff::print_indent();
 
  808             printf("Same-coefficient check failed.\n");
 
  812     libff::leave_block("Check same coefficients were used");
 
  813     libff::leave_block("Online pairing computations");
 
  814     libff::leave_block("Call to r1cs_ppzksnark_online_verifier_weak_IC");
 
  819 template<typename ppT>
 
  820 bool r1cs_ppzksnark_verifier_weak_IC(
 
  821     const r1cs_ppzksnark_verification_key<ppT> &vk,
 
  822     const r1cs_ppzksnark_primary_input<ppT> &primary_input,
 
  823     const r1cs_ppzksnark_proof<ppT> &proof)
 
  825     libff::enter_block("Call to r1cs_ppzksnark_verifier_weak_IC");
 
  826     r1cs_ppzksnark_processed_verification_key<ppT> pvk =
 
  827         r1cs_ppzksnark_verifier_process_vk<ppT>(vk);
 
  829         r1cs_ppzksnark_online_verifier_weak_IC<ppT>(pvk, primary_input, proof);
 
  830     libff::leave_block("Call to r1cs_ppzksnark_verifier_weak_IC");
 
  834 template<typename ppT>
 
  835 bool r1cs_ppzksnark_online_verifier_strong_IC(
 
  836     const r1cs_ppzksnark_processed_verification_key<ppT> &pvk,
 
  837     const r1cs_ppzksnark_primary_input<ppT> &primary_input,
 
  838     const r1cs_ppzksnark_proof<ppT> &proof)
 
  841     libff::enter_block("Call to r1cs_ppzksnark_online_verifier_strong_IC");
 
  843     if (pvk.encoded_IC_query.domain_size() != primary_input.size()) {
 
  844         libff::print_indent();
 
  846             "Input length differs from expected (got %zu, expected %zu).\n",
 
  847             primary_input.size(),
 
  848             pvk.encoded_IC_query.domain_size());
 
  852             r1cs_ppzksnark_online_verifier_weak_IC(pvk, primary_input, proof);
 
  855     libff::leave_block("Call to r1cs_ppzksnark_online_verifier_strong_IC");
 
  859 template<typename ppT>
 
  860 bool r1cs_ppzksnark_verifier_strong_IC(
 
  861     const r1cs_ppzksnark_verification_key<ppT> &vk,
 
  862     const r1cs_ppzksnark_primary_input<ppT> &primary_input,
 
  863     const r1cs_ppzksnark_proof<ppT> &proof)
 
  865     libff::enter_block("Call to r1cs_ppzksnark_verifier_strong_IC");
 
  866     r1cs_ppzksnark_processed_verification_key<ppT> pvk =
 
  867         r1cs_ppzksnark_verifier_process_vk<ppT>(vk);
 
  868     bool result = r1cs_ppzksnark_online_verifier_strong_IC<ppT>(
 
  869         pvk, primary_input, proof);
 
  870     libff::leave_block("Call to r1cs_ppzksnark_verifier_strong_IC");
 
  874 template<typename ppT>
 
  875 bool r1cs_ppzksnark_affine_verifier_weak_IC(
 
  876     const r1cs_ppzksnark_verification_key<ppT> &vk,
 
  877     const r1cs_ppzksnark_primary_input<ppT> &primary_input,
 
  878     const r1cs_ppzksnark_proof<ppT> &proof)
 
  880     libff::enter_block("Call to r1cs_ppzksnark_affine_verifier_weak_IC");
 
  881     assert(vk.encoded_IC_query.domain_size() >= primary_input.size());
 
  883     libff::affine_ate_G2_precomp<ppT> pvk_pp_G2_one_precomp =
 
  884         ppT::affine_ate_precompute_G2(libff::G2<ppT>::one());
 
  885     libff::affine_ate_G2_precomp<ppT> pvk_vk_alphaA_g2_precomp =
 
  886         ppT::affine_ate_precompute_G2(vk.alphaA_g2);
 
  887     libff::affine_ate_G1_precomp<ppT> pvk_vk_alphaB_g1_precomp =
 
  888         ppT::affine_ate_precompute_G1(vk.alphaB_g1);
 
  889     libff::affine_ate_G2_precomp<ppT> pvk_vk_alphaC_g2_precomp =
 
  890         ppT::affine_ate_precompute_G2(vk.alphaC_g2);
 
  891     libff::affine_ate_G2_precomp<ppT> pvk_vk_rC_Z_g2_precomp =
 
  892         ppT::affine_ate_precompute_G2(vk.rC_Z_g2);
 
  893     libff::affine_ate_G2_precomp<ppT> pvk_vk_gamma_g2_precomp =
 
  894         ppT::affine_ate_precompute_G2(vk.gamma_g2);
 
  895     libff::affine_ate_G1_precomp<ppT> pvk_vk_gamma_beta_g1_precomp =
 
  896         ppT::affine_ate_precompute_G1(vk.gamma_beta_g1);
 
  897     libff::affine_ate_G2_precomp<ppT> pvk_vk_gamma_beta_g2_precomp =
 
  898         ppT::affine_ate_precompute_G2(vk.gamma_beta_g2);
 
  900     libff::enter_block("Compute input-dependent part of A");
 
  901     const accumulation_vector<libff::G1<ppT>> accumulated_IC =
 
  902         vk.encoded_IC_query.template accumulate_chunk<libff::Fr<ppT>>(
 
  903             primary_input.begin(), primary_input.end(), 0);
 
  904     assert(accumulated_IC.is_fully_accumulated());
 
  905     const libff::G1<ppT> &acc = accumulated_IC.first;
 
  906     libff::leave_block("Compute input-dependent part of A");
 
  909     libff::enter_block("Check knowledge commitment for A is valid");
 
  910     libff::affine_ate_G1_precomp<ppT> proof_g_A_g_precomp =
 
  911         ppT::affine_ate_precompute_G1(proof.g_A.g);
 
  912     libff::affine_ate_G1_precomp<ppT> proof_g_A_h_precomp =
 
  913         ppT::affine_ate_precompute_G1(proof.g_A.h);
 
  914     libff::Fqk<ppT> kc_A_miller = ppT::affine_ate_e_over_e_miller_loop(
 
  916         pvk_vk_alphaA_g2_precomp,
 
  918         pvk_pp_G2_one_precomp);
 
  919     libff::GT<ppT> kc_A = ppT::final_exponentiation(kc_A_miller);
 
  921     if (kc_A != libff::GT<ppT>::one()) {
 
  922         libff::print_indent();
 
  923         printf("Knowledge commitment for A query incorrect.\n");
 
  926     libff::leave_block("Check knowledge commitment for A is valid");
 
  928     libff::enter_block("Check knowledge commitment for B is valid");
 
  929     libff::affine_ate_G2_precomp<ppT> proof_g_B_g_precomp =
 
  930         ppT::affine_ate_precompute_G2(proof.g_B.g);
 
  931     libff::affine_ate_G1_precomp<ppT> proof_g_B_h_precomp =
 
  932         ppT::affine_ate_precompute_G1(proof.g_B.h);
 
  933     libff::Fqk<ppT> kc_B_miller = ppT::affine_ate_e_over_e_miller_loop(
 
  934         pvk_vk_alphaB_g1_precomp,
 
  937         pvk_pp_G2_one_precomp);
 
  938     libff::GT<ppT> kc_B = ppT::final_exponentiation(kc_B_miller);
 
  939     if (kc_B != libff::GT<ppT>::one()) {
 
  940         libff::print_indent();
 
  941         printf("Knowledge commitment for B query incorrect.\n");
 
  944     libff::leave_block("Check knowledge commitment for B is valid");
 
  946     libff::enter_block("Check knowledge commitment for C is valid");
 
  947     libff::affine_ate_G1_precomp<ppT> proof_g_C_g_precomp =
 
  948         ppT::affine_ate_precompute_G1(proof.g_C.g);
 
  949     libff::affine_ate_G1_precomp<ppT> proof_g_C_h_precomp =
 
  950         ppT::affine_ate_precompute_G1(proof.g_C.h);
 
  951     libff::Fqk<ppT> kc_C_miller = ppT::affine_ate_e_over_e_miller_loop(
 
  953         pvk_vk_alphaC_g2_precomp,
 
  955         pvk_pp_G2_one_precomp);
 
  956     libff::GT<ppT> kc_C = ppT::final_exponentiation(kc_C_miller);
 
  957     if (kc_C != libff::GT<ppT>::one()) {
 
  958         libff::print_indent();
 
  959         printf("Knowledge commitment for C query incorrect.\n");
 
  962     libff::leave_block("Check knowledge commitment for C is valid");
 
  964     libff::enter_block("Check QAP divisibility");
 
  965     libff::affine_ate_G1_precomp<ppT> proof_g_A_g_acc_precomp =
 
  966         ppT::affine_ate_precompute_G1(proof.g_A.g + acc);
 
  967     libff::affine_ate_G1_precomp<ppT> proof_g_H_precomp =
 
  968         ppT::affine_ate_precompute_G1(proof.g_H);
 
  969     libff::Fqk<ppT> QAP_miller = ppT::affine_ate_e_times_e_over_e_miller_loop(
 
  971         pvk_vk_rC_Z_g2_precomp,
 
  973         pvk_pp_G2_one_precomp,
 
  974         proof_g_A_g_acc_precomp,
 
  975         proof_g_B_g_precomp);
 
  976     libff::GT<ppT> QAP = ppT::final_exponentiation(QAP_miller);
 
  977     if (QAP != libff::GT<ppT>::one()) {
 
  978         libff::print_indent();
 
  979         printf("QAP divisibility check failed.\n");
 
  982     libff::leave_block("Check QAP divisibility");
 
  984     libff::enter_block("Check same coefficients were used");
 
  985     libff::affine_ate_G1_precomp<ppT> proof_g_K_precomp =
 
  986         ppT::affine_ate_precompute_G1(proof.g_K);
 
  987     libff::affine_ate_G1_precomp<ppT> proof_g_A_g_acc_C_precomp =
 
  988         ppT::affine_ate_precompute_G1((proof.g_A.g + acc) + proof.g_C.g);
 
  989     libff::Fqk<ppT> K_miller = ppT::affine_ate_e_times_e_over_e_miller_loop(
 
  990         proof_g_A_g_acc_C_precomp,
 
  991         pvk_vk_gamma_beta_g2_precomp,
 
  992         pvk_vk_gamma_beta_g1_precomp,
 
  995         pvk_vk_gamma_g2_precomp);
 
  996     libff::GT<ppT> K = ppT::final_exponentiation(K_miller);
 
  997     if (K != libff::GT<ppT>::one()) {
 
  998         libff::print_indent();
 
  999         printf("Same-coefficient check failed.\n");
 
 1002     libff::leave_block("Check same coefficients were used");
 
 1004     libff::leave_block("Call to r1cs_ppzksnark_affine_verifier_weak_IC");
 
 1009 } // namespace libsnark
 
 1010 #endif // R1CS_PPZKSNARK_TCC_