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_