arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/folding-schemes/src/folding/nova/serialize.rs
folding-schemes/src/folding/nova/serialize.rsRaw
  1use ark_crypto_primitives::sponge::{poseidon::PoseidonConfig, Absorb};
  2use ark_ec::{CurveGroup, Group};
  3use ark_ff::PrimeField;
  4use ark_r1cs_std::{
  5    groups::{CurveVar, GroupOpsBounds},
  6    ToConstraintFieldGadget,
  7};
  8use ark_relations::r1cs::ConstraintSynthesizer;
  9use ark_relations::r1cs::ConstraintSystem;
 10use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError, Write};
 11use std::marker::PhantomData;
 12
 13use super::{circuits::AugmentedFCircuit, Nova, ProverParams};
 14use super::{CommittedInstance, Witness};
 15use crate::folding::circuits::{cyclefold::CycleFoldCircuit, CF2};
 16use crate::{
 17    ccs::r1cs::extract_r1cs, commitment::CommitmentScheme, folding::circuits::CF1,
 18    frontend::FCircuit,
 19};
 20
 21impl<C1, GC1, C2, GC2, FC, CS1, CS2> CanonicalSerialize for Nova<C1, GC1, C2, GC2, FC, CS1, CS2>
 22where
 23    C1: CurveGroup,
 24    C2: CurveGroup,
 25    FC: FCircuit<C1::ScalarField>,
 26    CS1: CommitmentScheme<C1>,
 27    CS2: CommitmentScheme<C2>,
 28    <C1 as CurveGroup>::BaseField: PrimeField,
 29    <C2 as CurveGroup>::BaseField: PrimeField,
 30    <C1 as Group>::ScalarField: Absorb,
 31    <C2 as Group>::ScalarField: Absorb,
 32    C1: CurveGroup<BaseField = C2::ScalarField, ScalarField = C2::BaseField>,
 33    for<'a> &'a GC1: GroupOpsBounds<'a, C1, GC1>,
 34    for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
 35    GC1: CurveVar<C1, <C2 as Group>::ScalarField>,
 36    GC1: ToConstraintFieldGadget<<C2 as Group>::ScalarField>,
 37    GC2: CurveVar<C2, <C2 as CurveGroup>::BaseField>,
 38{
 39    fn serialize_with_mode<W: Write>(
 40        &self,
 41        mut writer: W,
 42        compress: ark_serialize::Compress,
 43    ) -> Result<(), ark_serialize::SerializationError> {
 44        self.i.serialize_with_mode(&mut writer, compress)?;
 45        self.z_0.serialize_with_mode(&mut writer, compress)?;
 46        self.z_i.serialize_with_mode(&mut writer, compress)?;
 47        self.w_i.serialize_with_mode(&mut writer, compress)?;
 48        self.u_i.serialize_with_mode(&mut writer, compress)?;
 49        self.W_i.serialize_with_mode(&mut writer, compress)?;
 50        self.U_i.serialize_with_mode(&mut writer, compress)?;
 51        self.cf_W_i.serialize_with_mode(&mut writer, compress)?;
 52        self.cf_U_i.serialize_with_mode(&mut writer, compress)
 53    }
 54
 55    fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
 56        self.i.serialized_size(compress)
 57            + self.z_0.serialized_size(compress)
 58            + self.z_i.serialized_size(compress)
 59            + self.w_i.serialized_size(compress)
 60            + self.u_i.serialized_size(compress)
 61            + self.W_i.serialized_size(compress)
 62            + self.U_i.serialized_size(compress)
 63            + self.cf_W_i.serialized_size(compress)
 64            + self.cf_U_i.serialized_size(compress)
 65    }
 66
 67    fn serialize_compressed<W: Write>(
 68        &self,
 69        writer: W,
 70    ) -> Result<(), ark_serialize::SerializationError> {
 71        self.serialize_with_mode(writer, ark_serialize::Compress::Yes)
 72    }
 73
 74    fn compressed_size(&self) -> usize {
 75        self.serialized_size(ark_serialize::Compress::Yes)
 76    }
 77
 78    fn serialize_uncompressed<W: Write>(
 79        &self,
 80        writer: W,
 81    ) -> Result<(), ark_serialize::SerializationError> {
 82        self.serialize_with_mode(writer, ark_serialize::Compress::No)
 83    }
 84
 85    fn uncompressed_size(&self) -> usize {
 86        self.serialized_size(ark_serialize::Compress::No)
 87    }
 88}
 89
 90// Note that we can't derive or implement `CanonicalDeserialize` directly.
 91// This is because `CurveVar` notably does not implement the `Sync` trait.
 92impl<C1, GC1, C2, GC2, FC, CS1, CS2> Nova<C1, GC1, C2, GC2, FC, CS1, CS2>
 93where
 94    C1: CurveGroup,
 95    C2: CurveGroup,
 96    FC: FCircuit<CF1<C1>, Params = ()>,
 97    CS1: CommitmentScheme<C1>,
 98    CS2: CommitmentScheme<C2>,
 99    <C1 as CurveGroup>::BaseField: PrimeField,
