Zecale - Reconciling Privacy and Scalability on Smart-Contract Chains  0.5
Reference implementation of the Zecale protocol by Clearmatics
aggregator_gadget.tcc
Go to the documentation of this file.
1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
2 //
3 // SPDX-License-Identifier: LGPL-3.0+
4 
5 #ifndef __ZECALE_CIRCUITS_AGGREGATOR_GADGET_TCC__
6 #define __ZECALE_CIRCUITS_AGGREGATOR_GADGET_TCC__
7 
8 #include "libzecale/circuits/aggregator_gadget.hpp"
9 
10 namespace libzecale
11 {
12 
13 template<typename wppT, typename nverifierT, size_t NumProofs>
14 aggregator_gadget<wppT, nverifierT, NumProofs>::aggregator_gadget(
15  libsnark::protoboard<libff::Fr<wppT>> &pb,
16  const verification_key_variable_gadget &vk,
17  const std::array<libsnark::pb_variable_array<libff::Fr<wppT>>, NumProofs>
18  &inputs,
19  const std::array<std::shared_ptr<proof_variable_gadget>, NumProofs> &proofs,
20  const std::array<libsnark::pb_variable<libff::Fr<wppT>>, NumProofs>
21  &proof_results,
22  const std::string &annotation_prefix)
23  : libsnark::gadget<libff::Fr<wppT>>(pb, annotation_prefix)
24  , num_inputs_per_nested_proof(vk.num_primary_inputs())
25  , processed_vk()
26  , nested_primary_inputs(inputs)
27  , vk_processor(
28  pb, vk, processed_vk, FMT(annotation_prefix, " vk_processor"))
29 {
30  // Assert that a single input of a nested proof (element of
31  // libff::Fr<nppT>) can be encoded in a single input of the wrapping proof
32  // (element of libff::Fr<wppT>). This holds for all pairing chains we test,
33  // but if it fails then nested inputs will need to be encoded over multiple
34  // wrapper inputs. Unfortunately this check cannot be made statically.
35  //
36  // TODO: if num_bits are equal then also check that `libff::Fr<nppT>::mod`
37  // <= `libff::Fr<wppT>::num_bits`.
38  assert(libff::Fr<npp>::num_bits <= libff::Fr<wppT>::num_bits);
39 
40  // Allocate the bit representation of the public inputs and initialize the
41  // input packers.
42  const size_t num_bits_per_input = libff::Fr<npp>::size_in_bits();
43  const size_t num_input_bits_per_nested_proof =
44  num_inputs_per_nested_proof * num_bits_per_input;
45  for (size_t i = 0; i < NumProofs; i++) {
46  nested_primary_inputs_bits[i].allocate(
47  pb,
48  num_input_bits_per_nested_proof,
49  FMT(this->annotation_prefix,
50  " nested_primary_inputs_bits[%zu]",
51  i));
52 
53  nested_primary_input_packers.emplace_back(new input_packing_gadget(
54  pb,
55  nested_primary_inputs_bits[i],
56  inputs[i],
57  num_bits_per_input,
58  FMT(annotation_prefix, " nested_input_packers[%zu]", i)));
59  }
60 
61  // Initialize the verifier gadgets
62  for (size_t i = 0; i < NumProofs; i++) {
63  verifiers[i].reset(new online_verifier_gadget(
64  pb,
65  processed_vk,
66  nested_primary_inputs_bits[i],
67  libff::Fr<npp>::size_in_bits(),
68  *proofs[i],
69  proof_results[i],
70  FMT(this->annotation_prefix, " verifiers[%zu]", i)));
71  }
72 }
73 
74 template<typename wppT, typename nverifierT, size_t NumProofs>
75 void aggregator_gadget<wppT, nverifierT, NumProofs>::generate_r1cs_constraints()
76 {
77  vk_processor.generate_r1cs_constraints();
78 
79  // Generate constraints (including boolean-ness of the bit representations)
80  // for input packers, nested proofs and the proof verifiers.
81  for (size_t i = 0; i < NumProofs; i++) {
82  nested_primary_input_packers[i]->generate_r1cs_constraints(true);
83  verifiers[i]->generate_r1cs_constraints();
84  }
85 }
86 
87 template<typename wppT, typename nverifierT, size_t NumProofs>
88 void aggregator_gadget<wppT, nverifierT, NumProofs>::generate_r1cs_witness(
89  const std::array<
90  const libsnark::r1cs_primary_input<libff::Fr<npp>> *,
91  NumProofs> &nested_inputs)
92 {
93  vk_processor.generate_r1cs_witness();
94 
95  for (size_t i = 0; i < NumProofs; i++) {
96  // Witness the nested_primary_inputs. This is done by input values are
97  // of type libff::Fr<nppT>. They are converted to bit arrays to
98  // populate `nested_primary_inputs_bits`, and the
99  // `nested_primary_input_packers` are used to convert to variables of
100  // the circuit (elements of libff::Fr<wppT>).
101  const libsnark::r1cs_primary_input<libff::Fr<npp>>
102  &other_curve_primary_inputs = *(nested_inputs[i]);
103  const libff::bit_vector input_bits =
104  libff::convert_field_element_vector_to_bit_vector<libff::Fr<npp>>(
105  other_curve_primary_inputs);
106  nested_primary_inputs_bits[i].fill_with_bits(this->pb, input_bits);
107  nested_primary_input_packers[i]->generate_r1cs_witness_from_bits();
108 
109  // Witness the verifiers
110  verifiers[i]->generate_r1cs_witness();
111  }
112 }
113 
114 } // namespace libzecale
115 
116 #endif // __ZECALE_CIRCUITS_AGGREGATOR_GADGET_TCC__