1use super::common::*;
2use crate::circuit::anchor::AnchorCircuit;
3use ark_crypto_primitives::Error;
4use ark_ec::PairingEngine;
5use ark_ff::{BigInteger, PrimeField};
6use ark_std::{
7 rand::{CryptoRng, Rng, RngCore},
8 rc::Rc,
9 vec::Vec,
10};
11use arkworks_gadgets::{
12 arbitrary::anchor_data::Input as AnchorDataInput,
13 leaf::anchor::{
14 constraints::AnchorLeafGadget, AnchorLeaf, Private as LeafPrivate, Public as LeafPublic,
15 },
16 merkle_tree::Path,
17};
18use arkworks_utils::{
19 poseidon::PoseidonParameters,
20 utils::common::{setup_params_x5_3, setup_params_x5_4, Curve},
21};
22
23pub type AnchorConstraintDataInput<F> = AnchorDataInput<F>;
24
25pub type Leaf_x5<F> = AnchorLeaf<F, PoseidonCRH_x5_4<F>>;
26
27pub type LeafGadget_x5<F> = AnchorLeafGadget<F, PoseidonCRH_x5_4<F>, PoseidonCRH_x5_4Gadget<F>>;
28
29pub type Circuit_x5<F, const N: usize, const M: usize> = AnchorCircuit<
30 F,
31 PoseidonCRH_x5_4<F>,
32 PoseidonCRH_x5_4Gadget<F>,
33 TreeConfig_x5<F>,
34 LeafCRHGadget<F>,
35 PoseidonCRH_x5_3Gadget<F>,
36 N,
37 M,
38>;
39
40pub type Leaf_x17<F> = AnchorLeaf<F, PoseidonCRH_x17_5<F>>;
41pub type LeafGadget_x17<F> = AnchorLeafGadget<F, PoseidonCRH_x17_5<F>, PoseidonCRH_x17_5Gadget<F>>;
42
43pub type Circuit_x17<F, const N: usize, const M: usize> = AnchorCircuit<
44 F,
45 PoseidonCRH_x17_5<F>,
46 PoseidonCRH_x17_5Gadget<F>,
47 TreeConfig_x17<F>,
48 LeafCRHGadget<F>,
49 PoseidonCRH_x17_3Gadget<F>,
50 N,
51 M,
52>;
53
54pub fn setup_leaf_x5_4<F: PrimeField, R: RngCore>(
55 curve: Curve,
56 chain_id: u128,
57 rng: &mut R,
58) -> Result<Leaf, Error> {
59 let params5 = setup_params_x5_4::<F>(curve);
60 let leaf_private = LeafPrivate::generate(rng);
62
63 let chain_id_f = F::from(chain_id);
64 let leaf_public = LeafPublic::new(chain_id_f);
65
66 let leaf_hash = Leaf_x5::create_leaf(&leaf_private, &leaf_public, ¶ms5)?;
67 let nullifier_hash = Leaf_x5::create_nullifier(&leaf_private, ¶ms5)?;
68
69 let secret_bytes = leaf_private.secret().into_repr().to_bytes_le();
70 let nullifier_bytes = leaf_private.nullifier().into_repr().to_bytes_le();
71
72 let leaf_bytes = leaf_hash.into_repr().to_bytes_le();
73 let nullifier_hash_bytes = nullifier_hash.into_repr().to_bytes_le();
74
75 Ok(Leaf {
76 secret_bytes,
77 nullifier_bytes,
78 leaf_bytes,
79 nullifier_hash_bytes,
80 })
81}
82
83pub fn setup_leaf_with_privates_raw_x5_4<F: PrimeField>(
84 curve: Curve,
85 secret_bytes: Vec<u8>,
86 nullifier_bytes: Vec<u8>,
87 chain_id: u128,
88) -> Result<Leaf, Error> {
89 let params5 = setup_params_x5_4::<F>(curve);
90
91 let secret = F::from_le_bytes_mod_order(&secret_bytes);
92 let nullifier = F::from_le_bytes_mod_order(&nullifier_bytes);
93 let leaf_private = LeafPrivate::new(secret, nullifier);
95
96 let chain_id_f = F::from(chain_id);
97 let leaf_public = LeafPublic::new(chain_id_f);
98
99 let leaf_hash = Leaf_x5::create_leaf(&leaf_private, &leaf_public, ¶ms5)?;
100 let nullifier_hash = Leaf_x5::create_nullifier(&leaf_private, ¶ms5)?;
101
102 let leaf_bytes = leaf_hash.into_repr().to_bytes_le();
103 let nullifier_hash_bytes = nullifier_hash.into_repr().to_bytes_le();
104
105 Ok(Leaf {
106 secret_bytes,
107 nullifier_bytes,
108 leaf_bytes,
109 nullifier_hash_bytes,
110 })
111}
112
113pub const N: usize = 30;
114pub const M: usize = 2;
115pub type AnchorProverSetupBn254_30<F> = AnchorProverSetup<F, M, N>;
116
117pub fn setup_proof_x5_4<E: PairingEngine, R: RngCore + CryptoRng>(
118 curve: Curve,
119 chain_id: u128,
120 secret_raw: Vec<u8>,
121 nullifier_raw: Vec<u8>,
122 leaves_raw: Vec<Vec<u8>>,
123 index: u64,
124 roots: [Vec<u8>; M],
125 recipient_raw: Vec<u8>,
126 relayer_raw: Vec<u8>,
127 commitment_raw: Vec<u8>,
128 fee: u128,
129 refund: u128,
130 pk: Vec<u8>,
131 rng: &mut R,
132) -> Result<AnchorProof, Error> {
133 let params3 = setup_params_x5_3::<E::Fr>(curve);
134 let params4 = setup_params_x5_4::<E::Fr>(curve);
135 let prover = AnchorProverSetupBn254_30::new(params3, params4);
136
137 let (circuit, leaf_raw, nullifier_hash_raw, roots_raw, public_inputs_raw) = prover
138 .setup_circuit_with_privates_raw(
139 chain_id,
140 secret_raw,
141 nullifier_raw,
142 leaves_raw,
143 index,
144 roots,
145 recipient_raw,
146 relayer_raw,
147 commitment_raw,
148 fee,
149 refund,
150 )?;
151
152 let proof = prove_unchecked::<E, _, _>(circuit, &pk, rng)?;
153
154 Ok(AnchorProof {
155 proof,
156 leaf_raw,
157 nullifier_hash_raw,
158 roots_raw,
159 public_inputs_raw,
160 })
161}
162
163pub fn setup_keys_x5_4<E: PairingEngine, R: RngCore + CryptoRng>(
164 curve: Curve,
165 rng: &mut R,
166) -> Result<Keys, Error> {
167 let params3 = setup_params_x5_3::<E::Fr>(curve);
168 let params5 = setup_params_x5_4::<E::Fr>(curve);
169 let prover = AnchorProverSetupBn254_30::new(params3, params5);
170
171 let (circuit, ..) = prover.setup_random_circuit(rng)?;
172
173 let (pk, vk) = setup_keys_unchecked::<E, _, _>(circuit, rng)?;
174
175 Ok(Keys { pk, vk })
176}
177
178#[derive(Clone)]
179pub struct AnchorProverSetup<F: PrimeField, const M: usize, const N: usize> {
180 params3: PoseidonParameters<F>,
181 params4: PoseidonParameters<F>,
182}
183
184impl<F: PrimeField, const M: usize, const N: usize> AnchorProverSetup<F, M, N> {
185 pub fn new(params3: PoseidonParameters<F>, params4: PoseidonParameters<F>) -> Self {
186 Self { params3, params4 }
187 }
188
189 pub fn setup_arbitrary_data(
190 recipient: F,
191 relayer: F,
192 fee: F,
193 refund: F,
194 commitment: F,
195 ) -> AnchorConstraintDataInput<F> {
196 AnchorConstraintDataInput::new(recipient, relayer, fee, refund, commitment)
197 }
198
199 #[allow(clippy::too_many_arguments)]
200 pub fn construct_public_inputs(
201 chain_id: F,
202 nullifier_hash: F,
203 roots: [F; M],
204 recipient: F,
205 relayer: F,
206 fee: F,
207 refund: F,
208 commitment: F,
209 ) -> Vec<F> {
210 let mut pub_ins = vec![chain_id, nullifier_hash];
211 pub_ins.extend(roots.to_vec());
212 pub_ins.extend(vec![recipient, relayer, fee, refund, commitment]);
213
214 pub_ins
215 }
216
217 #[allow(clippy::too_many_arguments)]
218 pub fn deconstruct_public_inputs(
219 public_inputs: &[F],
220 ) -> (
221 F, F, Vec<F>, F, F, F, F, F, ) {
230 let chain_id: F = public_inputs[0];
231 let nullifier_hash = public_inputs[1];
232 let offset = 2 + M;
233 let roots = public_inputs[2..offset].to_vec();
234 let recipient = public_inputs[offset + 1];
235 let relayer = public_inputs[offset + 2];
236 let fee = public_inputs[offset + 3];
237 let refund = public_inputs[offset + 4];
238 let commitments = public_inputs[offset + 5];
239 (
240 chain_id,
241 nullifier_hash,
242 roots,
243 recipient,
244 relayer,
245 fee,
246 refund,
247 commitments,
248 )
249 }
250
251 pub fn setup_leaf<R: Rng>(
252 &self,
253 chain_id: F,
254 rng: &mut R,
255 ) -> Result<(LeafPrivate<F>, LeafPublic<F>, F, F), Error> {
256 let leaf_private = LeafPrivate::generate(rng);
258 let leaf_public = LeafPublic::new(chain_id);
260
261 let leaf_hash = AnchorLeaf::<F, PoseidonCRH_x5_4<F>>::create_leaf(
263 &leaf_private,
264 &leaf_public,
265 &self.params4,
266 )?;
267 let nullifier_hash =
268 AnchorLeaf::<F, PoseidonCRH_x5_4<F>>::create_nullifier(&leaf_private, &self.params4)?;
269
270 Ok((leaf_private, leaf_public, leaf_hash, nullifier_hash))
271 }
272
273 pub fn setup_leaf_with_privates(
274 &self,
275 chain_id: F,
276 secret: F,
277 nullfier: F,
278 ) -> Result<(LeafPrivate<F>, LeafPublic<F>, F, F), Error> {
279 let leaf_private = LeafPrivate::new(secret, nullfier);
281 let leaf_public = LeafPublic::new(chain_id);
282
283 let leaf_hash = Leaf_x5::create_leaf(&leaf_private, &leaf_public, &self.params4)?;
285 let nullifier_hash = Leaf_x5::create_nullifier(&leaf_private, &self.params4)?;
286
287 Ok((leaf_private, leaf_public, leaf_hash, nullifier_hash))
288 }
289
290 #[allow(clippy::too_many_arguments)]
291 pub fn setup_circuit<R: Rng>(
292 self,
293 chain_id: F,
294 leaves: &[F],
295 index: u64,
296 roots: [F; M], recipient: F,
298 relayer: F,
299 fee: F,
300 refund: F,
301 commitment: F,
302 rng: &mut R,
303 ) -> Result<(Circuit_x5<F, N, M>, F, F, Vec<F>, Vec<F>), Error> {
304 let arbitrary_input =
305 Self::setup_arbitrary_data(recipient, relayer, fee, refund, commitment);
306 let (leaf_private, leaf_public, leaf, nullifier_hash) = self.setup_leaf(chain_id, rng)?;
307 let (_, path) = self.setup_tree_and_path(&leaves, index)?;
308
309 let mc = Circuit_x5::new(
310 arbitrary_input.clone(),
311 leaf_private,
312 leaf_public,
313 roots,
314 self.params4,
315 path,
316 nullifier_hash,
317 );
318
319 let public_inputs = Self::construct_public_inputs(
320 chain_id,
321 nullifier_hash,
322 roots,
323 recipient,
324 relayer,
325 fee,
326 refund,
327 commitment,
328 );
329
330 Ok((mc, leaf, nullifier_hash, roots.to_vec(), public_inputs))
331 }
332
333 #[allow(clippy::too_many_arguments)]
334 pub fn setup_circuit_with_privates(
335 self,
336 chain_id: F,
337 secret: F,
338 nullifier: F,
339 leaves: &[F],
340 index: u64,
341 roots: [F; M],
342 recipient: F,
343 relayer: F,
344 fee: F,
345 refund: F,
346 commitment: F,
347 ) -> Result<(Circuit_x5<F, N, M>, F, F, Vec<F>, Vec<F>), Error> {
348 let arbitrary_input =
349 Self::setup_arbitrary_data(recipient, relayer, fee, refund, commitment);
350 let (leaf_private, leaf_public, leaf, nullifier_hash) =
351 self.setup_leaf_with_privates(chain_id, secret, nullifier)?;
352 let (_, path) = self.setup_tree_and_path(&leaves, index)?;
353
354 let mc = Circuit_x5::new(
355 arbitrary_input.clone(),
356 leaf_private,
357 leaf_public,
358 roots,
359 self.params4,
360 path,
361 nullifier_hash,
362 );
363
364 let public_inputs = Self::construct_public_inputs(
365 chain_id,
366 nullifier_hash,
367 roots,
368 recipient,
369 relayer,
370 fee,
371 refund,
372 commitment,
373 );
374
375 Ok((mc, leaf, nullifier_hash, roots.to_vec(), public_inputs))
376 }
377
378 pub fn setup_random_circuit<R: Rng>(
379 self,
380 rng: &mut R,
381 ) -> Result<(Circuit_x5<F, N, M>, F, F, Vec<F>, Vec<F>), Error> {
382 let chain_id = F::rand(rng);
383
384 let roots = [F::rand(rng); M];
385 let recipient = F::rand(rng);
386 let relayer = F::rand(rng);
387 let fee = F::rand(rng);
388 let refund = F::rand(rng);
389 let commitment = F::rand(rng);
390
391 let (leaf_privates, _leaf_public, leaf_hash, ..) = self.setup_leaf(chain_id, rng).unwrap();
392 let secret = leaf_privates.secret();
393 let nullifier = leaf_privates.nullifier();
394 let leaves = vec![leaf_hash];
395 let index = 0;
396
397 self.setup_circuit_with_privates(
398 chain_id, secret, nullifier, &leaves, index, roots, recipient, relayer, fee, refund,
399 commitment,
400 )
401 }
402
403 pub fn setup_circuit_with_privates_raw(
404 self,
405 chain_id: u128,
406 secret: Vec<u8>,
407 nullifier: Vec<u8>,
408 leaves: Vec<Vec<u8>>,
409 index: u64,
410 roots: [Vec<u8>; M],
411 recipient: Vec<u8>,
412 relayer: Vec<u8>,
413 commitment: Vec<u8>,
414 fee: u128,
415 refund: u128,
416 ) -> Result<
417 (
418 Circuit_x5<F, N, M>,
419 Vec<u8>,
420 Vec<u8>,
421 Vec<Vec<u8>>,
422 Vec<Vec<u8>>,
423 ),
424 Error,
425 > {
426 let chain_id_f = F::from(chain_id);
427 let secret_f = F::from_le_bytes_mod_order(&secret);
428 let nullifier_f = F::from_le_bytes_mod_order(&nullifier);
429 let leaves_f: Vec<F> = leaves
430 .iter()
431 .map(|x| F::from_le_bytes_mod_order(x))
432 .collect();
433 let mut roots_f: [F; M] = [F::default(); M];
434 for i in 0..M {
435 roots_f[i] = F::from_le_bytes_mod_order(&roots[i]);
436 }
437 let recipient_f = F::from_le_bytes_mod_order(&recipient);
438 let relayer_f = F::from_le_bytes_mod_order(&relayer);
439 let commitment_f = F::from_le_bytes_mod_order(&commitment);
440 let fee_f = F::from(fee);
441 let refund_f = F::from(refund);
442
443 let (mc, leaf, nullifier_hash, roots, public_inputs) = self.setup_circuit_with_privates(
444 chain_id_f,
445 secret_f,
446 nullifier_f,
447 &leaves_f,
448 index,
449 roots_f,
450 recipient_f,
451 relayer_f,
452 fee_f,
453 refund_f,
454 commitment_f,
455 )?;
456
457 let leaf_raw = leaf.into_repr().to_bytes_le();
458 let nullifier_hash_raw = nullifier_hash.into_repr().to_bytes_le();
459 let roots_raw = roots.iter().map(|x| x.into_repr().to_bytes_le()).collect();
460 let public_inputs_raw: Vec<Vec<u8>> = public_inputs
461 .iter()
462 .map(|x| x.into_repr().to_bytes_le())
463 .collect();
464
465 Ok((
466 mc,
467 leaf_raw,
468 nullifier_hash_raw,
469 roots_raw,
470 public_inputs_raw,
471 ))
472 }
473
474 pub fn setup_tree(&self, leaves: &[F]) -> Result<Tree_x5<F>, Error> {
475 let inner_params = Rc::new(self.params3.clone());
476 let mt = Tree_x5::new_sequential(inner_params, Rc::new(()), leaves)?;
477 Ok(mt)
478 }
479
480 pub fn setup_tree_and_path(
481 &self,
482 leaves: &[F],
483 index: u64,
484 ) -> Result<(Tree_x5<F>, Path<TreeConfig_x5<F>, N>), Error> {
485 let mt = self.setup_tree(leaves)?;
487 let path = mt.generate_membership_proof(index);
489
490 Ok((mt, path))
491 }
492}