100    <C2 as CurveGroup>::BaseField: PrimeField,
101    <C1 as Group>::ScalarField: Absorb,
102    <C2 as Group>::ScalarField: Absorb,
103    C1: CurveGroup<BaseField = C2::ScalarField, ScalarField = C2::BaseField>,
104    for<'a> &'a GC1: GroupOpsBounds<'a, C1, GC1>,
105    for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
106    GC1: CurveVar<C1, <C2 as Group>::ScalarField>,
107    GC1: ToConstraintFieldGadget<<C2 as Group>::ScalarField>,
108    GC2: CurveVar<C2, CF2<C2>>,
109    GC2: ToConstraintFieldGadget<<C2 as CurveGroup>::BaseField>,
110{
111    pub fn deserialize_nova<R: std::io::prelude::Read>(
112        mut reader: R,
113        compress: ark_serialize::Compress,
114        validate: ark_serialize::Validate,
115        prover_params: ProverParams<C1, C2, CS1, CS2>,
116        poseidon_config: PoseidonConfig<C1::ScalarField>,
117    ) -> Result<Self, ark_serialize::SerializationError> {
118        let i = C1::ScalarField::deserialize_with_mode(&mut reader, compress, validate)?;
119        let z_0 = Vec::<C1::ScalarField>::deserialize_with_mode(&mut reader, compress, validate)?;
120        let z_i = Vec::<C1::ScalarField>::deserialize_with_mode(&mut reader, compress, validate)?;
121        let w_i = Witness::<C1>::deserialize_with_mode(&mut reader, compress, validate)?;
122        let u_i = CommittedInstance::<C1>::deserialize_with_mode(&mut reader, compress, validate)?;
123        let W_i = Witness::<C1>::deserialize_with_mode(&mut reader, compress, validate)?;
124        let U_i = CommittedInstance::<C1>::deserialize_with_mode(&mut reader, compress, validate)?;
125        let cf_W_i = Witness::<C2>::deserialize_with_mode(&mut reader, compress, validate)?;
126        let cf_U_i =
127            CommittedInstance::<C2>::deserialize_with_mode(&mut reader, compress, validate)?;
128
129        let f_circuit = FC::new(()).unwrap();
130        let cs = ConstraintSystem::<C1::ScalarField>::new_ref();
131        let cs2 = ConstraintSystem::<C1::BaseField>::new_ref();
132        let augmented_F_circuit =
133            AugmentedFCircuit::<C1, C2, GC2, FC>::empty(&poseidon_config, f_circuit.clone());
134        let cf_circuit = CycleFoldCircuit::<C1, GC1>::empty();
135
136        augmented_F_circuit
137            .generate_constraints(cs.clone())
138            .map_err(|_| SerializationError::InvalidData)?;
139        cs.finalize();
140        let cs = cs.into_inner().ok_or(SerializationError::InvalidData)?;
141        let r1cs = extract_r1cs::<C1::ScalarField>(&cs);
142
143        cf_circuit
144            .generate_constraints(cs2.clone())
145            .map_err(|_| SerializationError::InvalidData)?;
146        cs2.finalize();
147        let cs2 = cs2.into_inner().ok_or(SerializationError::InvalidData)?;
148        let cf_r1cs = extract_r1cs::<C1::BaseField>(&cs2);
149
150        Ok(Nova {
151            _gc1: PhantomData,
152            _c2: PhantomData,
153            _gc2: PhantomData,
154            cs_pp: prover_params.cs_pp,
155            cf_cs_pp: prover_params.cf_cs_pp,
156            i,
157            z_0,
158            z_i,
159            w_i,
160            u_i,
161            W_i,
162            U_i,
163            cf_W_i,
164            cf_U_i,
165            r1cs,
166            cf_r1cs,
167            poseidon_config,
168            F: f_circuit,
169        })
170    }
171}
172
173#[cfg(test)]
174pub mod tests {
175    use ark_bn254::{constraints::GVar, Bn254, Fr, G1Projective as Projective};
176    use ark_grumpkin::{constraints::GVar as GVar2, Projective as Projective2};
177    use ark_poly_commit::kzg10::VerifierKey as KZGVerifierKey;
178    use ark_serialize::{CanonicalSerialize, Compress, Validate};
179    use std::{fs, io::Write};
180
181    use crate::{
182        commitment::{
183            kzg::{ProverKey as KZGProverKey, KZG},
184            pedersen::Pedersen,
185            CommitmentScheme,
186        },
187        folding::nova::{get_cs_params_len, Nova, ProverParams},
188        frontend::{tests::CubicFCircuit, FCircuit},
189        transcript::poseidon::poseidon_canonical_config,
190        FoldingScheme,
191    };
192
193    #[test]
194    fn test_serde_nova() {
195        let mut rng = ark_std::test_rng();
196        let poseidon_config = poseidon_canonical_config::<Fr>();
197        let F_circuit = CubicFCircuit::<Fr>::new(()).unwrap();
198        let (cs_len, cf_cs_len) =
199            get_cs_params_len::<Projective, GVar, Projective2, GVar2, CubicFCircuit<Fr>>(
200                &poseidon_config,
201                F_circuit,
202            )
203            .unwrap();
204        let (kzg_pk, _): (KZGProverKey<Projective>, KZGVerifierKey<Bn254>) =
205            KZG::<Bn254>::setup(&mut rng, cs_len).unwrap();
206        let (cf_pedersen_params, _) = Pedersen::<Projective2>::setup(&mut rng, cf_cs_len).unwrap();
207
208        // Initialize nova and make multiple `prove_step()`
209        type N = Nova<
210            Projective,
211            GVar,
212            Projective2,
213            GVar2,
214            CubicFCircuit<Fr>,
215            KZG<'static, Bn254>,
216            Pedersen<Projective2>,
217        >;
218        let prover_params =
219            ProverParams::<Projective, Projective2, KZG<Bn254>, Pedersen<Projective2>> {
220                poseidon_config: poseidon_config.clone(),
221                cs_pp: kzg_pk.clone(),
222                cf_cs_pp: cf_pedersen_params.clone(),
223            };
224
225        let z_0 = vec![Fr::from(3_u32)];
226        let mut nova = N::init(&prover_params, F_circuit, z_0.clone()).unwrap();
227
228        let num_steps: usize = 3;
229        for _ in 0..num_steps {
230            nova.prove_step(&mut rng, vec![]).unwrap();
231        }
232
233        let mut writer = vec![];
234        assert!(nova
235            .serialize_with_mode(&mut writer, ark_serialize::Compress::No)
236            .is_ok());
237
238        let mut file = fs::OpenOptions::new()
239            .create(true)
240            .write(true)
241            .open("./nova.serde")
242            .unwrap();
243
244        file.write_all(&writer).unwrap();
245
246        let bytes = fs::read("./nova.serde").unwrap();
247
248        let mut deserialized_nova = Nova::<
249            Projective,
250            GVar,
251            Projective2,
252            GVar2,
253            CubicFCircuit<Fr>,
254            KZG<Bn254>,
255            Pedersen<Projective2>,
256        >::deserialize_nova(
257            bytes.as_slice(),
258            Compress::No,
259            Validate::No,
260            prover_params,
261            poseidon_config,
262        )
263        .unwrap();
264
265        assert_eq!(nova.i, deserialized_nova.i);
266
267        let num_steps: usize = 3;
268        for _ in 0..num_steps {
269            deserialized_nova.prove_step(&mut rng, vec![]).unwrap();
270            nova.prove_step(&mut rng, vec![]).unwrap();
271        }
272
273        assert_eq!(deserialized_nova.w_i, nova.w_i);
274    }
275}