Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
run_r1cs_mp_ppzkpcd.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of functionality that runs the R1CS multi-predicate ppzkPCD
5  for a compliance predicate example.
6 
7  See run_r1cs_mp_ppzkpcd.hpp .
8 
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  *****************************************************************************/
14 
15 #ifndef RUN_R1CS_MP_PPZKPCD_TCC_
16 #define RUN_R1CS_MP_PPZKPCD_TCC_
17 
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>
20 
21 namespace libsnark
22 {
23 
24 template<typename PCD_ppT>
25 bool run_r1cs_mp_ppzkpcd_tally_example(
26  const size_t wordsize,
27  const size_t max_arity,
28  const size_t depth,
29  const bool test_serialization,
30  const bool test_multi_type,
31  const bool test_same_type_optimization)
32 {
33  libff::enter_block("Call to run_r1cs_mp_ppzkpcd_tally_example");
34 
35  typedef libff::Fr<typename PCD_ppT::curve_A_pp> FieldT;
36 
37  bool all_accept = true;
38 
39  libff::enter_block("Generate all messages");
40  size_t tree_size = 0;
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;
45  }
46 
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);
50 
51  nodes_in_layer = 1;
52  size_t node_idx = 0;
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;
58  } else {
59  if (test_same_type_optimization) {
60  tree_types[node_idx] = 1 + ((depth - layer) & 1);
61  } else {
62  tree_types[node_idx] = 1 + (std::rand() % 2);
63  }
64  }
65 
66  tree_elems[node_idx] = std::rand() % 100;
67  tree_arity[node_idx] =
68  1 + (std::rand() %
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]);
73  }
74  nodes_in_layer *= max_arity;
75  }
76 
77  libff::leave_block("Generate all messages");
78 
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(
81  tree_size);
82 
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);
89  } else {
90  tally_1_accepted_types.insert(2);
91  tally_2_accepted_types.insert(1);
92  }
93  }
94 
95  tally_cp_handler<FieldT> tally_1(
96  1,
97  max_arity,
98  wordsize,
99  test_same_type_optimization,
100  tally_1_accepted_types);
101  tally_cp_handler<FieldT> tally_2(
102  2,
103  max_arity,
104  wordsize,
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");
114 
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});
118 
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);
122 
123  if (test_serialization) {
124  libff::enter_block("Test serialization of keys");
125  keypair.pk = libff::reserialize<r1cs_mp_ppzkpcd_proving_key<PCD_ppT>>(
126  keypair.pk);
127  keypair.vk =
128  libff::reserialize<r1cs_mp_ppzkpcd_verification_key<PCD_ppT>>(
129  keypair.vk);
130  pvk = libff::reserialize<
131  r1cs_mp_ppzkpcd_processed_verification_key<PCD_ppT>>(pvk);
132  libff::leave_block("Test serialization of keys");
133  }
134 
135  std::shared_ptr<r1cs_pcd_message<FieldT>> base_msg =
136  tally_1.get_base_case_message(); /* we choose the base to always be
137  tally_1 */
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;
142 
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);
147 
148  const bool base_case =
149  (max_arity * cur_idx + max_arity >= tree_size);
150 
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);
154 
155  if (!base_case) {
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];
159  }
160  }
161  msgs.resize(tree_arity[i]);
162  proofs.resize(tree_arity[i]);
163 
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);
167 
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());
172 
173  libff::print_header("R1CS ppzkPCD Prover");
174  r1cs_mp_ppzkpcd_proof<PCD_ppT> proof =
175  r1cs_mp_ppzkpcd_prover<PCD_ppT>(
176  keypair.pk,
177  cur_cp.name,
178  tally_primary_input,
179  tally_auxiliary_input,
180  proofs);
181 
182  if (test_serialization) {
183  libff::enter_block("Test serialization of proof");
184  proof =
185  libff::reserialize<r1cs_mp_ppzkpcd_proof<PCD_ppT>>(proof);
186  libff::leave_block("Test serialization of proof");
187  }
188 
189  tree_proofs[cur_idx] = proof;
190  tree_messages[cur_idx] = cur_tally.get_outgoing_message();
191 
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]);
197 
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]);
201  assert(ans == ans2);
202 
203  all_accept = all_accept && ans;
204 
205  printf("\n");
206  for (size_t i = 0; i < msgs.size(); ++i) {
207  printf("Message %zu was:\n", i);
208  msgs[i]->print();
209  }
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();
213  printf("\n");
214  printf(
215  "Current node = %zu. Current proof verifies = %s\n",
216  cur_idx,
217  ans ? "YES" : "NO");
218  printf("\n\n\n "
219  "==========================================================="
220  "=====================\n\n\n");
221  }
222  }
223 
224  libff::leave_block("Call to run_r1cs_mp_ppzkpcd_tally_example");
225 
226  return all_accept;
227 }
228 
229 } // namespace libsnark
230 
231 #endif // RUN_R1CS_MP_PPZKPCD_TCC_