2 *****************************************************************************
4 Implementation of functionality that runs the R1CS multi-predicate ppzkPCD
5 for a compliance predicate example.
7 See run_r1cs_mp_ppzkpcd.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 RUN_R1CS_MP_PPZKPCD_TCC_
16 #define RUN_R1CS_MP_PPZKPCD_TCC_
18 #include <libsnark/zk_proof_systems/pcd/r1cs_pcd/compliance_predicate/examples/tally_cp.hpp>
19 #include <libsnark/zk_proof_systems/pcd/r1cs_pcd/r1cs_mp_ppzkpcd/r1cs_mp_ppzkpcd.hpp>
24 template<typename PCD_ppT>
25 bool run_r1cs_mp_ppzkpcd_tally_example(
26 const size_t wordsize,
27 const size_t max_arity,
29 const bool test_serialization,
30 const bool test_multi_type,
31 const bool test_same_type_optimization)
33 libff::enter_block("Call to run_r1cs_mp_ppzkpcd_tally_example");
35 typedef libff::Fr<typename PCD_ppT::curve_A_pp> FieldT;
37 bool all_accept = true;
39 libff::enter_block("Generate all messages");
41 size_t nodes_in_layer = 1;
42 for (size_t layer = 0; layer <= depth; ++layer) {
43 tree_size += nodes_in_layer;
44 nodes_in_layer *= max_arity;
47 std::vector<size_t> tree_types(tree_size);
48 std::vector<size_t> tree_elems(tree_size);
49 std::vector<size_t> tree_arity(tree_size);
53 for (size_t layer = 0; layer <= depth; ++layer) {
54 for (size_t id_in_layer = 0; id_in_layer < nodes_in_layer;
55 ++id_in_layer, ++node_idx) {
56 if (!test_multi_type) {
57 tree_types[node_idx] = 1;
59 if (test_same_type_optimization) {
60 tree_types[node_idx] = 1 + ((depth - layer) & 1);
62 tree_types[node_idx] = 1 + (std::rand() % 2);
66 tree_elems[node_idx] = std::rand() % 100;
67 tree_arity[node_idx] =
69 max_arity); /* we will just skip below this threshold */
70 printf("tree_types[%zu] = %zu\n", node_idx, tree_types[node_idx]);
71 printf("tree_elems[%zu] = %zu\n", node_idx, tree_elems[node_idx]);
72 printf("tree_arity[%zu] = %zu\n", node_idx, tree_arity[node_idx]);
74 nodes_in_layer *= max_arity;
77 libff::leave_block("Generate all messages");
79 std::vector<r1cs_mp_ppzkpcd_proof<PCD_ppT>> tree_proofs(tree_size);
80 std::vector<std::shared_ptr<r1cs_pcd_message<FieldT>>> tree_messages(
83 libff::enter_block("Generate compliance predicates");
84 std::set<size_t> tally_1_accepted_types, tally_2_accepted_types;
85 if (test_same_type_optimization) {
86 if (!test_multi_type) {
87 /* only tally 1 is going to be used */
88 tally_1_accepted_types.insert(1);
90 tally_1_accepted_types.insert(2);
91 tally_2_accepted_types.insert(1);
95 tally_cp_handler<FieldT> tally_1(
99 test_same_type_optimization,
100 tally_1_accepted_types);
101 tally_cp_handler<FieldT> tally_2(
105 test_same_type_optimization,
106 tally_2_accepted_types);
107 tally_1.generate_r1cs_constraints();
108 tally_2.generate_r1cs_constraints();
109 r1cs_pcd_compliance_predicate<FieldT> cp_1 =
110 tally_1.get_compliance_predicate();
111 r1cs_pcd_compliance_predicate<FieldT> cp_2 =
112 tally_2.get_compliance_predicate();
113 libff::leave_block("Generate compliance predicates");
115 libff::print_header("R1CS ppzkPCD Generator");
116 r1cs_mp_ppzkpcd_keypair<PCD_ppT> keypair =
117 r1cs_mp_ppzkpcd_generator<PCD_ppT>({cp_1, cp_2});
119 libff::print_header("Process verification key");
120 r1cs_mp_ppzkpcd_processed_verification_key<PCD_ppT> pvk =
121 r1cs_mp_ppzkpcd_process_vk<PCD_ppT>(keypair.vk);
123 if (test_serialization) {
124 libff::enter_block("Test serialization of keys");
125 keypair.pk = libff::reserialize<r1cs_mp_ppzkpcd_proving_key<PCD_ppT>>(
128 libff::reserialize<r1cs_mp_ppzkpcd_verification_key<PCD_ppT>>(
130 pvk = libff::reserialize<
131 r1cs_mp_ppzkpcd_processed_verification_key<PCD_ppT>>(pvk);
132 libff::leave_block("Test serialization of keys");
135 std::shared_ptr<r1cs_pcd_message<FieldT>> base_msg =
136 tally_1.get_base_case_message(); /* we choose the base to always be
138 nodes_in_layer /= max_arity;
139 for (long layer = depth; layer >= 0; --layer, nodes_in_layer /= max_arity) {
140 for (size_t i = 0; i < nodes_in_layer; ++i) {
141 const size_t cur_idx = (nodes_in_layer - 1) / (max_arity - 1) + i;
143 tally_cp_handler<FieldT> &cur_tally =
144 (tree_types[cur_idx] == 1 ? tally_1 : tally_2);
145 r1cs_pcd_compliance_predicate<FieldT> &cur_cp =
146 (tree_types[cur_idx] == 1 ? cp_1 : cp_2);
148 const bool base_case =
149 (max_arity * cur_idx + max_arity >= tree_size);
151 std::vector<std::shared_ptr<r1cs_pcd_message<FieldT>>> msgs(
152 max_arity, base_msg);
153 std::vector<r1cs_mp_ppzkpcd_proof<PCD_ppT>> proofs(max_arity);
156 for (size_t i = 0; i < max_arity; ++i) {
157 msgs[i] = tree_messages[max_arity * cur_idx + i + 1];
158 proofs[i] = tree_proofs[max_arity * cur_idx + i + 1];
161 msgs.resize(tree_arity[i]);
162 proofs.resize(tree_arity[i]);
164 std::shared_ptr<r1cs_pcd_local_data<FieldT>> ld;
165 ld.reset(new tally_pcd_local_data<FieldT>(tree_elems[cur_idx]));
166 cur_tally.generate_r1cs_witness(msgs, ld);
168 const r1cs_pcd_compliance_predicate_primary_input<FieldT>
169 tally_primary_input(cur_tally.get_outgoing_message());
170 const r1cs_pcd_compliance_predicate_auxiliary_input<FieldT>
171 tally_auxiliary_input(msgs, ld, cur_tally.get_witness());
173 libff::print_header("R1CS ppzkPCD Prover");
174 r1cs_mp_ppzkpcd_proof<PCD_ppT> proof =
175 r1cs_mp_ppzkpcd_prover<PCD_ppT>(
179 tally_auxiliary_input,
182 if (test_serialization) {
183 libff::enter_block("Test serialization of proof");
185 libff::reserialize<r1cs_mp_ppzkpcd_proof<PCD_ppT>>(proof);
186 libff::leave_block("Test serialization of proof");
189 tree_proofs[cur_idx] = proof;
190 tree_messages[cur_idx] = cur_tally.get_outgoing_message();
192 libff::print_header("R1CS ppzkPCD Verifier");
193 const r1cs_mp_ppzkpcd_primary_input<PCD_ppT> pcd_verifier_input(
194 tree_messages[cur_idx]);
195 const bool ans = r1cs_mp_ppzkpcd_verifier<PCD_ppT>(
196 keypair.vk, pcd_verifier_input, tree_proofs[cur_idx]);
198 libff::print_header("R1CS ppzkPCD Online Verifier");
199 const bool ans2 = r1cs_mp_ppzkpcd_online_verifier<PCD_ppT>(
200 pvk, pcd_verifier_input, tree_proofs[cur_idx]);
203 all_accept = all_accept && ans;
206 for (size_t i = 0; i < msgs.size(); ++i) {
207 printf("Message %zu was:\n", i);
210 printf("Summand at this node:\n%zu\n", tree_elems[cur_idx]);
211 printf("Outgoing message is:\n");
212 tree_messages[cur_idx]->print();
215 "Current node = %zu. Current proof verifies = %s\n",
219 "==========================================================="
220 "=====================\n\n\n");
224 libff::leave_block("Call to run_r1cs_mp_ppzkpcd_tally_example");
229 } // namespace libsnark
231 #endif // RUN_R1CS_MP_PPZKPCD_TCC_