Clearmatics Libsnark  0.1
C++ library for zkSNARK proofs
sp_pcd_circuits.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of functionality for creating and using the two PCD circuits in
5  a single-predicate PCD construction.
6 
7  See sp_pcd_circuits.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 SP_PCD_CIRCUITS_TCC_
16 #define SP_PCD_CIRCUITS_TCC_
17 
18 #include <libff/common/utils.hpp>
19 #include <libsnark/gadgetlib1/constraint_profiling.hpp>
20 
21 namespace libsnark
22 {
23 
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)
28 {
29  /* calculate some useful sizes */
30  assert(compliance_predicate.is_well_formed());
31  assert(compliance_predicate.has_equal_input_and_output_lengths());
32 
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 =
37  field_logsize() *
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();
46 
47  printf(
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);
53 
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);
57 
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");
61 
62  /* allocate inputs to the compliance predicate */
63  outgoing_message_type.allocate(pb, "outgoing_message_type");
64  outgoing_message_payload.allocate(
65  pb,
66  compliance_predicate.outgoing_message_payload_length,
67  "outgoing_message_payload");
68 
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());
75 
76  arity.allocate(pb, "arity");
77 
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(
85  pb,
86  compliance_predicate.outgoing_message_payload_length,
87  FMT("", "incoming_message_payloads_%zu", i));
88 
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());
95  }
96 
97  local_data.allocate(
98  pb, compliance_predicate.local_data_length, "local_data");
99  cp_witness.allocate(pb, compliance_predicate.witness_length, "cp_witness");
100 
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());
108  }
109 
110  compliance_predicate_as_gadget.reset(new gadget_from_r1cs<FieldT>(
111  pb,
112  {outgoing_message_vars,
113  pb_variable_array<FieldT>(1, arity),
114  incoming_messages_concat,
115  local_data,
116  cp_witness},
117  compliance_predicate.constraint_system,
118  "compliance_predicate_as_gadget"));
119 
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>(
124  pb,
125  outgoing_message_bits,
126  outgoing_message_vars,
127  field_logsize(),
128  "unpack_outgoing_message"));
129 
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>(
135  pb,
136  incoming_messages_bits[i],
137  incoming_message_vars[i],
138  field_logsize(),
139  FMT("", "unpack_incoming_messages_%zu", i)));
140  }
141 
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(
147  pb,
148  digest_size,
149  FMT("",
150  "sp_translation_step_vk_and_incoming_message_payload_digests_%"
151  "zu",
152  i));
153  }
154 
155  /* allocate blocks */
156  sp_translation_step_vk_bits.allocate(
157  pb, sp_translation_step_vk_size_in_bits, "sp_translation_step_vk_bits");
158 
159  block_for_outgoing_message.reset(new block_variable<FieldT>(
160  pb,
161  {sp_translation_step_vk_bits, outgoing_message_bits},
162  "block_for_outgoing_message"));
163 
164  for (size_t i = 0; i < compliance_predicate_arity; ++i) {
165  blocks_for_incoming_messages.emplace_back(block_variable<FieldT>(
166  pb,
167  {sp_translation_step_vk_bits, incoming_messages_bits[i]},
168  FMT("", "blocks_for_incoming_messages_zu", i)));
169  }
170 
171  /* allocate hash checkers */
172  hash_outgoing_message.reset(new CRH_with_field_out_gadget<FieldT>(
173  pb,
174  block_size,
175  *block_for_outgoing_message,
176  sp_compliance_step_pcd_circuit_input,
177  "hash_outgoing_message"));
178 
179  for (size_t i = 0; i < compliance_predicate_arity; ++i) {
180  hash_incoming_messages.emplace_back(CRH_with_field_out_gadget<FieldT>(
181  pb,
182  block_size,
183  blocks_for_incoming_messages[i],
184  sp_translation_step_vk_and_incoming_message_payload_digests[i],
185  FMT("", "hash_incoming_messages_%zu", i)));
186  }
187 
188  /* allocate useful zero variable */
189  zero.allocate(pb, "zero");
190 
191  /* prepare arguments for the verifier */
192  sp_translation_step_vk.reset(
193  new r1cs_ppzksnark_verification_key_variable<ppT>(
194  pb,
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"));
199 
200  verification_result.allocate(pb, "verification_result");
201  sp_translation_step_vk_and_incoming_message_payload_digest_bits.resize(
202  compliance_predicate_arity);
203 
204  for (size_t i = 0; i < compliance_predicate_arity; ++i) {
205  sp_translation_step_vk_and_incoming_message_payload_digest_bits[i]
206  .allocate(
207  pb,
208  digest_size * field_logsize(),
209  FMT("",
210  "sp_translation_step_vk_and_incoming_message_payload_"
211  "digest_bits_%zu",
212  i));
213  unpack_sp_translation_step_vk_and_incoming_message_payload_digests
214  .emplace_back(multipacking_gadget<FieldT>(
215  pb,
216  sp_translation_step_vk_and_incoming_message_payload_digest_bits
217  [i],
218  sp_translation_step_vk_and_incoming_message_payload_digests[i],
219  field_logsize(),
220  FMT("",
221  "unpack_sp_translation_step_vk_and_incoming_message_"
222  "payload_digests_%zu",
223  i)));
224 
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);
229  }
230 
231  proof.emplace_back(
232  r1cs_ppzksnark_proof_variable<ppT>(pb, FMT("", "proof_%zu", i)));
233  verifiers.emplace_back(r1cs_ppzksnark_verifier_gadget<ppT>(
234  pb,
235  *sp_translation_step_vk,
236  verifier_input[i],
237  sp_translation_step_pcd_circuit_maker<
238  other_curve<ppT>>::field_capacity(),
239  proof[i],
240  verification_result,
241  FMT("", "verifiers_%zu", i)));
242  }
243 
244  pb.set_input_sizes(input_size_in_elts());
245  printf("done compliance\n");
246 }
247 
248 template<typename ppT>
249 void sp_compliance_step_pcd_circuit_maker<ppT>::generate_r1cs_constraints()
250 {
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);
256 
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();
261  printf(
262  "* Compliance predicate payload length: %zu\n",
263  compliance_predicate.outgoing_message_payload_length);
264  libff::print_indent();
265  printf(
266  "* Compliance predicate local data length: %zu\n",
267  compliance_predicate.local_data_length);
268  libff::print_indent();
269  printf(
270  "* Compliance predicate witness length: %zu\n",
271  compliance_predicate.witness_length);
272 
273  PROFILE_CONSTRAINTS(pb, "booleanity")
274  {
275  PROFILE_CONSTRAINTS(pb, "booleanity: unpack outgoing_message")
276  {
277  unpack_outgoing_message->generate_r1cs_constraints(true);
278  }
279 
280  PROFILE_CONSTRAINTS(pb, "booleanity: unpack s incoming_message")
281  {
282  for (size_t i = 0; i < compliance_predicate_arity; ++i) {
283  unpack_incoming_messages[i].generate_r1cs_constraints(true);
284  }
285  }
286 
287  PROFILE_CONSTRAINTS(pb, "booleanity: unpack verification key")
288  {
289  sp_translation_step_vk->generate_r1cs_constraints(true);
290  }
291  }
292 
293  PROFILE_CONSTRAINTS(pb, "(1+s) copies of hash")
294  {
295  libff::print_indent();
296  printf("* Digest-size: %zu\n", digest_size);
297  hash_outgoing_message->generate_r1cs_constraints();
298 
299  for (size_t i = 0; i < compliance_predicate_arity; ++i) {
300  hash_incoming_messages[i].generate_r1cs_constraints();
301  }
302  }
303 
304  PROFILE_CONSTRAINTS(pb, "s copies of repacking circuit")
305  {
306  for (size_t i = 0; i < compliance_predicate_arity; ++i) {
307  unpack_sp_translation_step_vk_and_incoming_message_payload_digests
308  [i]
309  .generate_r1cs_constraints(true);
310  }
311  }
312 
313  PROFILE_CONSTRAINTS(pb, "compliance predicate")
314  {
315  compliance_predicate_as_gadget->generate_r1cs_constraints();
316  }
317 
318  PROFILE_CONSTRAINTS(pb, "s copies of verifier for translated proofs")
319  {
320  PROFILE_CONSTRAINTS(pb, "check that s proofs lie on the curve")
321  {
322  for (size_t i = 0; i < compliance_predicate_arity; ++i) {
323  proof[i].generate_r1cs_constraints();
324  }
325  }
326 
327  for (size_t i = 0; i < compliance_predicate_arity; ++i) {
328  verifiers[i].generate_r1cs_constraints();
329  }
330  }
331 
332  PROFILE_CONSTRAINTS(pb, "miscellaneous")
333  {
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");
338 
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");
344 
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));
351  }
352 
353  pb.add_r1cs_constraint(
354  r1cs_constraint<FieldT>(1, arity, compliance_predicate_arity),
355  "full_arity");
356  pb.add_r1cs_constraint(
357  r1cs_constraint<FieldT>(
358  1, outgoing_message_type, FieldT(compliance_predicate.type)),
359  "enforce_outgoing_type");
360  }
361 
362  PRINT_CONSTRAINT_PROFILING();
363  libff::print_indent();
364  printf(
365  "* Number of constraints in sp_compliance_step_pcd_circuit: %zu\n",
366  pb.num_constraints());
367 }
368 
369 template<typename ppT>
370 r1cs_constraint_system<libff::Fr<ppT>> sp_compliance_step_pcd_circuit_maker<
371  ppT>::get_circuit() const
372 {
373  return pb.get_constraint_system();
374 }
375 
376 template<typename ppT>
377 r1cs_primary_input<libff::Fr<ppT>> sp_compliance_step_pcd_circuit_maker<
378  ppT>::get_primary_input() const
379 {
380  return pb.primary_input();
381 }
382 
383 template<typename ppT>
384 r1cs_auxiliary_input<libff::Fr<ppT>> sp_compliance_step_pcd_circuit_maker<
385  ppT>::get_auxiliary_input() const
386 {
387  return pb.auxiliary_input();
388 }
389 
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)
399 {
400  const size_t compliance_predicate_arity = compliance_predicate.max_arity;
401  this->pb.clear_values();
402  this->pb.val(zero) = FieldT::zero();
403 
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();
412  }
413 
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();
421  }
422 
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();
426  }
427 
428  if (this->pb.val(incoming_message_types[0]) != FieldT::zero()) {
429  this->pb.val(verification_result) = FieldT::one();
430  }
431 
432 #ifdef DEBUG
433  generate_r1cs_constraints(); // force generating constraints
434  assert(this->pb.is_satisfied());
435 #endif
436 }
437 
438 template<typename ppT>
439 size_t sp_compliance_step_pcd_circuit_maker<ppT>::field_logsize()
440 {
441  return libff::Fr<ppT>::size_in_bits();
442 }
443 
444 template<typename ppT>
445 size_t sp_compliance_step_pcd_circuit_maker<ppT>::field_capacity()
446 {
447  return libff::Fr<ppT>::capacity();
448 }
449 
450 template<typename ppT>
451 size_t sp_compliance_step_pcd_circuit_maker<ppT>::input_size_in_elts()
452 {
453  const size_t digest_size =
454  CRH_with_field_out_gadget<FieldT>::get_digest_len();
455  return digest_size;
456 }
457 
458 template<typename ppT>
459 size_t sp_compliance_step_pcd_circuit_maker<ppT>::input_capacity_in_bits()
460 {
461  return input_size_in_elts() * field_capacity();
462 }
463 
464 template<typename ppT>
465 size_t sp_compliance_step_pcd_circuit_maker<ppT>::input_size_in_bits()
466 {
467  return input_size_in_elts() * field_logsize();
468 }
469 
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)
475 {
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");
479 
480  /* unpack translation step PCD circuit input */
481  unpacked_sp_translation_step_pcd_circuit_input.allocate(
482  pb,
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>(
488  pb,
489  unpacked_sp_translation_step_pcd_circuit_input,
490  sp_translation_step_pcd_circuit_input,
491  field_capacity(),
492  "unpack_sp_translation_step_pcd_circuit_input"));
493 
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"));
499 
500  /* verify previous proof */
501  online_verifier.reset(new r1cs_ppzksnark_online_verifier_gadget<ppT>(
502  pb,
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(),
506  *proof,
507  ONE, // must always accept
508  "verifier"));
509  pb.set_input_sizes(input_size_in_elts());
510 
511  printf("done translation\n");
512 }
513 
514 template<typename ppT>
515 void sp_translation_step_pcd_circuit_maker<ppT>::generate_r1cs_constraints()
516 {
517  PROFILE_CONSTRAINTS(pb, "repacking: unpack circuit input")
518  {
519  unpack_sp_translation_step_pcd_circuit_input->generate_r1cs_constraints(
520  true);
521  }
522 
523  PROFILE_CONSTRAINTS(pb, "verifier for compliance proofs")
524  {
525  PROFILE_CONSTRAINTS(pb, "check that proof lies on the curve")
526  {
527  proof->generate_r1cs_constraints();
528  }
529 
530  online_verifier->generate_r1cs_constraints();
531  }
532 
533  PRINT_CONSTRAINT_PROFILING();
534  libff::print_indent();
535  printf(
536  "* Number of constraints in sp_translation_step_pcd_circuit: %zu\n",
537  pb.num_constraints());
538 }
539 
540 template<typename ppT>
541 r1cs_constraint_system<libff::Fr<ppT>> sp_translation_step_pcd_circuit_maker<
542  ppT>::get_circuit() const
543 {
544  return pb.get_constraint_system();
545 }
546 
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)
551 {
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();
557 
558  proof->generate_r1cs_witness(compliance_step_proof);
559  online_verifier->generate_r1cs_witness();
560 
561 #ifdef DEBUG
562  generate_r1cs_constraints(); // force generating constraints
563 
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();
567  }
568 
569  assert(this->pb.is_satisfied());
570 #endif
571 }
572 
573 template<typename ppT>
574 r1cs_primary_input<libff::Fr<ppT>> sp_translation_step_pcd_circuit_maker<
575  ppT>::get_primary_input() const
576 {
577  return pb.primary_input();
578 }
579 
580 template<typename ppT>
581 r1cs_auxiliary_input<libff::Fr<ppT>> sp_translation_step_pcd_circuit_maker<
582  ppT>::get_auxiliary_input() const
583 {
584  return pb.auxiliary_input();
585 }
586 
587 template<typename ppT>
588 size_t sp_translation_step_pcd_circuit_maker<ppT>::field_logsize()
589 {
590  return libff::Fr<ppT>::size_in_bits();
591 }
592 
593 template<typename ppT>
594 size_t sp_translation_step_pcd_circuit_maker<ppT>::field_capacity()
595 {
596  return libff::Fr<ppT>::capacity();
597 }
598 
599 template<typename ppT>
600 size_t sp_translation_step_pcd_circuit_maker<ppT>::input_size_in_elts()
601 {
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());
606 }
607 
608 template<typename ppT>
609 size_t sp_translation_step_pcd_circuit_maker<ppT>::input_capacity_in_bits()
610 {
611  return input_size_in_elts() * field_capacity();
612 }
613 
614 template<typename ppT>
615 size_t sp_translation_step_pcd_circuit_maker<ppT>::input_size_in_bits()
616 {
617  return input_size_in_elts() * field_logsize();
618 }
619 
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>>
624  &primary_input)
625 {
626  libff::enter_block("Call to get_sp_compliance_step_pcd_circuit_input");
627  typedef libff::Fr<ppT> FieldT;
628 
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());
636  }
637 
638  libff::bit_vector block;
639  block.insert(
640  block.end(),
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());
644 
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");
648 
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");
652 
653  return digest;
654 }
655 
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)
661 {
662  libff::enter_block("Call to get_sp_translation_step_pcd_circuit_input");
663  typedef libff::Fr<ppT> FieldT;
664 
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(),
677  elt_bits.begin(),
678  elt_bits.end());
679  }
680 
681  sp_compliance_step_pcd_circuit_input_bits.resize(
682  sp_translation_step_pcd_circuit_maker<ppT>::input_capacity_in_bits(),
683  false);
684 
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");
690 
691  return result;
692 }
693 
694 } // namespace libsnark
695 
696 #endif // SP_PCD_CIRCUITS_TCC_