2 *****************************************************************************
4 Implementation of functionality for creating and using the two PCD circuits in
5 a multi-predicate PCD construction.
7 See mp_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 MP_PCD_CIRCUITS_TCC_
16 #define MP_PCD_CIRCUITS_TCC_
19 #include <libff/common/utils.hpp>
20 #include <libsnark/gadgetlib1/constraint_profiling.hpp>
25 template<typename ppT>
26 mp_compliance_step_pcd_circuit_maker<ppT>::mp_compliance_step_pcd_circuit_maker(
27 const r1cs_pcd_compliance_predicate<FieldT> &compliance_predicate,
28 const size_t max_number_of_predicates)
29 : compliance_predicate(compliance_predicate)
31 /* calculate some useful sizes */
32 const size_t digest_size =
33 CRH_with_field_out_gadget<FieldT>::get_digest_len();
34 const size_t outgoing_msg_size_in_bits =
36 (1 + compliance_predicate.outgoing_message_payload_length);
37 assert(compliance_predicate.has_equal_input_lengths());
38 const size_t translation_step_vk_size_in_bits =
39 r1cs_ppzksnark_verification_key_variable<ppT>::size_in_bits(
40 mp_translation_step_pcd_circuit_maker<
41 other_curve<ppT>>::input_size_in_elts());
42 const size_t padded_verifier_input_size =
43 mp_translation_step_pcd_circuit_maker<
44 other_curve<ppT>>::input_capacity_in_bits();
45 const size_t commitment_size =
46 set_commitment_gadget<FieldT, CRH_with_bit_out_gadget<FieldT>>::
49 const size_t output_block_size =
50 commitment_size + outgoing_msg_size_in_bits;
51 const size_t max_incoming_payload_length = *std::max_element(
52 compliance_predicate.incoming_message_payload_lengths.begin(),
53 compliance_predicate.incoming_message_payload_lengths.end());
54 const size_t max_input_block_size =
55 commitment_size + field_logsize() * (1 + max_incoming_payload_length);
57 CRH_with_bit_out_gadget<FieldT>::sample_randomness(
58 std::max(output_block_size, max_input_block_size));
60 /* allocate input of the compliance MP_PCD circuit */
61 mp_compliance_step_pcd_circuit_input.allocate(
62 pb, input_size_in_elts(), "mp_compliance_step_pcd_circuit_input");
64 /* allocate inputs to the compliance predicate */
65 outgoing_message_type.allocate(pb, "outgoing_message_type");
66 outgoing_message_payload.allocate(
68 compliance_predicate.outgoing_message_payload_length,
69 "outgoing_message_payload");
71 outgoing_message_vars.insert(
72 outgoing_message_vars.end(), outgoing_message_type);
73 outgoing_message_vars.insert(
74 outgoing_message_vars.end(),
75 outgoing_message_payload.begin(),
76 outgoing_message_payload.end());
78 arity.allocate(pb, "arity");
80 incoming_message_types.resize(compliance_predicate.max_arity);
81 incoming_message_payloads.resize(compliance_predicate.max_arity);
82 incoming_message_vars.resize(compliance_predicate.max_arity);
83 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
84 incoming_message_types[i].allocate(
85 pb, FMT("", "incoming_message_type_%zu", i));
86 incoming_message_payloads[i].allocate(
88 compliance_predicate.incoming_message_payload_lengths[i],
89 FMT("", "incoming_message_payloads_%zu", i));
91 incoming_message_vars[i].insert(
92 incoming_message_vars[i].end(), incoming_message_types[i]);
93 incoming_message_vars[i].insert(
94 incoming_message_vars[i].end(),
95 incoming_message_payloads[i].begin(),
96 incoming_message_payloads[i].end());
100 pb, compliance_predicate.local_data_length, "local_data");
101 cp_witness.allocate(pb, compliance_predicate.witness_length, "cp_witness");
103 /* convert compliance predicate from a constraint system into a gadget */
104 pb_variable_array<FieldT> incoming_messages_concat;
105 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
106 incoming_messages_concat.insert(
107 incoming_messages_concat.end(),
108 incoming_message_vars[i].begin(),
109 incoming_message_vars[i].end());
112 compliance_predicate_as_gadget.reset(new gadget_from_r1cs<FieldT>(
114 {outgoing_message_vars,
115 pb_variable_array<FieldT>(1, arity),
116 incoming_messages_concat,
119 compliance_predicate.constraint_system,
120 "compliance_predicate_as_gadget"));
122 /* unpack messages to bits */
123 outgoing_message_bits.allocate(
124 pb, outgoing_msg_size_in_bits, "outgoing_message_bits");
125 unpack_outgoing_message.reset(new multipacking_gadget<FieldT>(
127 outgoing_message_bits,
128 outgoing_message_vars,
130 "unpack_outgoing_message"));
132 incoming_messages_bits.resize(compliance_predicate.max_arity);
133 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
134 const size_t incoming_msg_size_in_bits =
136 (1 + compliance_predicate.incoming_message_payload_lengths[i]);
138 incoming_messages_bits[i].allocate(
140 incoming_msg_size_in_bits,
141 FMT("", "incoming_messages_bits_%zu", i));
142 unpack_incoming_messages.emplace_back(multipacking_gadget<FieldT>(
144 incoming_messages_bits[i],
145 incoming_message_vars[i],
147 FMT("", "unpack_incoming_messages_%zu", i)));
150 /* allocate digests */
151 commitment_and_incoming_message_digests.resize(
152 compliance_predicate.max_arity);
153 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
154 commitment_and_incoming_message_digests[i].allocate(
157 FMT("", "commitment_and_incoming_message_digests_%zu", i));
160 /* allocate commitment, verification key(s) and membership
161 * checker(s)/proof(s) */
163 new set_commitment_variable<FieldT, CRH_with_bit_out_gadget<FieldT>>(
164 pb, commitment_size, "commitment"));
166 libff::print_indent();
168 "* %s perform same type optimization for compliance predicate with "
170 (compliance_predicate.relies_on_same_type_inputs ? "Will" : "Will NOT"),
171 compliance_predicate.type);
172 if (compliance_predicate.relies_on_same_type_inputs) {
173 /* only one set_commitment_gadget is needed */
174 common_type.allocate(pb, "common_type");
175 common_type_check_aux.allocate(
177 compliance_predicate.accepted_input_types.size(),
178 "common_type_check_aux");
180 translation_step_vks_bits.resize(1);
181 translation_step_vks_bits[0].allocate(
182 pb, translation_step_vk_size_in_bits, "translation_step_vk_bits");
183 membership_check_results.allocate(pb, 1, "membership_check_results");
185 membership_proofs.emplace_back(set_membership_proof_variable<
187 CRH_with_bit_out_gadget<FieldT>>(
188 pb, max_number_of_predicates, "membership_proof"));
189 membership_checkers.emplace_back(
190 set_commitment_gadget<FieldT, CRH_with_bit_out_gadget<FieldT>>(
192 max_number_of_predicates,
193 translation_step_vks_bits[0],
195 membership_proofs[0],
196 membership_check_results[0],
197 "membership_checker"));
199 /* check for max_arity possibly different VKs */
200 translation_step_vks_bits.resize(compliance_predicate.max_arity);
201 membership_check_results.allocate(
202 pb, compliance_predicate.max_arity, "membership_check_results");
204 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
205 translation_step_vks_bits[i].allocate(
207 translation_step_vk_size_in_bits,
208 FMT("", "translation_step_vks_bits_%zu", i));
210 membership_proofs.emplace_back(set_membership_proof_variable<
212 CRH_with_bit_out_gadget<FieldT>>(
214 max_number_of_predicates,
215 FMT("", "membership_proof_%zu", i)));
216 membership_checkers.emplace_back(
217 set_commitment_gadget<FieldT, CRH_with_bit_out_gadget<FieldT>>(
219 max_number_of_predicates,
220 translation_step_vks_bits[i],
222 membership_proofs[i],
223 membership_check_results[i],
224 FMT("", "membership_checkers_%zu", i)));
228 /* allocate blocks */
229 block_for_outgoing_message.reset(new block_variable<FieldT>(
231 {commitment->bits, outgoing_message_bits},
232 "block_for_outgoing_message"));
234 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
235 block_for_incoming_messages.emplace_back(block_variable<FieldT>(
237 {commitment->bits, incoming_messages_bits[i]},
238 FMT("", "block_for_incoming_messages_%zu", i)));
241 /* allocate hash checkers */
242 hash_outgoing_message.reset(new CRH_with_field_out_gadget<FieldT>(
245 *block_for_outgoing_message,
246 mp_compliance_step_pcd_circuit_input,
247 "hash_outgoing_message"));
249 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
250 const size_t input_block_size =
251 commitment_size + incoming_messages_bits[i].size();
252 hash_incoming_messages.emplace_back(CRH_with_field_out_gadget<FieldT>(
255 block_for_incoming_messages[i],
256 commitment_and_incoming_message_digests[i],
257 FMT("", "hash_incoming_messages_%zu", i)));
260 /* allocate useful zero variable */
261 zero.allocate(pb, "zero");
263 /* prepare arguments for the verifier */
264 if (compliance_predicate.relies_on_same_type_inputs) {
265 translation_step_vks.emplace_back(
266 r1cs_ppzksnark_verification_key_variable<ppT>(
268 translation_step_vks_bits[0],
269 mp_translation_step_pcd_circuit_maker<
270 other_curve<ppT>>::input_size_in_elts(),
271 "translation_step_vk"));
273 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
274 translation_step_vks.emplace_back(
275 r1cs_ppzksnark_verification_key_variable<ppT>(
277 translation_step_vks_bits[i],
278 mp_translation_step_pcd_circuit_maker<
279 other_curve<ppT>>::input_size_in_elts(),
280 FMT("", "translation_step_vks_%zu", i)));
284 verification_results.allocate(
285 pb, compliance_predicate.max_arity, "verification_results");
286 commitment_and_incoming_messages_digest_bits.resize(
287 compliance_predicate.max_arity);
289 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
290 commitment_and_incoming_messages_digest_bits[i].allocate(
292 digest_size * field_logsize(),
293 FMT("", "commitment_and_incoming_messages_digest_bits_%zu", i));
294 unpack_commitment_and_incoming_message_digests.emplace_back(
295 multipacking_gadget<FieldT>(
297 commitment_and_incoming_messages_digest_bits[i],
298 commitment_and_incoming_message_digests[i],
301 "unpack_commitment_and_incoming_message_digests_%zu",
304 verifier_input.emplace_back(
305 commitment_and_incoming_messages_digest_bits[i]);
306 while (verifier_input[i].size() < padded_verifier_input_size) {
307 verifier_input[i].emplace_back(zero);
311 r1cs_ppzksnark_proof_variable<ppT>(pb, FMT("", "proof_%zu", i)));
312 const r1cs_ppzksnark_verification_key_variable<ppT> &vk_to_be_used =
313 (compliance_predicate.relies_on_same_type_inputs
314 ? translation_step_vks[0]
315 : translation_step_vks[i]);
316 verifier.emplace_back(r1cs_ppzksnark_verifier_gadget<ppT>(
320 mp_translation_step_pcd_circuit_maker<
321 other_curve<ppT>>::field_capacity(),
323 verification_results[i],
324 FMT("", "verifier_%zu", i)));
327 pb.set_input_sizes(input_size_in_elts());
330 template<typename ppT>
331 void mp_compliance_step_pcd_circuit_maker<ppT>::generate_r1cs_constraints()
333 const size_t digest_size =
334 CRH_with_bit_out_gadget<FieldT>::get_digest_len();
335 const size_t dimension = knapsack_dimension<FieldT>::dimension;
336 libff::print_indent();
337 printf("* Knapsack dimension: %zu\n", dimension);
339 libff::print_indent();
341 "* Compliance predicate arity: %zu\n", compliance_predicate.max_arity);
342 libff::print_indent();
344 "* Compliance predicate outgoing payload length: %zu\n",
345 compliance_predicate.outgoing_message_payload_length);
346 libff::print_indent();
347 printf("* Compliance predicate incoming payload lengths:");
348 for (auto l : compliance_predicate.incoming_message_payload_lengths) {
352 libff::print_indent();
354 "* Compliance predicate local data length: %zu\n",
355 compliance_predicate.local_data_length);
356 libff::print_indent();
358 "* Compliance predicate witness length: %zu\n",
359 compliance_predicate.witness_length);
361 PROFILE_CONSTRAINTS(pb, "booleanity")
363 PROFILE_CONSTRAINTS(pb, "booleanity: unpack outgoing_message")
365 unpack_outgoing_message->generate_r1cs_constraints(true);
368 PROFILE_CONSTRAINTS(pb, "booleanity: unpack s incoming_messages")
370 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
371 unpack_incoming_messages[i].generate_r1cs_constraints(true);
375 PROFILE_CONSTRAINTS(pb, "booleanity: unpack verification key")
377 for (size_t i = 0; i < translation_step_vks.size(); ++i) {
378 translation_step_vks[i].generate_r1cs_constraints(true);
383 PROFILE_CONSTRAINTS(pb, "(1+s) copies of hash")
385 libff::print_indent();
386 printf("* Digest-size: %zu\n", digest_size);
387 hash_outgoing_message->generate_r1cs_constraints();
389 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
390 hash_incoming_messages[i].generate_r1cs_constraints();
394 PROFILE_CONSTRAINTS(pb, "s copies of repacking circuit for verifier")
396 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
397 unpack_commitment_and_incoming_message_digests[i]
398 .generate_r1cs_constraints(true);
402 PROFILE_CONSTRAINTS(pb, "set membership check")
404 for (auto &membership_proof : membership_proofs) {
405 membership_proof.generate_r1cs_constraints();
408 for (auto &membership_checker : membership_checkers) {
409 membership_checker.generate_r1cs_constraints();
413 PROFILE_CONSTRAINTS(pb, "compliance predicate")
415 compliance_predicate_as_gadget->generate_r1cs_constraints();
418 PROFILE_CONSTRAINTS(pb, "s copies of verifier for translated proofs")
420 PROFILE_CONSTRAINTS(pb, "check that s proofs lie on the curve")
422 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
423 proof[i].generate_r1cs_constraints();
427 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
428 verifier[i].generate_r1cs_constraints();
432 PROFILE_CONSTRAINTS(pb, "miscellaneous")
434 generate_r1cs_equals_const_constraint<FieldT>(
435 pb, zero, FieldT::zero(), "zero");
437 PROFILE_CONSTRAINTS(pb, "check that s proofs lie on the curve")
439 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
440 generate_boolean_r1cs_constraint<FieldT>(
442 verification_results[i],
443 FMT("", "verification_results_%zu", i));
447 /* either type = 0 or proof verified w.r.t. a valid verification key */
449 pb, "check that s messages have valid proofs (or are base case)")
451 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
452 pb.add_r1cs_constraint(
453 r1cs_constraint<FieldT>(
454 incoming_message_types[i],
455 1 - verification_results[i],
457 FMT("", "not_base_case_implies_valid_proof_%zu", i));
461 if (compliance_predicate.relies_on_same_type_inputs) {
464 "check that all non-base case messages are of same type and "
465 "that VK is validly selected")
467 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
468 pb.add_r1cs_constraint(
469 r1cs_constraint<FieldT>(
470 incoming_message_types[i],
471 incoming_message_types[i] - common_type,
473 FMT("", "non_base_types_equal_%zu", i));
476 pb.add_r1cs_constraint(
477 r1cs_constraint<FieldT>(
478 common_type, 1 - membership_check_results[0], 0),
479 "valid_vk_for_the_common_type");
481 auto it = compliance_predicate.accepted_input_types.begin();
483 i < compliance_predicate.accepted_input_types.size();
485 pb.add_r1cs_constraint(
486 r1cs_constraint<FieldT>(
487 (i == 0 ? common_type
488 : common_type_check_aux[i - 1]),
489 common_type - FieldT(*it),
490 (i == compliance_predicate.accepted_input_types
494 : common_type_check_aux[i])),
496 "common_type_in_prescribed_set_%zu_must_equal_%zu",
503 pb, "check that all s messages have validly selected VKs")
505 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
506 pb.add_r1cs_constraint(
507 r1cs_constraint<FieldT>(
508 incoming_message_types[i],
509 1 - membership_check_results[i],
511 FMT("", "not_base_case_implies_valid_vk_%zu", i));
515 pb.add_r1cs_constraint(
516 r1cs_constraint<FieldT>(
517 1, outgoing_message_type, FieldT(compliance_predicate.type)),
518 "enforce_outgoing_type");
521 PRINT_CONSTRAINT_PROFILING();
522 libff::print_indent();
524 "* Number of constraints in mp_compliance_step_pcd_circuit: %zu\n",
525 pb.num_constraints());
528 template<typename ppT>
529 r1cs_constraint_system<libff::Fr<ppT>> mp_compliance_step_pcd_circuit_maker<
530 ppT>::get_circuit() const
532 return pb.get_constraint_system();
535 template<typename ppT>
536 r1cs_primary_input<libff::Fr<ppT>> mp_compliance_step_pcd_circuit_maker<
537 ppT>::get_primary_input() const
539 return pb.primary_input();
542 template<typename ppT>
543 r1cs_auxiliary_input<libff::Fr<ppT>> mp_compliance_step_pcd_circuit_maker<
544 ppT>::get_auxiliary_input() const
546 return pb.auxiliary_input();
549 template<typename ppT>
550 void mp_compliance_step_pcd_circuit_maker<ppT>::generate_r1cs_witness(
551 const set_commitment &commitment_to_translation_step_r1cs_vks,
552 const std::vector<r1cs_ppzksnark_verification_key<other_curve<ppT>>>
553 &mp_translation_step_pcd_circuit_vks,
554 const std::vector<set_membership_proof> &vk_membership_proofs,
555 const r1cs_pcd_compliance_predicate_primary_input<FieldT>
556 &compliance_predicate_primary_input,
557 const r1cs_pcd_compliance_predicate_auxiliary_input<FieldT>
558 &compliance_predicate_auxiliary_input,
559 const std::vector<r1cs_ppzksnark_proof<other_curve<ppT>>>
560 &translation_step_proofs)
562 this->pb.clear_values();
563 this->pb.val(zero) = FieldT::zero();
565 compliance_predicate_as_gadget->generate_r1cs_witness(
566 compliance_predicate_primary_input.as_r1cs_primary_input(),
567 compliance_predicate_auxiliary_input.as_r1cs_auxiliary_input(
568 compliance_predicate.incoming_message_payload_lengths));
570 unpack_outgoing_message->generate_r1cs_witness_from_packed();
571 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
572 unpack_incoming_messages[i].generate_r1cs_witness_from_packed();
575 for (size_t i = 0; i < translation_step_vks.size(); ++i) {
576 translation_step_vks[i].generate_r1cs_witness(
577 mp_translation_step_pcd_circuit_vks[i]);
580 commitment->generate_r1cs_witness(commitment_to_translation_step_r1cs_vks);
582 if (compliance_predicate.relies_on_same_type_inputs) {
583 /* all messages (except base case) must be of the same type */
584 this->pb.val(common_type) = FieldT::zero();
585 size_t nonzero_type_idx = 0;
586 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
587 if (this->pb.val(incoming_message_types[i]) == 0) {
591 if (this->pb.val(common_type).is_zero()) {
592 this->pb.val(common_type) =
593 this->pb.val(incoming_message_types[i]);
594 nonzero_type_idx = i;
597 this->pb.val(common_type) ==
598 this->pb.val(incoming_message_types[i]));
602 this->pb.val(membership_check_results[0]) =
603 (this->pb.val(common_type).is_zero() ? FieldT::zero()
605 membership_proofs[0].generate_r1cs_witness(
606 vk_membership_proofs[nonzero_type_idx]);
607 membership_checkers[0].generate_r1cs_witness();
609 auto it = compliance_predicate.accepted_input_types.begin();
610 for (size_t i = 0; i < compliance_predicate.accepted_input_types.size();
612 pb.val(common_type_check_aux[i]) =
613 ((i == 0 ? pb.val(common_type)
614 : pb.val(common_type_check_aux[i - 1])) *
615 (pb.val(common_type) - FieldT(*it)));
618 for (size_t i = 0; i < membership_checkers.size(); ++i) {
619 this->pb.val(membership_check_results[i]) =
620 (this->pb.val(incoming_message_types[i]).is_zero()
623 membership_proofs[i].generate_r1cs_witness(vk_membership_proofs[i]);
624 membership_checkers[i].generate_r1cs_witness();
628 hash_outgoing_message->generate_r1cs_witness();
629 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
630 hash_incoming_messages[i].generate_r1cs_witness();
631 unpack_commitment_and_incoming_message_digests[i]
632 .generate_r1cs_witness_from_packed();
635 for (size_t i = 0; i < compliance_predicate.max_arity; ++i) {
636 proof[i].generate_r1cs_witness(translation_step_proofs[i]);
637 verifier[i].generate_r1cs_witness();
641 get_circuit(); // force generating constraints
642 assert(this->pb.is_satisfied());
646 template<typename ppT>
647 size_t mp_compliance_step_pcd_circuit_maker<ppT>::field_logsize()
649 return libff::Fr<ppT>::size_in_bits();
652 template<typename ppT>
653 size_t mp_compliance_step_pcd_circuit_maker<ppT>::field_capacity()
655 return libff::Fr<ppT>::capacity();
658 template<typename ppT>
659 size_t mp_compliance_step_pcd_circuit_maker<ppT>::input_size_in_elts()
661 const size_t digest_size =
662 CRH_with_field_out_gadget<FieldT>::get_digest_len();
666 template<typename ppT>
667 size_t mp_compliance_step_pcd_circuit_maker<ppT>::input_capacity_in_bits()
669 return input_size_in_elts() * field_capacity();
672 template<typename ppT>
673 size_t mp_compliance_step_pcd_circuit_maker<ppT>::input_size_in_bits()
675 return input_size_in_elts() * field_logsize();
678 template<typename ppT>
679 mp_translation_step_pcd_circuit_maker<ppT>::
680 mp_translation_step_pcd_circuit_maker(
681 const r1cs_ppzksnark_verification_key<other_curve<ppT>>
684 /* allocate input of the translation MP_PCD circuit */
685 mp_translation_step_pcd_circuit_input.allocate(
686 pb, input_size_in_elts(), "mp_translation_step_pcd_circuit_input");
688 /* unpack translation step MP_PCD circuit input */
689 unpacked_mp_translation_step_pcd_circuit_input.allocate(
691 mp_compliance_step_pcd_circuit_maker<
692 other_curve<ppT>>::input_size_in_bits(),
693 "unpacked_mp_translation_step_pcd_circuit_input");
694 unpack_mp_translation_step_pcd_circuit_input.reset(
695 new multipacking_gadget<FieldT>(
697 unpacked_mp_translation_step_pcd_circuit_input,
698 mp_translation_step_pcd_circuit_input,
700 "unpack_mp_translation_step_pcd_circuit_input"));
702 /* prepare arguments for the verifier */
703 hardcoded_compliance_step_vk.reset(
704 new r1cs_ppzksnark_preprocessed_r1cs_ppzksnark_verification_key_variable<
705 ppT>(pb, compliance_step_vk, "hardcoded_compliance_step_vk"));
706 proof.reset(new r1cs_ppzksnark_proof_variable<ppT>(pb, "proof"));
708 /* verify previous proof */
709 online_verifier.reset(new r1cs_ppzksnark_online_verifier_gadget<ppT>(
711 *hardcoded_compliance_step_vk,
712 unpacked_mp_translation_step_pcd_circuit_input,
713 mp_compliance_step_pcd_circuit_maker<other_curve<ppT>>::field_logsize(),
715 ONE, // must always accept
718 pb.set_input_sizes(input_size_in_elts());
721 template<typename ppT>
722 void mp_translation_step_pcd_circuit_maker<ppT>::generate_r1cs_constraints()
724 PROFILE_CONSTRAINTS(pb, "repacking: unpack circuit input")
726 unpack_mp_translation_step_pcd_circuit_input->generate_r1cs_constraints(
730 PROFILE_CONSTRAINTS(pb, "verifier for compliance proofs")
732 PROFILE_CONSTRAINTS(pb, "check that proof lies on the curve")
734 proof->generate_r1cs_constraints();
737 online_verifier->generate_r1cs_constraints();
740 PRINT_CONSTRAINT_PROFILING();
741 libff::print_indent();
743 "* Number of constraints in mp_translation_step_pcd_circuit: %zu\n",
744 pb.num_constraints());
747 template<typename ppT>
748 r1cs_constraint_system<libff::Fr<ppT>> mp_translation_step_pcd_circuit_maker<
749 ppT>::get_circuit() const
751 return pb.get_constraint_system();
754 template<typename ppT>
755 void mp_translation_step_pcd_circuit_maker<ppT>::generate_r1cs_witness(
756 const r1cs_primary_input<libff::Fr<ppT>> translation_step_input,
757 const r1cs_ppzksnark_proof<other_curve<ppT>> &prev_proof)
759 this->pb.clear_values();
760 mp_translation_step_pcd_circuit_input.fill_with_field_elements(
761 pb, translation_step_input);
762 unpack_mp_translation_step_pcd_circuit_input
763 ->generate_r1cs_witness_from_packed();
765 proof->generate_r1cs_witness(prev_proof);
766 online_verifier->generate_r1cs_witness();
769 get_circuit(); // force generating constraints
770 assert(this->pb.is_satisfied());
774 template<typename ppT>
775 r1cs_primary_input<libff::Fr<ppT>> mp_translation_step_pcd_circuit_maker<
776 ppT>::get_primary_input() const
778 return pb.primary_input();
781 template<typename ppT>
782 r1cs_auxiliary_input<libff::Fr<ppT>> mp_translation_step_pcd_circuit_maker<
783 ppT>::get_auxiliary_input() const
785 return pb.auxiliary_input();
788 template<typename ppT>
789 size_t mp_translation_step_pcd_circuit_maker<ppT>::field_logsize()
791 return libff::Fr<ppT>::size_in_bits();
794 template<typename ppT>
795 size_t mp_translation_step_pcd_circuit_maker<ppT>::field_capacity()
797 return libff::Fr<ppT>::capacity();
800 template<typename ppT>
801 size_t mp_translation_step_pcd_circuit_maker<ppT>::input_size_in_elts()
803 return libff::div_ceil(
804 mp_compliance_step_pcd_circuit_maker<
805 other_curve<ppT>>::input_size_in_bits(),
806 mp_translation_step_pcd_circuit_maker<ppT>::field_capacity());
809 template<typename ppT>
810 size_t mp_translation_step_pcd_circuit_maker<ppT>::input_capacity_in_bits()
812 return input_size_in_elts() * field_capacity();
815 template<typename ppT>
816 size_t mp_translation_step_pcd_circuit_maker<ppT>::input_size_in_bits()
818 return input_size_in_elts() * field_logsize();
821 template<typename ppT>
822 r1cs_primary_input<libff::Fr<ppT>> get_mp_compliance_step_pcd_circuit_input(
823 const set_commitment &commitment_to_translation_step_r1cs_vks,
824 const r1cs_pcd_compliance_predicate_primary_input<libff::Fr<ppT>>
827 libff::enter_block("Call to get_mp_compliance_step_pcd_circuit_input");
828 typedef libff::Fr<ppT> FieldT;
830 const r1cs_variable_assignment<FieldT> outgoing_message_as_va =
831 primary_input.outgoing_message->as_r1cs_variable_assignment();
832 libff::bit_vector msg_bits;
833 for (const FieldT &elt : outgoing_message_as_va) {
834 const libff::bit_vector elt_bits =
835 libff::convert_field_element_to_bit_vector(elt);
836 msg_bits.insert(msg_bits.end(), elt_bits.begin(), elt_bits.end());
839 libff::bit_vector block;
842 commitment_to_translation_step_r1cs_vks.begin(),
843 commitment_to_translation_step_r1cs_vks.end());
844 block.insert(block.end(), msg_bits.begin(), msg_bits.end());
846 libff::enter_block("Sample CRH randomness");
847 CRH_with_field_out_gadget<FieldT>::sample_randomness(block.size());
848 libff::leave_block("Sample CRH randomness");
850 const std::vector<FieldT> digest =
851 CRH_with_field_out_gadget<FieldT>::get_hash(block);
852 libff::leave_block("Call to get_mp_compliance_step_pcd_circuit_input");
857 template<typename ppT>
858 r1cs_primary_input<libff::Fr<ppT>> get_mp_translation_step_pcd_circuit_input(
859 const set_commitment &commitment_to_translation_step_r1cs_vks,
860 const r1cs_pcd_compliance_predicate_primary_input<
861 libff::Fr<other_curve<ppT>>> &primary_input)
863 libff::enter_block("Call to get_mp_translation_step_pcd_circuit_input");
864 typedef libff::Fr<ppT> FieldT;
866 const std::vector<libff::Fr<other_curve<ppT>>>
867 mp_compliance_step_pcd_circuit_input =
868 get_mp_compliance_step_pcd_circuit_input<other_curve<ppT>>(
869 commitment_to_translation_step_r1cs_vks, primary_input);
870 libff::bit_vector mp_compliance_step_pcd_circuit_input_bits;
871 for (const libff::Fr<other_curve<ppT>> &elt :
872 mp_compliance_step_pcd_circuit_input) {
873 const libff::bit_vector elt_bits =
874 libff::convert_field_element_to_bit_vector<
875 libff::Fr<other_curve<ppT>>>(elt);
876 mp_compliance_step_pcd_circuit_input_bits.insert(
877 mp_compliance_step_pcd_circuit_input_bits.end(),
882 mp_compliance_step_pcd_circuit_input_bits.resize(
883 mp_translation_step_pcd_circuit_maker<ppT>::input_capacity_in_bits(),
886 const r1cs_primary_input<FieldT> result =
887 libff::pack_bit_vector_into_field_element_vector<FieldT>(
888 mp_compliance_step_pcd_circuit_input_bits,
889 mp_translation_step_pcd_circuit_maker<ppT>::field_capacity());
890 libff::leave_block("Call to get_mp_translation_step_pcd_circuit_input");
895 } // namespace libsnark
897 #endif // MP_PCD_CIRCUITS_TCC_