arkworks_r1cs_circuits/
anchor.rs1use ark_ff::fields::PrimeField;
27use ark_r1cs_std::{eq::EqGadget, fields::fp::FpVar, prelude::*};
28use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError};
29use ark_std::vec::Vec;
30use arkworks_native_gadgets::merkle_tree::Path;
31use arkworks_r1cs_gadgets::{merkle_tree::PathVar, poseidon::FieldHasherGadget, set::SetGadget};
32
33#[derive(Clone)]
44pub struct AnchorCircuit<F: PrimeField, HG: FieldHasherGadget<F>, const N: usize, const M: usize> {
45 arbitrary_input: F,
48 secret: F,
50 nullifier: F,
52 chain_id: F,
54 root_set: [F; M],
56 path: Path<F, HG::Native, N>,
58 nullifier_hash: F,
59 hasher3: HG::Native,
61 hasher4: HG::Native,
63}
64
65impl<F, HG, const N: usize, const M: usize> AnchorCircuit<F, HG, N, M>
67where
68 F: PrimeField,
69 HG: FieldHasherGadget<F>,
70{
71 #[allow(clippy::too_many_arguments)]
72 pub fn new(
73 arbitrary_input: F,
74 secret: F,
75 nullifier: F,
76 chain_id: F,
77 root_set: [F; M],
78 path: Path<F, HG::Native, N>,
79 nullifier_hash: F,
80 hasher3: HG::Native,
81 hasher4: HG::Native,
82 ) -> Self {
83 Self {
84 arbitrary_input,
85 secret,
86 nullifier,
87 chain_id,
88 root_set,
89 path,
90 nullifier_hash,
91 hasher3,
92 hasher4,
93 }
94 }
95}
96
97impl<F, HG, const N: usize, const M: usize> ConstraintSynthesizer<F> for AnchorCircuit<F, HG, N, M>
103where
104 F: PrimeField,
105 HG: FieldHasherGadget<F>,
106{
107 fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
108 let arbitrary_input = self.arbitrary_input;
109 let secret = self.secret;
110 let nullifier = self.nullifier;
111 let chain_id = self.chain_id;
112 let root_set = self.root_set;
113 let path = self.path;
114 let nullifier_hash = self.nullifier_hash;
115
116 let nullifier_hash_var = FpVar::<F>::new_input(cs.clone(), || Ok(nullifier_hash))?;
119 let arbitrary_input_var = FpVar::<F>::new_input(cs.clone(), || Ok(arbitrary_input))?;
120 let chain_id_var = FpVar::<F>::new_input(cs.clone(), || Ok(chain_id))?;
121 let roots_var = Vec::<FpVar<F>>::new_input(cs.clone(), || Ok(root_set))?;
122
123 let hasher3_gadget: HG =
125 FieldHasherGadget::<F>::from_native(&mut cs.clone(), self.hasher3)?;
126 let hasher4_gadget: HG =
127 FieldHasherGadget::<F>::from_native(&mut cs.clone(), self.hasher4)?;
128
129 let secret_var = FpVar::<F>::new_witness(cs.clone(), || Ok(secret))?;
131 let nullifier_var = FpVar::<F>::new_witness(cs.clone(), || Ok(nullifier))?;
132 let path_var = PathVar::<F, HG, N>::new_witness(cs.clone(), || Ok(path))?;
133
134 let anchor_leaf =
136 hasher4_gadget.hash(&[chain_id_var, nullifier_var.clone(), secret_var])?;
137 let anchor_nullifier = hasher3_gadget.hash_two(&nullifier_var, &nullifier_var)?;
138 let root_var = path_var.root_hash(&anchor_leaf, &hasher3_gadget)?;
139 let set_gadget = SetGadget::new(roots_var);
141 let is_set_member = set_gadget.check_membership(&root_var)?;
142 let _ = &arbitrary_input_var * &arbitrary_input_var;
144
145 is_set_member.enforce_equal(&Boolean::TRUE)?;
147 anchor_nullifier.enforce_equal(&nullifier_hash_var)?;
148
149 Ok(())
150 }
151}