1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
3 // SPDX-License-Identifier: LGPL-3.0+
5 #ifndef __ZETH_CIRCUITS_CIRCUIT_WRAPPER_TCC__
6 #define __ZETH_CIRCUITS_CIRCUIT_WRAPPER_TCC__
8 #include "libzeth/circuits/circuit_wrapper.hpp"
28 TreeDepth>::circuit_wrapper()
30 // Allocate a single public variable to hold the hash of the public
31 // joinsplit inputs. The public joinsplit inputs are then allocated
32 // immediately following this.
33 public_data_hash.allocate(pb, "public_data_hash");
34 pb.set_input_sizes(1);
36 // Joinsplit gadget internally allocates its public data first.
37 // TODO: joinsplit_gadget should be refactored to be properly composable.
38 joinsplit = std::make_shared<joinsplit_type>(pb);
39 const size_t num_public_elements = joinsplit->get_num_public_elements();
41 // Populate public_data to represent the joinsplit public data. Skip
42 // the first 2 variables (the constant 1, and the digest of the
43 // public_data), and use the num_public_elements variables that follow.
44 public_data.reserve(num_public_elements);
45 for (size_t i = 0; i < num_public_elements; ++i) {
46 public_data.emplace_back(i + 2);
48 assert(public_data.size() == num_public_elements);
50 // Initialize the input hasher gadget
51 input_hasher = std::make_shared<input_hasher_type>(
52 pb, public_data, public_data_hash, "input_hasher");
54 // Generate constraints
55 joinsplit->generate_r1cs_constraints();
56 input_hasher->generate_r1cs_constraints();
67 typename snarkT::keypair circuit_wrapper<
74 TreeDepth>::generate_trusted_setup() const
76 // Generate a verification and proving key (trusted setup) and write them
78 return snarkT::generate_setup(pb);
89 const libsnark::r1cs_constraint_system<libff::Fr<ppT>> &circuit_wrapper<
96 TreeDepth>::get_constraint_system() const
98 return pb.get_constraint_system();
109 extended_proof<ppT, snarkT> circuit_wrapper<
119 const std::array<joinsplit_input<Field, TreeDepth>, NumInputs> &inputs,
120 const std::array<zeth_note, NumOutputs> &outputs,
121 const bits64 &vpub_in,
122 const bits64 &vpub_out,
123 const bits256 &h_sig_in,
124 const bits256 &phi_in,
125 const typename snarkT::proving_key &proving_key,
126 std::vector<Field> &out_public_data) const
128 // left hand side and right hand side of the joinsplit
129 bits64 lhs_value = vpub_in;
130 bits64 rhs_value = vpub_out;
132 // Compute the sum on the left hand side of the joinsplit
133 for (size_t i = 0; i < NumInputs; i++) {
134 lhs_value = bits_add<ZETH_V_SIZE>(lhs_value, inputs[i].note.value);
137 // Compute the sum on the right hand side of the joinsplit
138 for (size_t i = 0; i < NumOutputs; i++) {
139 rhs_value = bits_add<ZETH_V_SIZE>(rhs_value, outputs[i].value);
142 // [CHECK] Make sure that the balance between rhs and lfh is respected
143 // Used to stop any proof computation that would inevitably fail
144 // due to a violation of the constraint:
145 // `1 * left_value = right_value` in the JoinSplit circuit
146 if (lhs_value != rhs_value) {
147 throw std::invalid_argument("invalid joinsplit balance");
150 joinsplit->generate_r1cs_witness(
151 root, inputs, outputs, vpub_in, vpub_out, h_sig_in, phi_in);
152 input_hasher->generate_r1cs_witness();
154 bool is_valid_witness = pb.is_satisfied();
155 std::cout << "******* [DEBUG] Satisfiability result: " << is_valid_witness
156 << " *******" << std::endl;
158 // Fill out the public data vector
159 const size_t num_public_elements =
160 joinsplit_type::get_num_public_elements();
161 out_public_data.resize(0);
162 out_public_data.reserve(num_public_elements);
163 for (size_t i = 0; i < num_public_elements; ++i) {
164 out_public_data.push_back(pb.val(public_data[i]));
167 // Instantiate an extended_proof from the proof we generated and the given
169 return extended_proof<ppT, snarkT>(
170 snarkT::generate_proof(proving_key, pb), pb.primary_input());
181 const std::vector<libff::Fr<ppT>> &circuit_wrapper<
188 TreeDepth>::get_last_assignment() const
190 return pb.full_variable_assignment();
193 } // namespace libzeth
195 #endif // __ZETH_CIRCUITS_CIRCUIT_WRAPPER_TCC__