arkworks_setups/
common.rs

1use ark_crypto_primitives::{Error, SNARK};
2use ark_ec::PairingEngine;
3use ark_ff::fields::PrimeField;
4use ark_groth16::{Groth16, Proof, ProvingKey, VerifyingKey};
5use ark_relations::r1cs::ConstraintSynthesizer;
6use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
7use ark_std::{
8	collections::BTreeMap,
9	rand::{CryptoRng, RngCore},
10	vec::Vec,
11};
12use arkworks_native_gadgets::{
13	merkle_tree::{Path, SparseMerkleTree},
14	poseidon::{sbox::PoseidonSbox, FieldHasher, PoseidonParameters},
15};
16use arkworks_utils::{
17	bytes_matrix_to_f, bytes_vec_to_f, poseidon_params::setup_poseidon_params, Curve,
18};
19use tiny_keccak::{Hasher, Keccak};
20
21pub struct VAnchorLeaf {
22	pub chain_id_bytes: Vec<u8>,
23	pub amount: u128,
24	pub public_key_bytes: Vec<u8>,
25	pub blinding_bytes: Vec<u8>,
26	pub index: u32,
27	pub private_key_bytes: Vec<u8>,
28	pub nullifier_bytes: Vec<u8>,
29	pub leaf_bytes: Vec<u8>,
30	pub nullifier_hash_bytes: Vec<u8>,
31}
32
33pub struct Leaf {
34	pub chain_id_bytes: Option<Vec<u8>>,
35	pub secret_bytes: Vec<u8>,
36	pub nullifier_bytes: Vec<u8>,
37	pub leaf_bytes: Vec<u8>,
38	pub nullifier_hash_bytes: Vec<u8>,
39}
40
41pub struct VAnchorProof {
42	pub proof: Vec<u8>,
43	pub public_inputs_raw: Vec<Vec<u8>>,
44}
45
46pub struct AnchorProof {
47	pub proof: Vec<u8>,
48	pub leaf_raw: Vec<u8>,
49	pub nullifier_hash_raw: Vec<u8>,
50	pub roots_raw: Vec<Vec<u8>>,
51	pub public_inputs_raw: Vec<Vec<u8>>,
52}
53
54pub struct MixerProof {
55	pub proof: Vec<u8>,
56	pub leaf_raw: Vec<u8>,
57	pub nullifier_hash_raw: Vec<u8>,
58	pub root_raw: Vec<u8>,
59	pub public_inputs_raw: Vec<Vec<u8>>,
60}
61
62pub struct Keys {
63	pub pk: Vec<u8>,
64	pub vk: Vec<u8>,
65}
66
67pub fn setup_keys<E: PairingEngine, R: RngCore + CryptoRng, C: ConstraintSynthesizer<E::Fr>>(
68	circuit: C,
69	rng: &mut R,
70) -> Result<(Vec<u8>, Vec<u8>), Error> {
71	let (pk, vk) = Groth16::<E>::circuit_specific_setup(circuit, rng)?;
72
73	let mut pk_bytes = Vec::new();
74	let mut vk_bytes = Vec::new();
75	pk.serialize(&mut pk_bytes)?;
76	vk.serialize(&mut vk_bytes)?;
77	Ok((pk_bytes, vk_bytes))
78}
79
80pub fn setup_keys_unchecked<
81	E: PairingEngine,
82	R: RngCore + CryptoRng,
83	C: ConstraintSynthesizer<E::Fr>,
84>(
85	circuit: C,
86	rng: &mut R,
87) -> Result<(Vec<u8>, Vec<u8>), Error> {
88	let (pk, vk) = Groth16::<E>::circuit_specific_setup(circuit, rng)?;
89
90	let mut pk_bytes = Vec::new();
91	let mut vk_bytes = Vec::new();
92	pk.serialize_unchecked(&mut pk_bytes)?;
93	vk.serialize_unchecked(&mut vk_bytes)?;
94	Ok((pk_bytes, vk_bytes))
95}
96
97pub fn prove<E: PairingEngine, R: RngCore + CryptoRng, C: ConstraintSynthesizer<E::Fr>>(
98	circuit: C,
99	pk_bytes: &[u8],
100	rng: &mut R,
101) -> Result<Vec<u8>, Error> {
102	let pk = ProvingKey::<E>::deserialize(pk_bytes)?;
103
104	let proof = Groth16::prove(&pk, circuit, rng)?;
105	let mut proof_bytes = Vec::new();
106	proof.serialize(&mut proof_bytes)?;
107	Ok(proof_bytes)
108}
109
110pub fn prove_unchecked<
111	E: PairingEngine,
112	R: RngCore + CryptoRng,
113	C: ConstraintSynthesizer<E::Fr>,
114>(
115	circuit: C,
116	pk_unchecked_bytes: &[u8],
117	rng: &mut R,
118) -> Result<Vec<u8>, Error> {
119	let pk = ProvingKey::<E>::deserialize_unchecked(pk_unchecked_bytes)?;
120
121	let proof = Groth16::prove(&pk, circuit, rng)?;
122	let mut proof_bytes = Vec::new();
123	proof.serialize(&mut proof_bytes)?;
124	Ok(proof_bytes)
125}
126
127pub fn verify<E: PairingEngine>(
128	public_inputs: &[E::Fr],
129	vk_bytes: &[u8],
130	proof: &[u8],
131) -> Result<bool, Error> {
132	let vk = VerifyingKey::<E>::deserialize(vk_bytes)?;
133	let proof = Proof::<E>::deserialize(proof)?;
134	verify_groth16(&vk, &public_inputs, &proof)
135}
136
137pub fn verify_unchecked<E: PairingEngine>(
138	public_inputs: &[E::Fr],
139	vk_unchecked_bytes: &[u8],
140	proof: &[u8],
141) -> Result<bool, Error> {
142	let vk = VerifyingKey::<E>::deserialize_unchecked(vk_unchecked_bytes)?;
143	let proof = Proof::<E>::deserialize(proof)?;
144	verify_groth16(&vk, &public_inputs, &proof)
145}
146
147pub fn verify_unchecked_raw<E: PairingEngine>(
148	public_inputs: &[Vec<u8>],
149	vk_unchecked_bytes: &[u8],
150	proof: &[u8],
151) -> Result<bool, Error> {
152	let pub_ins: Vec<E::Fr> = public_inputs
153		.iter()
154		.map(|x| E::Fr::from_be_bytes_mod_order(&x))
155		.collect();
156	let vk = VerifyingKey::<E>::deserialize_unchecked(vk_unchecked_bytes)?;
157	let proof = Proof::<E>::deserialize(proof)?;
158	verify_groth16(&vk, &pub_ins, &proof)
159}
160
161pub fn verify_groth16<E: PairingEngine>(
162	vk: &VerifyingKey<E>,
163	public_inputs: &[E::Fr],
164	proof: &Proof<E>,
165) -> Result<bool, Error> {
166	let res = Groth16::<E>::verify(vk, public_inputs, proof)?;
167	Ok(res)
168}
169
170pub fn keccak_256(input: &[u8]) -> Vec<u8> {
171	let mut keccak = Keccak::v256();
172	keccak.update(&input);
173
174	let mut output = [0u8; 32];
175	keccak.finalize(&mut output);
176	output.to_vec()
177}
178
179pub type SMT<F, H, const HEIGHT: usize> = SparseMerkleTree<F, H, HEIGHT>;
180
181pub fn create_merkle_tree<F: PrimeField, H: FieldHasher<F>, const N: usize>(
182	hasher: &H,
183	leaves: &[F],
184	default_leaf: &[u8],
185) -> SparseMerkleTree<F, H, N> {
186	let pairs: BTreeMap<u32, F> = leaves
187		.iter()
188		.enumerate()
189		.map(|(i, l)| (i as u32, *l))
190		.collect();
191	let smt = SparseMerkleTree::<F, H, N>::new(&pairs, hasher, default_leaf).unwrap();
192
193	smt
194}
195
196pub fn setup_tree_and_create_path<F: PrimeField, H: FieldHasher<F>, const HEIGHT: usize>(
197	hasher: &H,
198	leaves: &[F],
199	index: u64,
200	default_leaf: &[u8],
201) -> Result<(SMT<F, H, HEIGHT>, Path<F, H, HEIGHT>), Error> {
202	// Making the merkle tree
203	let smt = create_merkle_tree::<F, H, HEIGHT>(hasher, leaves, default_leaf);
204	// Getting the proof path
205	let path = smt.generate_membership_proof(index);
206	Ok((smt, path))
207}
208
209pub fn setup_params<F: PrimeField>(curve: Curve, exp: i8, width: u8) -> PoseidonParameters<F> {
210	let pos_data = setup_poseidon_params(curve, exp, width).unwrap();
211
212	let mds_f = bytes_matrix_to_f(&pos_data.mds);
213	let rounds_f = bytes_vec_to_f(&pos_data.rounds);
214
215	let pos = PoseidonParameters {
216		mds_matrix: mds_f,
217		round_keys: rounds_f,
218		full_rounds: pos_data.full_rounds,
219		partial_rounds: pos_data.partial_rounds,
220		sbox: PoseidonSbox(pos_data.exp),
221		width: pos_data.width,
222	};
223
224	pos
225}