arkworks_circuits/setup/
mixer.rs

1use super::common::*;
2use crate::circuit::mixer::MixerCircuit;
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::mixer_data::Input as MixerDataInput,
13	leaf::mixer::{constraints::MixerLeafGadget, MixerLeaf, Private as LeafPrivate},
14	merkle_tree::Path,
15};
16use arkworks_utils::{
17	poseidon::PoseidonParameters,
18	utils::common::{setup_params_x5_3, setup_params_x5_5, Curve},
19};
20
21pub type MixerConstraintDataInput<F> = MixerDataInput<F>;
22
23pub type Leaf_x5<F> = MixerLeaf<F, PoseidonCRH_x5_5<F>>;
24
25pub type LeafGadget_x5<F> = MixerLeafGadget<F, PoseidonCRH_x5_5<F>, PoseidonCRH_x5_5Gadget<F>>;
26
27pub type Circuit_x5<F, const N: usize> = MixerCircuit<
28	F,
29	PoseidonCRH_x5_5<F>,
30	PoseidonCRH_x5_5Gadget<F>,
31	TreeConfig_x5<F>,
32	LeafCRHGadget<F>,
33	PoseidonCRH_x5_3Gadget<F>,
34	N,
35>;
36
37pub type Leaf_x17<F> = MixerLeaf<F, PoseidonCRH_x17_5<F>>;
38pub type LeafGadget_x17<F> = MixerLeafGadget<F, PoseidonCRH_x17_5<F>, PoseidonCRH_x17_5Gadget<F>>;
39
40pub type Circuit_x17<F, const N: usize> = MixerCircuit<
41	F,
42	PoseidonCRH_x17_5<F>,
43	PoseidonCRH_x17_5Gadget<F>,
44	TreeConfig_x17<F>,
45	LeafCRHGadget<F>,
46	PoseidonCRH_x17_3Gadget<F>,
47	N,
48>;
49
50pub type Leaf_MiMC220<F> = MixerLeaf<F, MiMCCRH_220<F>>;
51pub type LeafGadget_MiMC220<F> = MixerLeafGadget<F, MiMCCRH_220<F>, MiMCCRH_220Gadget<F>>;
52
53pub type Circuit_MiMC220<F, const N: usize> = MixerCircuit<
54	F,
55	MiMCCRH_220<F>,
56	MiMCCRH_220Gadget<F>,
57	TreeConfig_MiMC220<F>,
58	LeafCRHGadget<F>,
59	MiMCCRH_220Gadget<F>,
60	N,
61>;
62
63pub fn setup_leaf_x5_5<F: PrimeField, R: RngCore>(
64	curve: Curve,
65	rng: &mut R,
66) -> Result<Leaf, Error> {
67	let params5 = setup_params_x5_5::<F>(curve);
68	// Secret inputs for the leaf
69	let leaf_private = LeafPrivate::generate(rng);
70
71	let leaf_hash = Leaf_x5::create_leaf(&leaf_private, &params5)?;
72	let nullifier_hash = Leaf_x5::create_nullifier(&leaf_private, &params5)?;
73
74	let secret_bytes = leaf_private.secret().into_repr().to_bytes_le();
75	let nullifier_bytes = leaf_private.nullifier().into_repr().to_bytes_le();
76
77	let leaf_bytes = leaf_hash.into_repr().to_bytes_le();
78	let nullifier_hash_bytes = nullifier_hash.into_repr().to_bytes_le();
79	Ok(Leaf {
80		secret_bytes,
81		nullifier_bytes,
82		leaf_bytes,
83		nullifier_hash_bytes,
84	})
85}
86
87pub fn setup_leaf_with_privates_raw_x5_5<F: PrimeField>(
88	curve: Curve,
89	secret_bytes: Vec<u8>,
90	nullifier_bytes: Vec<u8>,
91) -> Result<Leaf, Error> {
92	let params5 = setup_params_x5_5::<F>(curve);
93
94	let secret = F::from_le_bytes_mod_order(&secret_bytes);
95	let nullifier = F::from_le_bytes_mod_order(&nullifier_bytes);
96	// Secret inputs for the leaf
97	let leaf_private = LeafPrivate::new(secret, nullifier);
98
99	let leaf_hash = Leaf_x5::create_leaf(&leaf_private, &params5)?;
100	let nullifier_hash = Leaf_x5::create_nullifier(&leaf_private, &params5)?;
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	Ok(Leaf {
105		secret_bytes,
106		nullifier_bytes,
107		leaf_bytes,
108		nullifier_hash_bytes,
109	})
110}
111
112pub const LEN: usize = 30;
113type MixerProverSetupBn254_30<F> = MixerProverSetup<F, LEN>;
114
115pub fn setup_proof_x5_5<E: PairingEngine, R: RngCore + CryptoRng>(
116	curve: Curve,
117	secret_raw: Vec<u8>,
118	nullifier_raw: Vec<u8>,
119	leaves_raw: Vec<Vec<u8>>,
120	index: u64,
121	recipient_raw: Vec<u8>,
122	relayer_raw: Vec<u8>,
123	fee: u128,
124	refund: u128,
125	pk: Vec<u8>,
126	rng: &mut R,
127) -> Result<MixerProof, Error> {
128	let params3 = setup_params_x5_3::<E::Fr>(curve);
129	let params5 = setup_params_x5_5::<E::Fr>(curve);
130	let prover = MixerProverSetupBn254_30::new(params3, params5);
131
132	let (circuit, leaf_raw, nullifier_hash_raw, root_raw, public_inputs_raw) = prover
133		.setup_circuit_with_privates_raw(
134			secret_raw,
135			nullifier_raw,
136			&leaves_raw,
137			index,
138			recipient_raw,
139			relayer_raw,
140			fee,
141			refund,
142		)?;
143
144	let proof = prove_unchecked::<E, _, _>(circuit, &pk, rng)?;
145
146	Ok(MixerProof {
147		proof,
148		leaf_raw,
149		nullifier_hash_raw,
150		root_raw,
151		public_inputs_raw,
152	})
153}
154
155pub fn setup_keys_x5_5<E: PairingEngine, R: RngCore + CryptoRng>(
156	curve: Curve,
157	rng: &mut R,
158) -> Result<Keys, Error> {
159	let params3 = setup_params_x5_3::<E::Fr>(curve);
160	let params5 = setup_params_x5_5::<E::Fr>(curve);
161	let prover = MixerProverSetupBn254_30::new(params3, params5);
162
163	let (circuit, ..) = prover.setup_random_circuit(rng)?;
164
165	let (pk, vk) = setup_keys_unchecked::<E, _, _>(circuit, rng)?;
166
167	Ok(Keys { pk, vk })
168}
169
170pub struct MixerProverSetup<F: PrimeField, const N: usize> {
171	params3: PoseidonParameters<F>,
172	params5: PoseidonParameters<F>,
173}
174
175impl<F: PrimeField, const N: usize> MixerProverSetup<F, N> {
176	pub fn new(params3: PoseidonParameters<F>, params5: PoseidonParameters<F>) -> Self {
177		Self { params3, params5 }
178	}
179
180	pub fn setup_arbitrary_data(
181		recipient: F,
182		relayer: F,
183		fee: F,
184		refund: F,
185	) -> MixerConstraintDataInput<F> {
186		MixerConstraintDataInput::new(recipient, relayer, fee, refund)
187	}
188
189	pub fn construct_public_inputs(
190		nullifier_hash: F,
191		root: F,
192		recipient: F,
193		relayer: F,
194		fee: F,
195		refund: F,
196	) -> Vec<F> {
197		vec![nullifier_hash, root, recipient, relayer, fee, refund]
198	}
199
200	pub fn deconstruct_public_inputs(
201		public_inputs: &[F],
202	) -> (
203		F, // nullifier hash
204		F, // root
205		F, // recipient
206		F, // relayer
207		F, // fee
208		F, // refund
209	) {
210		(
211			public_inputs[0],
212			public_inputs[1],
213			public_inputs[2],
214			public_inputs[3],
215			public_inputs[4],
216			public_inputs[6],
217		)
218	}
219
220	pub fn setup_leaf<R: Rng>(&self, rng: &mut R) -> Result<(LeafPrivate<F>, F, F), Error> {
221		// Secret inputs for the leaf
222		let leaf_private = LeafPrivate::generate(rng);
223
224		// Creating the leaf
225		let leaf_hash = Leaf_x5::create_leaf(&leaf_private, &self.params5)?;
226		let nullifier_hash = Leaf_x5::create_nullifier(&leaf_private, &self.params5)?;
227		Ok((leaf_private, leaf_hash, nullifier_hash))
228	}
229
230	pub fn setup_leaf_with_privates(
231		&self,
232		secret: F,
233		nullifier: F,
234	) -> Result<(LeafPrivate<F>, F, F), Error> {
235		// Secret inputs for the leaf
236		let leaf_private = LeafPrivate::new(secret, nullifier);
237
238		// Creating the leaf
239		let leaf_hash = Leaf_x5::create_leaf(&leaf_private, &self.params5)?;
240		let nullifier_hash = Leaf_x5::create_nullifier(&leaf_private, &self.params5)?;
241		Ok((leaf_private, leaf_hash, nullifier_hash))
242	}
243
244	pub fn setup_leaf_with_privates_raw(
245		&self,
246		secret: Vec<u8>,
247		nullifier: Vec<u8>,
248	) -> Result<(LeafPrivate<F>, F, F), Error> {
249		// Secret inputs for the leaf
250		let secret_f = F::from_le_bytes_mod_order(&secret);
251		let nullifier_f = F::from_le_bytes_mod_order(&nullifier);
252
253		self.setup_leaf_with_privates(secret_f, nullifier_f)
254	}
255
256	#[allow(clippy::too_many_arguments)]
257	pub fn setup_circuit_with_privates(
258		self,
259		secret: F,
260		nullifier: F,
261		leaves: &[F],
262		index: u64,
263		recipient: F,
264		relayer: F,
265		fee: F,
266		refund: F,
267	) -> Result<(Circuit_x5<F, N>, F, F, F, Vec<F>), Error> {
268		let arbitrary_input = Self::setup_arbitrary_data(recipient, relayer, fee, refund);
269		let (leaf_private, leaf, nullifier_hash) =
270			self.setup_leaf_with_privates(secret, nullifier)?;
271		let (tree, path) = self.setup_tree_and_create_path(&leaves, index)?;
272		let root = tree.root().inner();
273
274		let mc = Circuit_x5::new(
275			arbitrary_input,
276			leaf_private,
277			self.params5,
278			path,
279			root,
280			nullifier_hash,
281		);
282		let public_inputs =
283			Self::construct_public_inputs(nullifier_hash, root, recipient, relayer, fee, refund);
284		Ok((mc, leaf, nullifier_hash, root, public_inputs))
285	}
286
287	#[allow(clippy::too_many_arguments)]
288	pub fn setup_circuit_with_privates_raw(
289		self,
290		secret: Vec<u8>,
291		nullifier: Vec<u8>,
292		leaves: &[Vec<u8>],
293		index: u64,
294		recipient: Vec<u8>,
295		relayer: Vec<u8>,
296		fee: u128,
297		refund: u128,
298	) -> Result<(Circuit_x5<F, N>, Vec<u8>, Vec<u8>, Vec<u8>, Vec<Vec<u8>>), Error> {
299		let secret_f = F::from_le_bytes_mod_order(&secret);
300		let nullifier_f = F::from_le_bytes_mod_order(&nullifier);
301		let leaves_f: Vec<F> = leaves
302			.iter()
303			.map(|x| F::from_le_bytes_mod_order(x))
304			.collect();
305		let recipient_f = F::from_le_bytes_mod_order(&recipient);
306		let relayer_f = F::from_le_bytes_mod_order(&relayer);
307		let fee_f = F::from(fee);
308		let refund_f = F::from(refund);
309
310		let (mc, leaf, nullifier_hash, root, public_inputs) = self.setup_circuit_with_privates(
311			secret_f,
312			nullifier_f,
313			&leaves_f,
314			index,
315			recipient_f,
316			relayer_f,
317			fee_f,
318			refund_f,
319		)?;
320
321		let leaf_raw = leaf.into_repr().to_bytes_le();
322		let nullifier_hash_raw = nullifier_hash.into_repr().to_bytes_le();
323		let root_raw = root.into_repr().to_bytes_le();
324		let public_inputs_raw: Vec<Vec<u8>> = public_inputs
325			.iter()
326			.map(|x| x.into_repr().to_bytes_le())
327			.collect();
328
329		Ok((
330			mc,
331			leaf_raw,
332			nullifier_hash_raw,
333			root_raw,
334			public_inputs_raw,
335		))
336	}
337
338	pub fn setup_random_circuit<R: Rng>(
339		self,
340		rng: &mut R,
341	) -> Result<(Circuit_x5<F, N>, F, F, F, Vec<F>), Error> {
342		let recipient = F::rand(rng);
343		let relayer = F::rand(rng);
344		let fee = F::rand(rng);
345		let refund = F::rand(rng);
346
347		let (leaf_privates, leaf_hash, ..) = self.setup_leaf(rng).unwrap();
348		let secret = leaf_privates.secret();
349		let nullifier = leaf_privates.nullifier();
350		let leaves = vec![leaf_hash];
351		let index = 0;
352
353		self.setup_circuit_with_privates(
354			secret, nullifier, &leaves, index, recipient, relayer, fee, refund,
355		)
356	}
357
358	pub fn create_circuit(
359		self,
360		arbitrary_input: MixerConstraintDataInput<F>,
361		leaf_private: LeafPrivate<F>,
362		path: Path<TreeConfig_x5<F>, N>,
363		root: F,
364		nullifier_hash: F,
365	) -> Circuit_x5<F, N> {
366		let mc = Circuit_x5::new(
367			arbitrary_input,
368			leaf_private,
369			self.params5,
370			path,
371			root,
372			nullifier_hash,
373		);
374		mc
375	}
376
377	pub fn setup_tree(&self, leaves: &[F]) -> Result<Tree_x5<F>, Error> {
378		let inner_params = Rc::new(self.params3.clone());
379		let mt = Tree_x5::new_sequential(inner_params, Rc::new(()), leaves)?;
380		Ok(mt)
381	}
382
383	pub fn setup_tree_and_create_path(
384		&self,
385		leaves: &[F],
386		index: u64,
387	) -> Result<(Tree_x5<F>, Path<TreeConfig_x5<F>, N>), Error> {
388		// Making the merkle tree
389		let mt = self.setup_tree(leaves)?;
390		// Getting the proof path
391		let path = mt.generate_membership_proof(index);
392		Ok((mt, path))
393	}
394}