2  *****************************************************************************
 
    4  Implementation of functionality for creating and using the two PCD circuits in
 
    5  a single-predicate PCD construction.
 
    7  See sp_pcd_circuits.hpp .
 
    9  *****************************************************************************
 
   10  * @author     This file is part of libsnark, developed by SCIPR Lab
 
   11  *             and contributors (see AUTHORS).
 
   12  * @copyright  MIT license (see LICENSE file)
 
   13  *****************************************************************************/
 
   15 #ifndef SP_PCD_CIRCUITS_TCC_
 
   16 #define SP_PCD_CIRCUITS_TCC_
 
   18 #include <libff/common/utils.hpp>
 
   19 #include <libsnark/gadgetlib1/constraint_profiling.hpp>
 
   24 template<typename ppT>
 
   25 sp_compliance_step_pcd_circuit_maker<ppT>::sp_compliance_step_pcd_circuit_maker(
 
   26     const r1cs_pcd_compliance_predicate<FieldT> &compliance_predicate)
 
   27     : compliance_predicate(compliance_predicate)
 
   29     /* calculate some useful sizes */
 
   30     assert(compliance_predicate.is_well_formed());
 
   31     assert(compliance_predicate.has_equal_input_and_output_lengths());
 
   33     const size_t compliance_predicate_arity = compliance_predicate.max_arity;
 
   34     const size_t digest_size =
 
   35         CRH_with_field_out_gadget<FieldT>::get_digest_len();
 
   36     const size_t msg_size_in_bits =
 
   38         (1 + compliance_predicate.outgoing_message_payload_length);
 
   39     const size_t sp_translation_step_vk_size_in_bits =
 
   40         r1cs_ppzksnark_verification_key_variable<ppT>::size_in_bits(
 
   41             sp_translation_step_pcd_circuit_maker<
 
   42                 other_curve<ppT>>::input_size_in_elts());
 
   43     const size_t padded_verifier_input_size =
 
   44         sp_translation_step_pcd_circuit_maker<
 
   45             other_curve<ppT>>::input_capacity_in_bits();
 
   48         "other curve input size = %zu\n",
 
   49         sp_translation_step_pcd_circuit_maker<
 
   50             other_curve<ppT>>::input_size_in_elts());
 
   51     printf("translation_vk_bits = %zu\n", sp_translation_step_vk_size_in_bits);
 
   52     printf("padded verifier input size = %zu\n", padded_verifier_input_size);
 
   54     const size_t block_size =
 
   55         msg_size_in_bits + sp_translation_step_vk_size_in_bits;
 
   56     CRH_with_bit_out_gadget<FieldT>::sample_randomness(block_size);
 
   58     /* allocate input of the compliance PCD circuit */
 
   59     sp_compliance_step_pcd_circuit_input.allocate(
 
   60         pb, input_size_in_elts(), "sp_compliance_step_pcd_circuit_input");
 
   62     /* allocate inputs to the compliance predicate */
 
   63     outgoing_message_type.allocate(pb, "outgoing_message_type");
 
   64     outgoing_message_payload.allocate(
 
   66         compliance_predicate.outgoing_message_payload_length,
 
   67         "outgoing_message_payload");
 
   69     outgoing_message_vars.insert(
 
   70         outgoing_message_vars.end(), outgoing_message_type);
 
   71     outgoing_message_vars.insert(
 
   72         outgoing_message_vars.end(),
 
   73         outgoing_message_payload.begin(),
 
   74         outgoing_message_payload.end());
 
   76     arity.allocate(pb, "arity");
 
   78     incoming_message_types.resize(compliance_predicate_arity);
 
   79     incoming_message_payloads.resize(compliance_predicate_arity);
 
   80     incoming_message_vars.resize(compliance_predicate_arity);
 
   81     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
   82         incoming_message_types[i].allocate(
 
   83             pb, FMT("", "incoming_message_type_%zu", i));
 
   84         incoming_message_payloads[i].allocate(
 
   86             compliance_predicate.outgoing_message_payload_length,
 
   87             FMT("", "incoming_message_payloads_%zu", i));
 
   89         incoming_message_vars[i].insert(
 
   90             incoming_message_vars[i].end(), incoming_message_types[i]);
 
   91         incoming_message_vars[i].insert(
 
   92             incoming_message_vars[i].end(),
 
   93             incoming_message_payloads[i].begin(),
 
   94             incoming_message_payloads[i].end());
 
   98         pb, compliance_predicate.local_data_length, "local_data");
 
   99     cp_witness.allocate(pb, compliance_predicate.witness_length, "cp_witness");
 
  101     /* convert compliance predicate from a constraint system into a gadget */
 
  102     pb_variable_array<FieldT> incoming_messages_concat;
 
  103     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  104         incoming_messages_concat.insert(
 
  105             incoming_messages_concat.end(),
 
  106             incoming_message_vars[i].begin(),
 
  107             incoming_message_vars[i].end());
 
  110     compliance_predicate_as_gadget.reset(new gadget_from_r1cs<FieldT>(
 
  112         {outgoing_message_vars,
 
  113          pb_variable_array<FieldT>(1, arity),
 
  114          incoming_messages_concat,
 
  117         compliance_predicate.constraint_system,
 
  118         "compliance_predicate_as_gadget"));
 
  120     /* unpack messages to bits */
 
  121     outgoing_message_bits.allocate(
 
  122         pb, msg_size_in_bits, "outgoing_message_bits");
 
  123     unpack_outgoing_message.reset(new multipacking_gadget<FieldT>(
 
  125         outgoing_message_bits,
 
  126         outgoing_message_vars,
 
  128         "unpack_outgoing_message"));
 
  130     incoming_messages_bits.resize(compliance_predicate_arity);
 
  131     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  132         incoming_messages_bits[i].allocate(
 
  133             pb, msg_size_in_bits, FMT("", "incoming_messages_bits_%zu", i));
 
  134         unpack_incoming_messages.emplace_back(multipacking_gadget<FieldT>(
 
  136             incoming_messages_bits[i],
 
  137             incoming_message_vars[i],
 
  139             FMT("", "unpack_incoming_messages_%zu", i)));
 
  142     /* allocate digests */
 
  143     sp_translation_step_vk_and_incoming_message_payload_digests.resize(
 
  144         compliance_predicate_arity);
 
  145     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  146         sp_translation_step_vk_and_incoming_message_payload_digests[i].allocate(
 
  150                 "sp_translation_step_vk_and_incoming_message_payload_digests_%"
 
  155     /* allocate blocks */
 
  156     sp_translation_step_vk_bits.allocate(
 
  157         pb, sp_translation_step_vk_size_in_bits, "sp_translation_step_vk_bits");
 
  159     block_for_outgoing_message.reset(new block_variable<FieldT>(
 
  161         {sp_translation_step_vk_bits, outgoing_message_bits},
 
  162         "block_for_outgoing_message"));
 
  164     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  165         blocks_for_incoming_messages.emplace_back(block_variable<FieldT>(
 
  167             {sp_translation_step_vk_bits, incoming_messages_bits[i]},
 
  168             FMT("", "blocks_for_incoming_messages_zu", i)));
 
  171     /* allocate hash checkers */
 
  172     hash_outgoing_message.reset(new CRH_with_field_out_gadget<FieldT>(
 
  175         *block_for_outgoing_message,
 
  176         sp_compliance_step_pcd_circuit_input,
 
  177         "hash_outgoing_message"));
 
  179     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  180         hash_incoming_messages.emplace_back(CRH_with_field_out_gadget<FieldT>(
 
  183             blocks_for_incoming_messages[i],
 
  184             sp_translation_step_vk_and_incoming_message_payload_digests[i],
 
  185             FMT("", "hash_incoming_messages_%zu", i)));
 
  188     /* allocate useful zero variable */
 
  189     zero.allocate(pb, "zero");
 
  191     /* prepare arguments for the verifier */
 
  192     sp_translation_step_vk.reset(
 
  193         new r1cs_ppzksnark_verification_key_variable<ppT>(
 
  195             sp_translation_step_vk_bits,
 
  196             sp_translation_step_pcd_circuit_maker<
 
  197                 other_curve<ppT>>::input_size_in_elts(),
 
  198             "sp_translation_step_vk"));
 
  200     verification_result.allocate(pb, "verification_result");
 
  201     sp_translation_step_vk_and_incoming_message_payload_digest_bits.resize(
 
  202         compliance_predicate_arity);
 
  204     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  205         sp_translation_step_vk_and_incoming_message_payload_digest_bits[i]
 
  208                 digest_size * field_logsize(),
 
  210                     "sp_translation_step_vk_and_incoming_message_payload_"
 
  213         unpack_sp_translation_step_vk_and_incoming_message_payload_digests
 
  214             .emplace_back(multipacking_gadget<FieldT>(
 
  216                 sp_translation_step_vk_and_incoming_message_payload_digest_bits
 
  218                 sp_translation_step_vk_and_incoming_message_payload_digests[i],
 
  221                     "unpack_sp_translation_step_vk_and_incoming_message_"
 
  222                     "payload_digests_%zu",
 
  225         verifier_input.emplace_back(
 
  226             sp_translation_step_vk_and_incoming_message_payload_digest_bits[i]);
 
  227         while (verifier_input[i].size() < padded_verifier_input_size) {
 
  228             verifier_input[i].emplace_back(zero);
 
  232             r1cs_ppzksnark_proof_variable<ppT>(pb, FMT("", "proof_%zu", i)));
 
  233         verifiers.emplace_back(r1cs_ppzksnark_verifier_gadget<ppT>(
 
  235             *sp_translation_step_vk,
 
  237             sp_translation_step_pcd_circuit_maker<
 
  238                 other_curve<ppT>>::field_capacity(),
 
  241             FMT("", "verifiers_%zu", i)));
 
  244     pb.set_input_sizes(input_size_in_elts());
 
  245     printf("done compliance\n");
 
  248 template<typename ppT>
 
  249 void sp_compliance_step_pcd_circuit_maker<ppT>::generate_r1cs_constraints()
 
  251     const size_t digest_size =
 
  252         CRH_with_bit_out_gadget<FieldT>::get_digest_len();
 
  253     const size_t dimension = knapsack_dimension<FieldT>::dimension;
 
  254     libff::print_indent();
 
  255     printf("* Knapsack dimension: %zu\n", dimension);
 
  257     const size_t compliance_predicate_arity = compliance_predicate.max_arity;
 
  258     libff::print_indent();
 
  259     printf("* Compliance predicate arity: %zu\n", compliance_predicate_arity);
 
  260     libff::print_indent();
 
  262         "* Compliance predicate payload length: %zu\n",
 
  263         compliance_predicate.outgoing_message_payload_length);
 
  264     libff::print_indent();
 
  266         "* Compliance predicate local data length: %zu\n",
 
  267         compliance_predicate.local_data_length);
 
  268     libff::print_indent();
 
  270         "* Compliance predicate witness length: %zu\n",
 
  271         compliance_predicate.witness_length);
 
  273     PROFILE_CONSTRAINTS(pb, "booleanity")
 
  275         PROFILE_CONSTRAINTS(pb, "booleanity: unpack outgoing_message")
 
  277             unpack_outgoing_message->generate_r1cs_constraints(true);
 
  280         PROFILE_CONSTRAINTS(pb, "booleanity: unpack s incoming_message")
 
  282             for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  283                 unpack_incoming_messages[i].generate_r1cs_constraints(true);
 
  287         PROFILE_CONSTRAINTS(pb, "booleanity: unpack verification key")
 
  289             sp_translation_step_vk->generate_r1cs_constraints(true);
 
  293     PROFILE_CONSTRAINTS(pb, "(1+s) copies of hash")
 
  295         libff::print_indent();
 
  296         printf("* Digest-size: %zu\n", digest_size);
 
  297         hash_outgoing_message->generate_r1cs_constraints();
 
  299         for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  300             hash_incoming_messages[i].generate_r1cs_constraints();
 
  304     PROFILE_CONSTRAINTS(pb, "s copies of repacking circuit")
 
  306         for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  307             unpack_sp_translation_step_vk_and_incoming_message_payload_digests
 
  309                     .generate_r1cs_constraints(true);
 
  313     PROFILE_CONSTRAINTS(pb, "compliance predicate")
 
  315         compliance_predicate_as_gadget->generate_r1cs_constraints();
 
  318     PROFILE_CONSTRAINTS(pb, "s copies of verifier for translated proofs")
 
  320         PROFILE_CONSTRAINTS(pb, "check that s proofs lie on the curve")
 
  322             for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  323                 proof[i].generate_r1cs_constraints();
 
  327         for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  328             verifiers[i].generate_r1cs_constraints();
 
  332     PROFILE_CONSTRAINTS(pb, "miscellaneous")
 
  334         generate_r1cs_equals_const_constraint<FieldT>(
 
  335             pb, zero, FieldT::zero(), "zero");
 
  336         generate_boolean_r1cs_constraint<FieldT>(
 
  337             pb, verification_result, "verification_result");
 
  339         /* type * (1-verification_result) = 0 */
 
  340         pb.add_r1cs_constraint(
 
  341             r1cs_constraint<FieldT>(
 
  342                 incoming_message_types[0], 1 - verification_result, 0),
 
  343             "not_base_case_implies_valid_proofs");
 
  345         /* all types equal */
 
  346         for (size_t i = 1; i < compliance_predicate.max_arity; ++i) {
 
  347             pb.add_r1cs_constraint(
 
  348                 r1cs_constraint<FieldT>(
 
  349                     1, incoming_message_types[0], incoming_message_types[i]),
 
  350                 FMT("", "type_%zu_equal_to_type_0", i));
 
  353         pb.add_r1cs_constraint(
 
  354             r1cs_constraint<FieldT>(1, arity, compliance_predicate_arity),
 
  356         pb.add_r1cs_constraint(
 
  357             r1cs_constraint<FieldT>(
 
  358                 1, outgoing_message_type, FieldT(compliance_predicate.type)),
 
  359             "enforce_outgoing_type");
 
  362     PRINT_CONSTRAINT_PROFILING();
 
  363     libff::print_indent();
 
  365         "* Number of constraints in sp_compliance_step_pcd_circuit: %zu\n",
 
  366         pb.num_constraints());
 
  369 template<typename ppT>
 
  370 r1cs_constraint_system<libff::Fr<ppT>> sp_compliance_step_pcd_circuit_maker<
 
  371     ppT>::get_circuit() const
 
  373     return pb.get_constraint_system();
 
  376 template<typename ppT>
 
  377 r1cs_primary_input<libff::Fr<ppT>> sp_compliance_step_pcd_circuit_maker<
 
  378     ppT>::get_primary_input() const
 
  380     return pb.primary_input();
 
  383 template<typename ppT>
 
  384 r1cs_auxiliary_input<libff::Fr<ppT>> sp_compliance_step_pcd_circuit_maker<
 
  385     ppT>::get_auxiliary_input() const
 
  387     return pb.auxiliary_input();
 
  390 template<typename ppT>
 
  391 void sp_compliance_step_pcd_circuit_maker<ppT>::generate_r1cs_witness(
 
  392     const r1cs_ppzksnark_verification_key<other_curve<ppT>>
 
  393         &sp_translation_step_pcd_circuit_vk,
 
  394     const r1cs_pcd_compliance_predicate_primary_input<FieldT>
 
  395         &compliance_predicate_primary_input,
 
  396     const r1cs_pcd_compliance_predicate_auxiliary_input<FieldT>
 
  397         &compliance_predicate_auxiliary_input,
 
  398     const std::vector<r1cs_ppzksnark_proof<other_curve<ppT>>> &incoming_proofs)
 
  400     const size_t compliance_predicate_arity = compliance_predicate.max_arity;
 
  401     this->pb.clear_values();
 
  402     this->pb.val(zero) = FieldT::zero();
 
  404     compliance_predicate_as_gadget->generate_r1cs_witness(
 
  405         compliance_predicate_primary_input.as_r1cs_primary_input(),
 
  406         compliance_predicate_auxiliary_input.as_r1cs_auxiliary_input(
 
  407             compliance_predicate.incoming_message_payload_lengths));
 
  408     this->pb.val(arity) = FieldT(compliance_predicate_arity);
 
  409     unpack_outgoing_message->generate_r1cs_witness_from_packed();
 
  410     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  411         unpack_incoming_messages[i].generate_r1cs_witness_from_packed();
 
  414     sp_translation_step_vk->generate_r1cs_witness(
 
  415         sp_translation_step_pcd_circuit_vk);
 
  416     hash_outgoing_message->generate_r1cs_witness();
 
  417     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  418         hash_incoming_messages[i].generate_r1cs_witness();
 
  419         unpack_sp_translation_step_vk_and_incoming_message_payload_digests[i]
 
  420             .generate_r1cs_witness_from_packed();
 
  423     for (size_t i = 0; i < compliance_predicate_arity; ++i) {
 
  424         proof[i].generate_r1cs_witness(incoming_proofs[i]);
 
  425         verifiers[i].generate_r1cs_witness();
 
  428     if (this->pb.val(incoming_message_types[0]) != FieldT::zero()) {
 
  429         this->pb.val(verification_result) = FieldT::one();
 
  433     generate_r1cs_constraints(); // force generating constraints
 
  434     assert(this->pb.is_satisfied());
 
  438 template<typename ppT>
 
  439 size_t sp_compliance_step_pcd_circuit_maker<ppT>::field_logsize()
 
  441     return libff::Fr<ppT>::size_in_bits();
 
  444 template<typename ppT>
 
  445 size_t sp_compliance_step_pcd_circuit_maker<ppT>::field_capacity()
 
  447     return libff::Fr<ppT>::capacity();
 
  450 template<typename ppT>
 
  451 size_t sp_compliance_step_pcd_circuit_maker<ppT>::input_size_in_elts()
 
  453     const size_t digest_size =
 
  454         CRH_with_field_out_gadget<FieldT>::get_digest_len();
 
  458 template<typename ppT>
 
  459 size_t sp_compliance_step_pcd_circuit_maker<ppT>::input_capacity_in_bits()
 
  461     return input_size_in_elts() * field_capacity();
 
  464 template<typename ppT>
 
  465 size_t sp_compliance_step_pcd_circuit_maker<ppT>::input_size_in_bits()
 
  467     return input_size_in_elts() * field_logsize();
 
  470 template<typename ppT>
 
  471 sp_translation_step_pcd_circuit_maker<ppT>::
 
  472     sp_translation_step_pcd_circuit_maker(
 
  473         const r1cs_ppzksnark_verification_key<other_curve<ppT>>
 
  474             &sp_compliance_step_vk)
 
  476     /* allocate input of the translation PCD circuit */
 
  477     sp_translation_step_pcd_circuit_input.allocate(
 
  478         pb, input_size_in_elts(), "sp_translation_step_pcd_circuit_input");
 
  480     /* unpack translation step PCD circuit input */
 
  481     unpacked_sp_translation_step_pcd_circuit_input.allocate(
 
  483         sp_compliance_step_pcd_circuit_maker<
 
  484             other_curve<ppT>>::input_size_in_bits(),
 
  485         "unpacked_sp_translation_step_pcd_circuit_input");
 
  486     unpack_sp_translation_step_pcd_circuit_input.reset(
 
  487         new multipacking_gadget<FieldT>(
 
  489             unpacked_sp_translation_step_pcd_circuit_input,
 
  490             sp_translation_step_pcd_circuit_input,
 
  492             "unpack_sp_translation_step_pcd_circuit_input"));
 
  494     /* prepare arguments for the verifier */
 
  495     hardcoded_sp_compliance_step_vk.reset(
 
  496         new r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable<
 
  497             ppT>(pb, sp_compliance_step_vk, "hardcoded_sp_compliance_step_vk"));
 
  498     proof.reset(new r1cs_ppzksnark_proof_variable<ppT>(pb, "proof"));
 
  500     /* verify previous proof */
 
  501     online_verifier.reset(new r1cs_ppzksnark_online_verifier_gadget<ppT>(
 
  503         *hardcoded_sp_compliance_step_vk,
 
  504         unpacked_sp_translation_step_pcd_circuit_input,
 
  505         sp_compliance_step_pcd_circuit_maker<other_curve<ppT>>::field_logsize(),
 
  507         ONE, // must always accept
 
  509     pb.set_input_sizes(input_size_in_elts());
 
  511     printf("done translation\n");
 
  514 template<typename ppT>
 
  515 void sp_translation_step_pcd_circuit_maker<ppT>::generate_r1cs_constraints()
 
  517     PROFILE_CONSTRAINTS(pb, "repacking: unpack circuit input")
 
  519         unpack_sp_translation_step_pcd_circuit_input->generate_r1cs_constraints(
 
  523     PROFILE_CONSTRAINTS(pb, "verifier for compliance proofs")
 
  525         PROFILE_CONSTRAINTS(pb, "check that proof lies on the curve")
 
  527             proof->generate_r1cs_constraints();
 
  530         online_verifier->generate_r1cs_constraints();
 
  533     PRINT_CONSTRAINT_PROFILING();
 
  534     libff::print_indent();
 
  536         "* Number of constraints in sp_translation_step_pcd_circuit: %zu\n",
 
  537         pb.num_constraints());
 
  540 template<typename ppT>
 
  541 r1cs_constraint_system<libff::Fr<ppT>> sp_translation_step_pcd_circuit_maker<
 
  542     ppT>::get_circuit() const
 
  544     return pb.get_constraint_system();
 
  547 template<typename ppT>
 
  548 void sp_translation_step_pcd_circuit_maker<ppT>::generate_r1cs_witness(
 
  549     const r1cs_primary_input<libff::Fr<ppT>> sp_translation_step_input,
 
  550     const r1cs_ppzksnark_proof<other_curve<ppT>> &compliance_step_proof)
 
  552     this->pb.clear_values();
 
  553     sp_translation_step_pcd_circuit_input.fill_with_field_elements(
 
  554         pb, sp_translation_step_input);
 
  555     unpack_sp_translation_step_pcd_circuit_input
 
  556         ->generate_r1cs_witness_from_packed();
 
  558     proof->generate_r1cs_witness(compliance_step_proof);
 
  559     online_verifier->generate_r1cs_witness();
 
  562     generate_r1cs_constraints(); // force generating constraints
 
  564     printf("Input to the translation circuit:\n");
 
  565     for (size_t i = 0; i < this->pb.num_inputs(); ++i) {
 
  566         this->pb.val(pb_variable<FieldT>(i + 1)).print();
 
  569     assert(this->pb.is_satisfied());
 
  573 template<typename ppT>
 
  574 r1cs_primary_input<libff::Fr<ppT>> sp_translation_step_pcd_circuit_maker<
 
  575     ppT>::get_primary_input() const
 
  577     return pb.primary_input();
 
  580 template<typename ppT>
 
  581 r1cs_auxiliary_input<libff::Fr<ppT>> sp_translation_step_pcd_circuit_maker<
 
  582     ppT>::get_auxiliary_input() const
 
  584     return pb.auxiliary_input();
 
  587 template<typename ppT>
 
  588 size_t sp_translation_step_pcd_circuit_maker<ppT>::field_logsize()
 
  590     return libff::Fr<ppT>::size_in_bits();
 
  593 template<typename ppT>
 
  594 size_t sp_translation_step_pcd_circuit_maker<ppT>::field_capacity()
 
  596     return libff::Fr<ppT>::capacity();
 
  599 template<typename ppT>
 
  600 size_t sp_translation_step_pcd_circuit_maker<ppT>::input_size_in_elts()
 
  602     return libff::div_ceil(
 
  603         sp_compliance_step_pcd_circuit_maker<
 
  604             other_curve<ppT>>::input_size_in_bits(),
 
  605         sp_translation_step_pcd_circuit_maker<ppT>::field_capacity());
 
  608 template<typename ppT>
 
  609 size_t sp_translation_step_pcd_circuit_maker<ppT>::input_capacity_in_bits()
 
  611     return input_size_in_elts() * field_capacity();
 
  614 template<typename ppT>
 
  615 size_t sp_translation_step_pcd_circuit_maker<ppT>::input_size_in_bits()
 
  617     return input_size_in_elts() * field_logsize();
 
  620 template<typename ppT>
 
  621 r1cs_primary_input<libff::Fr<ppT>> get_sp_compliance_step_pcd_circuit_input(
 
  622     const libff::bit_vector &sp_translation_step_vk_bits,
 
  623     const r1cs_pcd_compliance_predicate_primary_input<libff::Fr<ppT>>
 
  626     libff::enter_block("Call to get_sp_compliance_step_pcd_circuit_input");
 
  627     typedef libff::Fr<ppT> FieldT;
 
  629     const r1cs_variable_assignment<FieldT> outgoing_message_as_va =
 
  630         primary_input.outgoing_message->as_r1cs_variable_assignment();
 
  631     libff::bit_vector msg_bits;
 
  632     for (const FieldT &elt : outgoing_message_as_va) {
 
  633         const libff::bit_vector elt_bits =
 
  634             libff::convert_field_element_to_bit_vector(elt);
 
  635         msg_bits.insert(msg_bits.end(), elt_bits.begin(), elt_bits.end());
 
  638     libff::bit_vector block;
 
  641         sp_translation_step_vk_bits.begin(),
 
  642         sp_translation_step_vk_bits.end());
 
  643     block.insert(block.end(), msg_bits.begin(), msg_bits.end());
 
  645     libff::enter_block("Sample CRH randomness");
 
  646     CRH_with_field_out_gadget<FieldT>::sample_randomness(block.size());
 
  647     libff::leave_block("Sample CRH randomness");
 
  649     const std::vector<FieldT> digest =
 
  650         CRH_with_field_out_gadget<FieldT>::get_hash(block);
 
  651     libff::leave_block("Call to get_sp_compliance_step_pcd_circuit_input");
 
  656 template<typename ppT>
 
  657 r1cs_primary_input<libff::Fr<ppT>> get_sp_translation_step_pcd_circuit_input(
 
  658     const libff::bit_vector &sp_translation_step_vk_bits,
 
  659     const r1cs_pcd_compliance_predicate_primary_input<
 
  660         libff::Fr<other_curve<ppT>>> &primary_input)
 
  662     libff::enter_block("Call to get_sp_translation_step_pcd_circuit_input");
 
  663     typedef libff::Fr<ppT> FieldT;
 
  665     const std::vector<libff::Fr<other_curve<ppT>>>
 
  666         sp_compliance_step_pcd_circuit_input =
 
  667             get_sp_compliance_step_pcd_circuit_input<other_curve<ppT>>(
 
  668                 sp_translation_step_vk_bits, primary_input);
 
  669     libff::bit_vector sp_compliance_step_pcd_circuit_input_bits;
 
  670     for (const libff::Fr<other_curve<ppT>> &elt :
 
  671          sp_compliance_step_pcd_circuit_input) {
 
  672         const libff::bit_vector elt_bits =
 
  673             libff::convert_field_element_to_bit_vector<
 
  674                 libff::Fr<other_curve<ppT>>>(elt);
 
  675         sp_compliance_step_pcd_circuit_input_bits.insert(
 
  676             sp_compliance_step_pcd_circuit_input_bits.end(),
 
  681     sp_compliance_step_pcd_circuit_input_bits.resize(
 
  682         sp_translation_step_pcd_circuit_maker<ppT>::input_capacity_in_bits(),
 
  685     const r1cs_primary_input<FieldT> result =
 
  686         libff::pack_bit_vector_into_field_element_vector<FieldT>(
 
  687             sp_compliance_step_pcd_circuit_input_bits,
 
  688             sp_translation_step_pcd_circuit_maker<ppT>::field_capacity());
 
  689     libff::leave_block("Call to get_sp_translation_step_pcd_circuit_input");
 
  694 } // namespace libsnark
 
  696 #endif // SP_PCD_CIRCUITS_TCC_