1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
3 // SPDX-License-Identifier: LGPL-3.0+
5 #ifndef __ZECALE_CORE_AGGREGATOR_CIRCUIT_TCC__
6 #define __ZECALE_CORE_AGGREGATOR_CIRCUIT_TCC__
8 #include "libzecale/circuits/aggregator_circuit.hpp"
10 #include <libzeth/zeth_constants.hpp>
12 using namespace libzeth;
17 template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
18 aggregator_circuit<wppT, wsnarkT, nverifierT, NumProofs>::aggregator_circuit(
19 const size_t inputs_per_nested_proof)
20 : _num_inputs_per_nested_proof(inputs_per_nested_proof), _pb()
22 // The order of allocation here is important as it determines which inputs
25 // Input for hash of nested verification key.
26 _nested_vk_hash.allocate(_pb, FMT("", "_nested_vk_hash"));
28 // Packed results (populated by the packer)
29 _nested_proof_results.allocate(_pb, FMT("", "_nested_proof_results"));
31 // Allocate nested primary inputs (populated by aggregator).
32 for (size_t i = 0; i < NumProofs; i++) {
33 _nested_primary_inputs[i].allocate(
35 _num_inputs_per_nested_proof,
36 FMT("", "_nested_primary_inputs_bits[%zu]", i));
39 // Set the number of primary inputs.
40 const size_t total_primary_inputs = num_primary_inputs();
41 _pb.set_input_sizes(total_primary_inputs);
43 // Allocate the unpacked nested proof verification results (populated by
44 // aggregator, consumed by results packer.
45 for (size_t i = 0; i < NumProofs; i++) {
46 _nested_proof_results_unpacked[i].allocate(
47 _pb, FMT("", "_nested_proof_results[%zu]", i));
50 // Allocate vk and the intermediate bit representation
51 _nested_vk.reset(new verification_key_variable_gadget(
52 _pb, _num_inputs_per_nested_proof, "_nested_vk"));
54 // Allocate proof variables.
55 for (size_t i = 0; i < NumProofs; i++) {
56 _nested_proofs[i].reset(
57 new proof_variable_gadget(_pb, FMT("", "_nested_proofs[%zu]", i)));
60 // Nested verification key hash gadget
61 _nested_vk_hash_gadget.reset(
62 new verification_key_hash_gadget<wppT, nverifierT>(
66 FMT("", "_nested_vk_hash_gadget")));
69 _aggregator_gadget.reset(new aggregator_gadget<wppT, nverifierT, NumProofs>(
72 _nested_primary_inputs,
74 _nested_proof_results_unpacked,
75 "_aggregator_gadget"));
77 // Results packer gadgets
78 libsnark::pb_linear_combination_array<libff::Fr<wppT>>
79 unpacked_results_array(NumProofs);
80 for (size_t i = 0; i < NumProofs; ++i) {
81 unpacked_results_array[i] = _nested_proof_results_unpacked[i];
84 _nested_proof_results_packer.reset(
85 new libsnark::packing_gadget<libff::Fr<wppT>>(
87 unpacked_results_array,
88 _nested_proof_results,
89 "_nested_proof_results_packer"));
91 // Initialize all constraints in the circuit.
92 for (size_t i = 0; i < NumProofs; ++i) {
93 _nested_proofs[i]->generate_r1cs_constraints();
95 _nested_vk_hash_gadget->generate_r1cs_constraints();
96 _aggregator_gadget->generate_r1cs_constraints();
97 _nested_proof_results_packer->generate_r1cs_constraints(false);
100 template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
101 typename wsnarkT::keypair aggregator_circuit<
105 NumProofs>::generate_trusted_setup() const
107 // Generate a verification and proving key (trusted setup)
108 return wsnarkT::generate_setup(_pb);
111 template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
112 const libsnark::r1cs_constraint_system<libff::Fr<wppT>>
113 &aggregator_circuit<wppT, wsnarkT, nverifierT, NumProofs>::
114 get_constraint_system() const
116 return _pb.get_constraint_system();
119 template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
120 libzeth::extended_proof<wppT, wsnarkT> aggregator_circuit<
126 const typename nsnark::verification_key &nested_vk,
128 const libzeth::extended_proof<npp, nsnark> *,
129 NumProofs> &extended_proofs,
130 const typename wsnarkT::proving_key &aggregator_proving_key)
132 // Witness the proofs and construct the array of primary inputs (in npp).
133 // These will be used to populate _nested_primary_inputs.
134 std::array<const libsnark::r1cs_primary_input<libff::Fr<npp>> *, NumProofs>
136 for (size_t i = 0; i < NumProofs; ++i) {
137 const libzeth::extended_proof<npp, nsnark> &ep = *(extended_proofs[i]);
138 if (ep.get_primary_inputs().size() != _num_inputs_per_nested_proof) {
139 throw std::runtime_error(
140 "attempt to aggregate proof with invalid number of inputs");
143 nested_inputs[i] = &ep.get_primary_inputs();
144 _nested_proofs[i]->generate_r1cs_witness(ep.get_proof());
147 // Witness the verification key
148 _nested_vk->generate_r1cs_witness(nested_vk);
150 // Witness hash of verification keypair
151 _nested_vk_hash_gadget->generate_r1cs_witness();
153 // Pass the input values (in npp) to the aggregator gadget.
154 _aggregator_gadget->generate_r1cs_witness(nested_inputs);
156 // Witness the packed results
157 _nested_proof_results_packer->generate_r1cs_witness_from_bits();
160 // Check the validity of the circuit.
161 bool is_valid_witness = _pb.is_satisfied();
162 std::cout << "*** [DEBUG] Satisfiability result: " << is_valid_witness
163 << " ***" << std::endl;
166 // Return an extended_proof for the given witness.
167 return extended_proof<wppT, wsnarkT>(
168 wsnarkT::generate_proof(aggregator_proving_key, _pb),
169 _pb.primary_input());
172 template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
173 size_t aggregator_circuit<wppT, wsnarkT, nverifierT, NumProofs>::
174 num_primary_inputs() const
176 // Compute the total number of primary inputs for a circuit of this type,
177 // including leading vk_hash, results and nested primary inputs (see
178 // aggregator_circuit.hpp for full layout).
179 return 1 + 1 + NumProofs * _num_inputs_per_nested_proof;
182 } // namespace libzecale
184 #endif // __ZECALE_CORE_AGGREGATOR_CIRCUIT_TCC__