arnaucube
arnaucube/sigmabus-pocPublic Self-hosted repository
sigmabus-poc/src/circuits.rs
src/circuits.rsRaw
  1use ark_crypto_primitives::crh::{
  2    poseidon::constraints::{CRHGadget, CRHParametersVar},
  3    CRHSchemeGadget,
  4};
  5use ark_crypto_primitives::sponge::{poseidon::PoseidonConfig, Absorb};
  6use ark_ec::{AffineRepr, CurveGroup};
  7use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::fp::FpVar};
  8use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError};
  9use core::marker::PhantomData;
 10
 11// CF (ConstraintField)
 12pub type CF<C> = <<C as CurveGroup>::Affine as AffineRepr>::ScalarField;
 13
 14#[derive(Debug, Clone)]
 15pub struct GenZKCircuit<C: CurveGroup> {
 16    pub _c: PhantomData<C>,
 17    pub poseidon_config: PoseidonConfig<C::ScalarField>,
 18    // public
 19    pub cm: C::ScalarField,
 20    pub s: C::ScalarField,
 21    pub r_h: C::ScalarField,
 22    pub c: C::ScalarField,
 23    // private
 24    pub x: C::ScalarField,
 25    pub r: C::ScalarField,
 26    pub o_h: C::ScalarField,
 27}
 28impl<C: CurveGroup> ConstraintSynthesizer<CF<C>> for GenZKCircuit<C>
 29where
 30    C::ScalarField: Absorb,
 31{
 32    fn generate_constraints(self, cs: ConstraintSystemRef<CF<C>>) -> Result<(), SynthesisError> {
 33        // public inputs
 34        let cmVar = FpVar::<C::ScalarField>::new_input(cs.clone(), || Ok(self.cm))?;
 35        let sVar = FpVar::<C::ScalarField>::new_input(cs.clone(), || Ok(self.s))?;
 36        let r_hVar = FpVar::<C::ScalarField>::new_input(cs.clone(), || Ok(self.r_h))?;
 37        let cVar = FpVar::<C::ScalarField>::new_input(cs.clone(), || Ok(self.c))?;
 38
 39        // private inputs
 40        let xVar = FpVar::<C::ScalarField>::new_witness(cs.clone(), || Ok(self.x))?;
 41        let rVar = FpVar::<C::ScalarField>::new_witness(cs.clone(), || Ok(self.r))?;
 42        let o_hVar = FpVar::<C::ScalarField>::new_witness(cs.clone(), || Ok(self.o_h))?;
 43
 44        let crh_params =
 45            CRHParametersVar::<C::ScalarField>::new_witness(
 46                cs.clone(),
 47                || Ok(self.poseidon_config),
 48            )
 49            .unwrap();
 50
 51        Self::check(&crh_params, cmVar, sVar, r_hVar, cVar, xVar, rVar, o_hVar)?;
 52
 53        Ok(())
 54    }
 55}
 56
 57impl<C: CurveGroup> GenZKCircuit<C>
 58where
 59    C::ScalarField: Absorb,
 60{
 61    #[allow(clippy::too_many_arguments)]
 62    pub fn check(
 63        crh_params: &CRHParametersVar<C::ScalarField>,
 64        // public inputs:
 65        cm: FpVar<C::ScalarField>,
 66        s: FpVar<C::ScalarField>,
 67        r_h: FpVar<C::ScalarField>,
 68        c: FpVar<C::ScalarField>,
 69        // private inputs:
 70        x: FpVar<C::ScalarField>,
 71        r: FpVar<C::ScalarField>,
 72        o_h: FpVar<C::ScalarField>,
 73    ) -> Result<(), SynthesisError> {
 74        // cm == Commit(x) (Poseidon)
 75        let computed_cm = CRHGadget::<C::ScalarField>::evaluate(crh_params, &[x.clone()]).unwrap();
 76        computed_cm.enforce_equal(&cm)?;
 77
 78        // r_h == HCommit(r, o_h) (Poseidon)
 79        let computed_r_h =
 80            CRHGadget::<C::ScalarField>::evaluate(crh_params, &[r.clone(), o_h.clone()]).unwrap();
 81        computed_r_h.enforce_equal(&r_h)?;
 82
 83        // s == r + c * x
 84        s.enforce_equal(&(r + (c * x)))?;
 85        Ok(())
 86    }
 87}
 88
 89#[cfg(test)]
 90pub mod tests {
 91    use super::*;
 92    use ark_bn254::{Fr, G1Projective};
 93    use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge};
 94    use ark_ec::Group;
 95    use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar};
 96    use ark_relations::r1cs::ConstraintSystem;
 97    use ark_std::UniformRand;
 98    use std::ops::Mul;
 99
100    use crate::sigmabus::SigmaProof;
101    use crate::transcript::{tests::poseidon_test_config, PoseidonTranscript};
102
103    #[test]
104    fn test_gen_zk() {
105        let mut rng = ark_std::test_rng();
106
107        let poseidon_config = poseidon_test_config::<Fr>();
108        let mut transcript = PoseidonTranscript::<G1Projective>::new(&poseidon_config);
109
110        let x = Fr::rand(&mut rng);
111
112        // the next lines do the same that is done in Sigmabus::prove but here in the test to have
113        // access to the internal values:
114        let mut sponge = PoseidonSponge::<Fr>::new(&poseidon_config);
115        sponge.absorb(&x);
116        let cm: Fr = sponge.squeeze_field_elements(1)[0];
117        transcript.absorb(&cm);
118
119        let r = Fr::rand(&mut rng);
120        let o_h = Fr::rand(&mut rng);
121
122        let R = G1Projective::generator().mul(r);
123
124        let mut sponge = PoseidonSponge::<Fr>::new(&poseidon_config);
125        sponge.absorb(&vec![r, o_h]);
126
127        let r_h: Fr = sponge.squeeze_field_elements(1)[0];
128
129        transcript.absorb_point(&R);
130        transcript.absorb(&r_h);
131        let c = transcript.get_challenge();
132
133        let s = r + c * x;
134        let sigma_proof = SigmaProof { s, R, r_h };
135        // end of Sigmabus::prove
136
137        let cs = ConstraintSystem::<Fr>::new_ref();
138
139        // public inputs
140        let cmVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(cm)).unwrap();
141        let sVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(sigma_proof.s)).unwrap();
142        let r_hVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(sigma_proof.r_h)).unwrap();
143        let cVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(c)).unwrap();
144        // private inputs
145        let xVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(x)).unwrap();
146        let rVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(r)).unwrap();
147        let o_hVar = FpVar::<Fr>::new_witness(cs.clone(), || Ok(o_h)).unwrap();
148
149        let crh_params =
150            CRHParametersVar::<Fr>::new_witness(cs.clone(), || Ok(poseidon_config)).unwrap();
151
152        // GenZK
153        GenZKCircuit::<G1Projective>::check(
154            &crh_params,
155            cmVar,
156            sVar,
157            r_hVar,
158            cVar,
159            xVar,
160            rVar,
161            o_hVar,
162        )
163        .unwrap();
164        assert!(cs.is_satisfied().unwrap());
165        dbg!("num_constraints={:?}", cs.num_constraints());
166    }
167}