2 *****************************************************************************
4 Implementation of interfaces for the Zerocash Pour gadget.
6 See zerocash_pour_gadget.hpp .
8 *****************************************************************************
9 * @author This file is part of libzerocash, developed by the Zerocash
10 * project and contributors (see AUTHORS).
11 * @copyright MIT license (see LICENSE file)
12 *****************************************************************************/
14 #include "algebra/fields/field_utils.hpp"
16 namespace libzerocash {
18 template<typename FieldT>
19 zerocash_pour_gadget<FieldT>::zerocash_pour_gadget(protoboard<FieldT> &pb,
20 const size_t num_old_coins,
21 const size_t num_new_coins,
22 const size_t tree_depth,
23 const std::string &annotation_prefix) :
24 gadget<FieldT>(pb, FMT(annotation_prefix, " zerocash_pour_gadget")),
25 tree_depth(tree_depth),
26 num_old_coins(num_old_coins),
27 num_new_coins(num_new_coins)
29 /* allocate packed inputs */
30 const size_t input_size_in_bits = sha256_digest_len + num_old_coins*sha256_digest_len + num_new_coins*sha256_digest_len + (coin_value_length * 2) + (num_old_coins + 1) * sha256_digest_len;
31 const size_t input_size_in_field_elements = div_ceil(input_size_in_bits, FieldT::capacity());
32 input_as_field_elements.allocate(pb, input_size_in_field_elements, FMT(annotation_prefix, " input_as_field_elements"));
33 this->pb.set_input_sizes(input_size_in_field_elements);
36 merkle_tree_root_variable.reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " merkle_tree_root_variable")));
38 old_coin_enforce_commitment.allocate(pb, num_old_coins, FMT(annotation_prefix, " old_coin_enforce_commitment"));
39 old_coin_serial_number_variables.resize(num_old_coins);
40 for (size_t i = 0; i < num_old_coins; ++i)
42 old_coin_serial_number_variables[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " old_coin_serial_number_variables_%zu", i)));
45 new_coin_commitment_variables.resize(num_new_coins);
46 for (size_t i = 0; i < num_new_coins; ++i)
48 new_coin_commitment_variables[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " new_coin_commitment_variables_%zu", i)));
51 public_old_value_variable.allocate(pb, coin_value_length, FMT(annotation_prefix, " public_old_value_variable"));
52 public_new_value_variable.allocate(pb, coin_value_length, FMT(annotation_prefix, " public_new_value_variable"));
53 signature_public_key_hash_variable.reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " signature_public_key_hash")));
55 mac_of_signature_public_key_hash_variables.resize(num_old_coins);
56 for (size_t i = 0; i < num_old_coins; ++i)
58 mac_of_signature_public_key_hash_variables[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " mac_of_signature_public_key_hash_variables_%zu", i)));
61 /* do the multipacking */
62 input_as_bits.insert(input_as_bits.end(), merkle_tree_root_variable->bits.begin(), merkle_tree_root_variable->bits.end());
63 for (size_t i = 0; i < num_old_coins; ++i)
65 input_as_bits.insert(input_as_bits.end(), old_coin_serial_number_variables[i]->bits.begin(), old_coin_serial_number_variables[i]->bits.end());
67 for (size_t i = 0; i < num_new_coins; ++i)
69 input_as_bits.insert(input_as_bits.end(), new_coin_commitment_variables[i]->bits.begin(), new_coin_commitment_variables[i]->bits.end());
71 input_as_bits.insert(input_as_bits.end(), public_old_value_variable.begin(), public_old_value_variable.end());
72 input_as_bits.insert(input_as_bits.end(), public_new_value_variable.begin(), public_new_value_variable.end());
73 input_as_bits.insert(input_as_bits.end(), signature_public_key_hash_variable->bits.begin(), signature_public_key_hash_variable->bits.end());
74 for (size_t i = 0; i < num_old_coins; ++i)
76 input_as_bits.insert(input_as_bits.end(), mac_of_signature_public_key_hash_variables[i]->bits.begin(), mac_of_signature_public_key_hash_variables[i]->bits.end());
78 assert(input_as_bits.size() == input_size_in_bits);
79 unpack_inputs.reset(new multipacking_gadget<FieldT>(this->pb, input_as_bits, input_as_field_elements, FieldT::capacity(), FMT(this->annotation_prefix, " unpack_inputs")));
81 pb_linear_combination_array<FieldT> IV = SHA256_default_IV(pb);
82 zero.allocate(this->pb, FMT(this->annotation_prefix, " zero")); /* TODO */
84 /* allocate witness */
85 new_address_public_key_variables.resize(num_new_coins);
86 new_address_commitment_nonce_variables.resize(num_new_coins);
87 new_coin_serial_number_nonce_variables.resize(num_new_coins);
88 new_coin_value_variables.resize(num_new_coins);
89 for (size_t i = 0; i < num_new_coins; ++i)
91 new_address_public_key_variables[i].allocate(pb, address_public_key_length, FMT(annotation_prefix, " new_address_public_key_variables_%zu", i));
92 new_address_commitment_nonce_variables[i].allocate(pb, address_commitment_nonce_length, FMT(annotation_prefix, " new_address_commitment_nonce_variables_%zu", i));
93 new_coin_serial_number_nonce_variables[i].allocate(pb, serial_number_nonce_length, FMT(annotation_prefix, " new_coin_serial_number_nonce_variables_%zu", i));
94 new_coin_value_variables[i].allocate(pb, coin_value_length, FMT(annotation_prefix, " new_coin_value_variables_%zu", i));
97 old_address_secret_key_variables.resize(num_old_coins);
98 old_address_commitment_nonce_variables.resize(num_old_coins);
99 old_coin_serial_number_nonce_variables.resize(num_old_coins);
100 old_coin_value_variables.resize(num_old_coins);
101 for (size_t i = 0; i < num_old_coins; ++i)
103 old_address_secret_key_variables[i].allocate(pb, address_secret_key_length, FMT(annotation_prefix, " old_address_secret_key_variables_%zu", i));
104 old_address_commitment_nonce_variables[i].allocate(pb, address_commitment_nonce_length, FMT(annotation_prefix, " old_address_commitment_nonce_variables_%zu", i));
105 old_coin_serial_number_nonce_variables[i].allocate(pb, serial_number_nonce_length, FMT(annotation_prefix, " old_coin_serial_number_nonce_variables_%zu", i));
106 old_coin_value_variables[i].allocate(pb, coin_value_length, FMT(annotation_prefix, " old_coin_value_variables_%zu", i));
109 /* do the actual hashing */
110 pb_variable_array<FieldT> zero_one;
111 zero_one.emplace_back(zero);
112 zero_one.emplace_back(ONE);
114 prf_for_old_coin_serial_number_input_variables.resize(num_old_coins);
115 prfs_for_old_coin_serial_numbers.resize(num_old_coins);
116 for (size_t i = 0; i < num_old_coins; ++i)
118 /* (C) old_coin_serial_number_variables[i] = PRF_{old_address_secret_key_variables[i]}^{sn}
119 (old_coin_serial_number_nonce_variables[0..254]) =
120 H(old_address_secret_key_variables[i] || 01 || old_coin_serial_number_nonce_variables[0..254]) */
121 prf_for_old_coin_serial_number_input_variables[i].reset(new block_variable<FieldT>(pb, {
122 old_address_secret_key_variables[i],
124 pb_variable_array<FieldT>(old_coin_serial_number_nonce_variables[i].begin(),
125 old_coin_serial_number_nonce_variables[i].begin() + truncated_serial_number_length) },
126 FMT(annotation_prefix, " prf_for_old_coin_serial_number_input_variables_%zu", i)));
127 prfs_for_old_coin_serial_numbers[i].reset(new sha256_compression_function_gadget<FieldT>(pb, IV, prf_for_old_coin_serial_number_input_variables[i]->bits, *old_coin_serial_number_variables[i], FMT(annotation_prefix, " prfs_for_old_coin_serial_numbers_%zu", i)));
130 old_address_public_key_variables.resize(num_old_coins);
131 prf_for_old_address_public_key_input_variables.resize(num_old_coins);
132 prfs_for_old_address_public_keys.resize(num_old_coins);
134 for (size_t i = 0; i < num_old_coins; ++i)
136 old_address_public_key_variables[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " old_address_public_key_variables_%zu", i)));
138 /* (B) old_address_public_keys[i] = PRF_{old_address_secret_key_variables[i]}^{addr}(z) =
139 H(old_address_secret_key_variables[i] || 00 || z), where z = 0...0 */
140 pb_variable_array<FieldT> addr_pk_pad(address_public_key_padding_length, zero);
141 prf_for_old_address_public_key_input_variables[i].reset(new block_variable<FieldT>(pb,
142 { old_address_secret_key_variables[i], addr_pk_pad },
143 FMT(annotation_prefix, " prf_for_old_address_public_key_input_variables_%zu", i)));
144 prfs_for_old_address_public_keys[i].reset(new sha256_compression_function_gadget<FieldT>(pb,
146 prf_for_old_address_public_key_input_variables[i]->bits,
147 *old_address_public_key_variables[i],
148 FMT(annotation_prefix, " prfs_for_old_address_public_keys_%zu", i)));
151 commitments_to_old_address_public_keys.resize(num_old_coins);
152 commit_to_old_address_public_key_input_variables.resize(num_old_coins);
153 commit_to_old_address_public_keys.resize(num_old_coins);
155 for (size_t i = 0; i < num_old_coins; ++i)
157 /* (D0) commitments_to_old_address_public_keys[i] = H(old_address_public_key_variables[i] || old_coin_serial_number_nonce_variables[i]) */
158 commitments_to_old_address_public_keys[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " commitments_to_old_address_public_keys_%zu", i)));
159 commit_to_old_address_public_key_input_variables[i].reset(new block_variable<FieldT>(pb, { old_address_public_key_variables[i]->bits, old_coin_serial_number_nonce_variables[i] }, FMT(annotation_prefix, " commit_to_old_address_public_key_input_variables_%zu", i)));
160 commit_to_old_address_public_keys[i].reset(new sha256_compression_function_gadget<FieldT>(pb, IV, commit_to_old_address_public_key_input_variables[i]->bits, *commitments_to_old_address_public_keys[i], FMT(annotation_prefix, " commit_to_old_address_public_keys_%zu", i)));
163 old_coin_value_commitment_nonces.resize(num_old_coins);
164 commit_to_old_coin_value_commitment_nonce_input_variables.resize(num_old_coins);
165 commit_to_old_coin_value_commitment_nonces.resize(num_old_coins);
167 for (size_t i = 0; i < num_old_coins; ++i)
169 /* (D1) old_coin_value_commitment_nonces[i] =
170 H(old_address_commitment_nonce_variables[i] || commitments_to_old_address_public_keys[i] [0..128]) */
171 old_coin_value_commitment_nonces[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " old_coin_value_commitment_nonces_%zu", i)));
172 commit_to_old_coin_value_commitment_nonce_input_variables[i].reset(new block_variable<FieldT>(pb, { old_address_commitment_nonce_variables[i], pb_variable_array<FieldT>(commitments_to_old_address_public_keys[i]->bits.begin(), commitments_to_old_address_public_keys[i]->bits.begin()+ truncated_coin_commitment_length) }, FMT(annotation_prefix, " commit_to_old_coin_value_commitment_nonce_input_variables_%zu", i)));
173 commit_to_old_coin_value_commitment_nonces[i].reset(new sha256_compression_function_gadget<FieldT>(pb, IV, commit_to_old_coin_value_commitment_nonce_input_variables[i]->bits, *old_coin_value_commitment_nonces[i], FMT(annotation_prefix, " commit_to_old_coin_value_commitment_nonces_%zu", i)));
176 pb_variable_array<FieldT> coincomm_pad(coin_commitment_padding_length, zero);
177 old_coin_commitment_variables.resize(num_old_coins);
178 compute_old_coin_commitment_input_variables.resize(num_old_coins);
179 compute_old_coin_commitments.resize(num_old_coins);
181 for (size_t i = 0; i < num_old_coins; ++i)
183 /* (D2) old_coin_commitment_variables[i] = COMM_s(old_coin_value_variables[i] || old_coin_value_commitment_nonces[i])
184 H(old_coin_value_commitment_nonces[i] || 0^{192} || old_coin_value_variables[i])
186 Here we ignore commitment randomness s, as k = old_coin_value_commitment_nonces[i] is an output of a
187 statistically hiding commitment scheme. */
188 old_coin_commitment_variables[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " old_coin_commitment_variables_%zu", i)));
189 compute_old_coin_commitment_input_variables[i].reset(new block_variable<FieldT>(pb, { old_coin_value_commitment_nonces[i]->bits, coincomm_pad, old_coin_value_variables[i] }, FMT(annotation_prefix, " compute_old_coin_commitment_input_variables_%zu", i)));
190 compute_old_coin_commitments[i].reset(new sha256_compression_function_gadget<FieldT>(pb, IV, compute_old_coin_commitment_input_variables[i]->bits, *old_coin_commitment_variables[i], FMT(annotation_prefix, " compute_old_coin_commitment_%zu", i)));
193 commitments_to_new_address_public_keys.resize(num_new_coins);
194 commit_to_new_address_public_key_input_variables.resize(num_new_coins);
195 commit_to_new_address_public_keys.resize(num_new_coins);
197 for (size_t i = 0; i < num_new_coins; ++i)
199 /* (E0) commitments_to_new_address_public_keys[i] = H(new_address_public_key_variables[i] || new_coin_serial_number_nonce_variables[i]) */
200 commitments_to_new_address_public_keys[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " commitments_to_new_address_public_keys_%zu", i)));
201 commit_to_new_address_public_key_input_variables[i].reset(new block_variable<FieldT>(pb, { new_address_public_key_variables[i], new_coin_serial_number_nonce_variables[i] }, FMT(annotation_prefix, " commit_to_new_address_public_key_input_variables_%zu", i)));
202 commit_to_new_address_public_keys[i].reset(new sha256_compression_function_gadget<FieldT>(pb, IV, commit_to_new_address_public_key_input_variables[i]->bits, *commitments_to_new_address_public_keys[i], FMT(annotation_prefix, " commit_to_new_address_public_keys_%zu", i)));
205 new_coin_value_commitment_nonces.resize(num_new_coins);
206 commit_to_new_coin_value_commitment_nonce_input_variables.resize(num_new_coins);
207 commit_to_new_coin_value_commitment_nonces.resize(num_new_coins);
208 for (size_t i = 0; i < num_new_coins; ++i)
210 /* (E1) new_coin_value_commitment_nonces[i] =
211 H(new_address_commitment_nonce_variables[i] || commitments_to_new_address_public_keys[i] [0..128]) */
212 new_coin_value_commitment_nonces[i].reset(new digest_variable<FieldT>(pb, sha256_digest_len, FMT(annotation_prefix, " new_coin_value_commitment_nonces_%zu", i)));
213 commit_to_new_coin_value_commitment_nonce_input_variables[i].reset(new block_variable<FieldT>(pb, { new_address_commitment_nonce_variables[i], pb_variable_array<FieldT>(commitments_to_new_address_public_keys[i]->bits.begin(), commitments_to_new_address_public_keys[i]->bits.begin()+ truncated_coin_commitment_length) }, FMT(annotation_prefix, " commit_to_new_coin_value_commitment_nonce_input_variables_%zu", i)));
214 commit_to_new_coin_value_commitment_nonces[i].reset(new sha256_compression_function_gadget<FieldT>(pb, IV, commit_to_new_coin_value_commitment_nonce_input_variables[i]->bits, *new_coin_value_commitment_nonces[i], FMT(annotation_prefix, " commit_to_new_coin_value_commitment_nonces_%zu", i)));
217 compute_new_coin_commitment_input_variables.resize(num_new_coins);
218 compute_new_coin_commitments.resize(num_new_coins);
220 for (size_t i = 0; i < num_new_coins; ++i)
222 /* (E2) new_coin_commitment_variables[i] = COMM_s(new_coin_value_variables[i] || new_coin_value_commitment_nonces[i])
223 H(new_coin_value_commitment_nonces[i] || 0^{192} || new_coin_value_variables[i]) */
224 compute_new_coin_commitment_input_variables[i].reset(new block_variable<FieldT>(pb, { new_coin_value_commitment_nonces[i]->bits, coincomm_pad, new_coin_value_variables[i] }, FMT(annotation_prefix, " compute_new_coin_commitment_input_variables_%zu", i)));
225 compute_new_coin_commitments[i].reset(new sha256_compression_function_gadget<FieldT>(pb, IV, compute_new_coin_commitment_input_variables[i]->bits, *new_coin_commitment_variables[i], FMT(annotation_prefix, " compute_new_coin_commitment_%zu", i)));
228 /* compute signature public key macs */
229 prf_for_macs_of_signature_public_key_hash_input_variables.resize(num_old_coins);
230 prfs_for_macs_of_signature_public_key_hash.resize(num_old_coins);
231 const size_t truncated_signature_public_key_hash_length = indexed_signature_public_key_hash_length - log2(num_old_coins);
233 for (size_t i = 0; i < num_old_coins; ++i)
235 /* (F) mac_of_signature_public_key_hash_variables[i] = PRF_{old_address_secret_key_variables[i]}^{pk}
236 (i || signature_public_key_hash_variable) =
237 H(old_address_secret_key_variables[i] || 10 || i || signature_public_key_hash_variable)
239 Here signature_public_key_hash is truncated so that the entire argument fits inside SHA256 block.
240 Furthermore, the representation of i is MSB to LSB and is exactly log2(num_old_coins) bits long. */
241 pb_variable_array<FieldT> prf_padding;
242 prf_padding.emplace_back(ONE);
243 prf_padding.emplace_back(zero);
245 for (size_t j = 0; j < log2(num_old_coins); ++j)
247 prf_padding.emplace_back((i >> (log2(num_old_coins) - j - 1)) & 1 ? ONE : zero);
250 prf_for_macs_of_signature_public_key_hash_input_variables[i].reset(new block_variable<FieldT>(pb, { old_address_secret_key_variables[i], prf_padding, pb_variable_array<FieldT>(signature_public_key_hash_variable->bits.begin(), signature_public_key_hash_variable->bits.begin()+truncated_signature_public_key_hash_length) }, FMT(annotation_prefix, " prf_for_macs_of_signature_public_key_hash_input_variables_%zu", i)));
251 prfs_for_macs_of_signature_public_key_hash[i].reset(new sha256_compression_function_gadget<FieldT>(pb, IV, prf_for_macs_of_signature_public_key_hash_input_variables[i]->bits, *mac_of_signature_public_key_hash_variables[i], FMT(annotation_prefix, " prfs_for_macs_of_signature_public_key_hash_%zu", i)));
254 /* prove membership in the Merkle tree*/
255 old_coin_merkle_tree_position_variables.resize(num_old_coins);
256 old_coin_authentication_path_variables.resize(num_old_coins);
257 old_coin_commitments_in_tree.resize(num_old_coins);
258 for (size_t i = 0; i < num_old_coins; ++i)
260 /* (A) old_coin_commitment_variables[i] appears on path old_coin_authentication_paths[i]
261 to merkle_tree_root_variable */
262 old_coin_merkle_tree_position_variables[i].allocate(pb, tree_depth, FMT(annotation_prefix, " old_coin_merkle_tree_position_variables_%zu", i));
263 old_coin_authentication_path_variables[i].reset(new merkle_authentication_path_variable<FieldT, sha256_two_to_one_hash_gadget<FieldT> >(pb, tree_depth, FMT(annotation_prefix, " old_coin_authentication_path_variables_%zu", i)));
264 old_coin_commitments_in_tree[i].reset(new merkle_tree_check_read_gadget<FieldT, sha256_two_to_one_hash_gadget<FieldT> >(
265 pb, tree_depth, old_coin_merkle_tree_position_variables[i], *old_coin_commitment_variables[i], *merkle_tree_root_variable,
266 *old_coin_authentication_path_variables[i], old_coin_enforce_commitment[i], FMT(annotation_prefix, " old_coin_commitments_in_tree_%zu", i)));
270 template<typename FieldT>
271 void zerocash_pour_gadget<FieldT>::generate_r1cs_constraints()
273 generate_r1cs_equals_const_constraint<FieldT>(this->pb, zero, FieldT::zero(), FMT(this->annotation_prefix, " zero"));
275 for (size_t i = 0; i < num_old_coins; ++i)
277 prfs_for_old_coin_serial_numbers[i]->generate_r1cs_constraints();
278 prfs_for_old_address_public_keys[i]->generate_r1cs_constraints();
279 commit_to_old_address_public_keys[i]->generate_r1cs_constraints();
280 commit_to_old_coin_value_commitment_nonces[i]->generate_r1cs_constraints();
281 compute_old_coin_commitments[i]->generate_r1cs_constraints();
282 old_coin_commitments_in_tree[i]->generate_r1cs_constraints();
283 prfs_for_macs_of_signature_public_key_hash[i]->generate_r1cs_constraints();
285 for (size_t j = 0; j < tree_depth; ++j)
287 generate_boolean_r1cs_constraint<FieldT>(this->pb, old_coin_merkle_tree_position_variables[i][j], FMT(this->annotation_prefix, " old_coin_merkle_tree_position_variables_%zu_%zu", i, j));
291 for (size_t i = 0; i < num_new_coins; ++i)
293 commit_to_new_address_public_keys[i]->generate_r1cs_constraints();
294 commit_to_new_coin_value_commitment_nonces[i]->generate_r1cs_constraints();
295 compute_new_coin_commitments[i]->generate_r1cs_constraints();
298 unpack_inputs->generate_r1cs_constraints(true);
300 /* ensure bitness of all values */
301 for (size_t j = 0; j < coin_value_length; ++j)
303 for (size_t i = 0; i < num_old_coins; ++i)
305 generate_boolean_r1cs_constraint<FieldT>(this->pb, old_coin_value_variables[i][j], FMT(this->annotation_prefix, " old_coin_value_variables_%zu_%zu", i, j));
307 for (size_t i = 0; i < num_new_coins; ++i)
309 generate_boolean_r1cs_constraint<FieldT>(this->pb, new_coin_value_variables[i][j], FMT(this->annotation_prefix, " new_coin_value_variables_%zu_%zu", i, j));
313 for (size_t i = 0; i < num_old_coins; ++i)
315 generate_boolean_r1cs_constraint<FieldT>(this->pb, old_coin_enforce_commitment[i], FMT(this->annotation_prefix, " old_coin_enforce_commitment_%zu", i));
316 this->pb.add_r1cs_constraint(r1cs_constraint<FieldT>(
317 pb_packing_sum<FieldT>(pb_variable_array<FieldT>(old_coin_value_variables[i].rbegin(), old_coin_value_variables[i].rend())),
318 1 - old_coin_enforce_commitment[i],
319 0), FMT(this->annotation_prefix, " enforce_%zu", i));
322 /* check the balance equation */
323 linear_combination<FieldT> old_packed_value;
324 for (size_t i = 0; i < num_old_coins; ++i)
326 old_packed_value = old_packed_value + pb_packing_sum<FieldT>(pb_variable_array<FieldT>(old_coin_value_variables[i].rbegin(), old_coin_value_variables[i].rend()));
328 old_packed_value = old_packed_value + pb_packing_sum<FieldT>(pb_variable_array<FieldT>(public_old_value_variable.rbegin(), public_old_value_variable.rend()));
330 linear_combination<FieldT> new_packed_value;
331 for (size_t i = 0; i < num_new_coins; ++i)
333 new_packed_value = new_packed_value + pb_packing_sum<FieldT>(pb_variable_array<FieldT>(new_coin_value_variables[i].rbegin(), new_coin_value_variables[i].rend()));
335 new_packed_value = new_packed_value + pb_packing_sum<FieldT>(pb_variable_array<FieldT>(public_new_value_variable.rbegin(), public_new_value_variable.rend()));
337 this->pb.add_r1cs_constraint(r1cs_constraint<FieldT>(1, old_packed_value, new_packed_value), FMT(this->annotation_prefix, " balance"));
340 template<typename FieldT>
341 void zerocash_pour_gadget<FieldT>::generate_r1cs_witness(const std::vector<merkle_authentication_path> &old_coin_authentication_paths,
342 const std::vector<size_t> &old_coin_merkle_tree_positions,
343 const bit_vector &merkle_tree_root,
344 const std::vector<bit_vector> &new_address_public_keys,
345 const std::vector<bit_vector> &old_address_secret_keys,
346 const std::vector<bit_vector> &new_address_commitment_nonces,
347 const std::vector<bit_vector> &old_address_commitment_nonces,
348 const std::vector<bit_vector> &new_coin_serial_number_nonces,
349 const std::vector<bit_vector> &old_coin_serial_number_nonces,
350 const std::vector<bit_vector> &new_coin_values,
351 const bit_vector &public_old_value,
352 const bit_vector &public_new_value,
353 const std::vector<bit_vector> &old_coin_values,
354 const bit_vector &signature_public_key_hash)
356 /* fill in the auxiliary variables */
357 this->pb.val(zero) = FieldT::zero();
359 /* fill in the witness */
360 for (size_t i = 0; i < num_new_coins; ++i)
362 new_address_public_key_variables[i].fill_with_bits(this->pb, new_address_public_keys[i]);
363 new_address_commitment_nonce_variables[i].fill_with_bits(this->pb, new_address_commitment_nonces[i]);
366 for (size_t i = 0; i < num_old_coins; ++i)
368 old_address_secret_key_variables[i].fill_with_bits(this->pb, old_address_secret_keys[i]);
369 old_address_commitment_nonce_variables[i].fill_with_bits(this->pb, old_address_commitment_nonces[i]);
372 for (size_t i = 0; i < num_new_coins; ++i)
374 new_coin_serial_number_nonce_variables[i].fill_with_bits(this->pb, new_coin_serial_number_nonces[i]);
375 new_coin_value_variables[i].fill_with_bits(this->pb, new_coin_values[i]);
378 for (size_t i = 0; i < num_old_coins; ++i)
380 this->pb.val(old_coin_enforce_commitment[i]) = FieldT::zero();
381 old_coin_serial_number_nonce_variables[i].fill_with_bits(this->pb, old_coin_serial_number_nonces[i]);
382 old_coin_value_variables[i].fill_with_bits(this->pb, old_coin_values[i]);
384 for (size_t j = 0; j < coin_value_length; ++j)
386 if (old_coin_values[i][j]) {
387 // If any bit in the value is nonzero, the value is nonzero.
388 // Thus, the old coin must be committed in the tree.
389 this->pb.val(old_coin_enforce_commitment[i]) = FieldT::one();
395 public_old_value_variable.fill_with_bits(this->pb, public_old_value);
396 public_new_value_variable.fill_with_bits(this->pb, public_new_value);
397 signature_public_key_hash_variable->generate_r1cs_witness(signature_public_key_hash);
400 for (size_t i = 0; i < num_old_coins; ++i)
402 prfs_for_old_coin_serial_numbers[i]->generate_r1cs_witness();
403 prfs_for_old_address_public_keys[i]->generate_r1cs_witness();
404 commit_to_old_address_public_keys[i]->generate_r1cs_witness();
405 commit_to_old_coin_value_commitment_nonces[i]->generate_r1cs_witness();
406 compute_old_coin_commitments[i]->generate_r1cs_witness();
407 prfs_for_macs_of_signature_public_key_hash[i]->generate_r1cs_witness();
410 for (size_t i = 0; i < num_new_coins; ++i)
412 commit_to_new_address_public_keys[i]->generate_r1cs_witness();
413 commit_to_new_coin_value_commitment_nonces[i]->generate_r1cs_witness();
414 compute_new_coin_commitments[i]->generate_r1cs_witness();
417 /* prove the membership in the Merkle tree */
418 for (size_t i = 0; i < num_old_coins; ++i)
420 /* (A) old_coin_commitment_variables[i] appears on path old_coin_authentication_paths[i]
421 to merkle_tree_root_variable */
422 old_coin_merkle_tree_position_variables[i].fill_with_bits_of_ulong(this->pb, old_coin_merkle_tree_positions[i]);
423 old_coin_authentication_path_variables[i]->generate_r1cs_witness(old_coin_merkle_tree_positions[i], old_coin_authentication_paths[i]);
424 old_coin_commitments_in_tree[i]->generate_r1cs_witness();
428 unpack_inputs->generate_r1cs_witness_from_bits();
431 printf("input_as_field_elements according to witness map:\n");
432 for (size_t i = 0; i < input_as_field_elements.size(); ++i)
434 this->pb.val(input_as_field_elements[i]).print();
439 template<typename FieldT>
440 r1cs_primary_input<FieldT> zerocash_pour_input_map(const size_t num_old_coins,
441 const size_t num_new_coins,
442 const bit_vector &merkle_tree_root,
443 const std::vector<bit_vector> &old_coin_serial_numbers,
444 const std::vector<bit_vector> &new_coin_commitments,
445 const bit_vector &public_old_value,
446 const bit_vector &public_new_value,
447 const bit_vector &signature_public_key_hash,
448 const std::vector<bit_vector> &signature_public_key_hash_macs)
450 enter_block("Call to zerocash_pour_input_map");
451 assert(merkle_tree_root.size() == sha256_digest_len);
452 assert(old_coin_serial_numbers.size() == num_old_coins);
453 for (auto &old_coin_serial_number : old_coin_serial_numbers)
455 assert(old_coin_serial_number.size() == serial_number_length);
457 assert(new_coin_commitments.size() == num_new_coins);
458 for (auto &new_coin_commitment : new_coin_commitments)
460 assert(new_coin_commitment.size() == coin_commitment_length);
462 assert(public_old_value.size() == coin_value_length);
463 assert(public_new_value.size() == coin_value_length);
464 assert(signature_public_key_hash.size() == sha256_digest_len);
465 assert(signature_public_key_hash_macs.size() == num_old_coins);
466 for (auto &signature_public_key_hash_mac : signature_public_key_hash_macs)
468 assert(signature_public_key_hash_mac.size() == sha256_digest_len);
471 bit_vector input_as_bits;
473 input_as_bits.insert(input_as_bits.end(), merkle_tree_root.begin(), merkle_tree_root.end());
474 for (auto &old_coin_serial_number : old_coin_serial_numbers)
476 input_as_bits.insert(input_as_bits.end(), old_coin_serial_number.begin(), old_coin_serial_number.end());
478 for (auto &new_coin_commitment : new_coin_commitments)
480 input_as_bits.insert(input_as_bits.end(), new_coin_commitment.begin(), new_coin_commitment.end());
482 input_as_bits.insert(input_as_bits.end(), public_old_value.begin(), public_old_value.end());
483 input_as_bits.insert(input_as_bits.end(), public_new_value.begin(), public_new_value.end());
484 input_as_bits.insert(input_as_bits.end(), signature_public_key_hash.begin(), signature_public_key_hash.end());
485 for (auto &signature_public_key_hash_mac : signature_public_key_hash_macs)
487 input_as_bits.insert(input_as_bits.end(), signature_public_key_hash_mac.begin(), signature_public_key_hash_mac.end());
489 std::vector<FieldT> input_as_field_elements = pack_bit_vector_into_field_element_vector<FieldT>(input_as_bits);
492 printf("input_as_field_elements from zerocash_pour_input_map:\n");
493 for (size_t i = 0; i < input_as_field_elements.size(); ++i)
495 input_as_field_elements[i].print();
498 leave_block("Call to zerocash_pour_input_map");
500 return input_as_field_elements;