arnaucube
arnaucube/nova-studyPublic Self-hosted repository
nova-study/src/transcript.rs
src/transcript.rsRaw
  1use ark_ec::{AffineRepr, CurveGroup};
  2use ark_ff::PrimeField;
  3use std::marker::PhantomData;
  4
  5use ark_r1cs_std::fields::fp::FpVar;
  6
  7use ark_crypto_primitives::sponge::poseidon::{
  8    constraints::PoseidonSpongeVar, PoseidonConfig, PoseidonSponge,
  9};
 10use ark_crypto_primitives::sponge::{
 11    constraints::CryptographicSpongeVar, Absorb, CryptographicSponge,
 12};
 13use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
 14
 15pub struct Transcript<F: PrimeField + Absorb, C: CurveGroup>
 16where
 17    <C as CurveGroup>::BaseField: Absorb,
 18{
 19    // where F is the Constraint Field (eq. C::ScalarField)
 20    sponge: PoseidonSponge<F>,
 21    _c: PhantomData<C>,
 22}
 23impl<F: PrimeField + Absorb, C: CurveGroup> Transcript<F, C>
 24where
 25    <C as CurveGroup>::BaseField: Absorb,
 26{
 27    pub fn new(poseidon_config: &PoseidonConfig<F>) -> Self {
 28        let sponge = PoseidonSponge::<F>::new(poseidon_config);
 29        Transcript {
 30            sponge,
 31            _c: PhantomData,
 32        }
 33    }
 34    pub fn add(&mut self, v: &F) {
 35        self.sponge.absorb(&v);
 36    }
 37    pub fn add_vec(&mut self, v: &[F]) {
 38        self.sponge.absorb(&v);
 39    }
 40    pub fn add_point(&mut self, v: &C) {
 41        let v_affine = v.into_affine();
 42        let xy = v_affine.xy().unwrap(); // WIP
 43        self.sponge.absorb(&vec![xy.0, xy.1]);
 44    }
 45    pub fn get_challenge(&mut self) -> F {
 46        let c = self.sponge.squeeze_field_elements(1);
 47        self.add(&c[0]);
 48        c[0]
 49    }
 50    pub fn get_challenge_vec(&mut self, n: usize) -> Vec<F> {
 51        let c = self.sponge.squeeze_field_elements(n);
 52        self.sponge.absorb(&c);
 53        c
 54    }
 55}
 56
 57pub struct TranscriptVar<F: PrimeField> {
 58    // where F is the Constraint Field
 59    sponge: PoseidonSpongeVar<F>,
 60}
 61impl<F: PrimeField> TranscriptVar<F> {
 62    pub fn new(cs: ConstraintSystemRef<F>, poseidon_config: &PoseidonConfig<F>) -> Self {
 63        let sponge = PoseidonSpongeVar::<F>::new(cs, poseidon_config);
 64        Self { sponge }
 65    }
 66    pub fn add(&mut self, v: FpVar<F>) -> Result<(), SynthesisError> {
 67        self.sponge.absorb(&v)
 68    }
 69    pub fn get_challenge(&mut self) -> Result<FpVar<F>, SynthesisError> {
 70        let c = self.sponge.squeeze_field_elements(1)?;
 71        self.sponge.absorb(&c[0])?;
 72        Ok(c[0].clone())
 73    }
 74    pub fn get_challenge_vec(&mut self, n: usize) -> Result<Vec<FpVar<F>>, SynthesisError> {
 75        let c = self.sponge.squeeze_field_elements(n)?;
 76        self.sponge.absorb(&c)?;
 77        Ok(c)
 78    }
 79}
 80
 81use ark_crypto_primitives::sponge::poseidon::find_poseidon_ark_and_mds;
 82
 83// WARNING this is for test only
 84pub fn poseidon_test_config<F: PrimeField>() -> PoseidonConfig<F> {
 85    let full_rounds = 8;
 86    let partial_rounds = 31;
 87    let alpha = 5;
 88    let rate = 2;
 89
 90    let (ark, mds) = find_poseidon_ark_and_mds::<F>(
 91        F::MODULUS_BIT_SIZE as u64,
 92        rate,
 93        full_rounds,
 94        partial_rounds,
 95        0,
 96    );
 97
 98    PoseidonConfig::new(
 99        full_rounds as usize,
100        partial_rounds as usize,
101        alpha,
102        mds,
103        ark,
104        rate,
105        1,
106    )
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112    use ark_mnt4_298::{Fr, G1Projective}; // scalar field
113    use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar};
114    use ark_relations::r1cs::ConstraintSystem;
115
116    #[test]
117    fn test_transcript_and_transcriptvar() {
118        let config = poseidon_test_config::<Fr>();
119        let mut tr = Transcript::<Fr, G1Projective>::new(&config);
120        tr.add(&Fr::from(42_u32));
121        let c = tr.get_challenge();
122
123        let cs = ConstraintSystem::<Fr>::new_ref();
124        let mut tr_var = TranscriptVar::<Fr>::new(cs.clone(), &config);
125        let v = FpVar::<Fr>::new_witness(cs.clone(), || Ok(Fr::from(42_u32))).unwrap();
126        tr_var.add(v).unwrap();
127        let c_var = tr_var.get_challenge().unwrap();
128
129        assert_eq!(c, c_var.value().unwrap());
130    }
131}