arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/folding-schemes/src/folding/hypernova/serialize.rs
folding-schemes/src/folding/hypernova/serialize.rsRaw
  1use crate::arith::ccs::CCS;
  2use crate::arith::r1cs::R1CS;
  3use crate::folding::hypernova::ProverParams;
  4use crate::folding::hypernova::VerifierParams;
  5use ark_crypto_primitives::sponge::poseidon::PoseidonConfig;
  6use ark_crypto_primitives::sponge::Absorb;
  7use ark_ec::{CurveGroup, Group};
  8use ark_ff::PrimeField;
  9use ark_r1cs_std::groups::{CurveVar, GroupOpsBounds};
 10use ark_r1cs_std::ToConstraintFieldGadget;
 11use ark_serialize::CanonicalDeserialize;
 12use ark_serialize::{CanonicalSerialize, Compress, SerializationError, Validate};
 13use ark_std::marker::PhantomData;
 14
 15use crate::folding::hypernova::cccs::CCCS;
 16use crate::folding::hypernova::lcccs::LCCCS;
 17use crate::folding::hypernova::Witness;
 18use crate::folding::nova::{
 19    CommittedInstance as CycleFoldCommittedInstance, Witness as CycleFoldWitness,
 20};
 21use crate::FoldingScheme;
 22use crate::{
 23    commitment::CommitmentScheme,
 24    folding::{circuits::CF2, nova::PreprocessorParam},
 25    frontend::FCircuit,
 26};
 27
 28use super::HyperNova;
 29
 30impl<C1, GC1, C2, GC2, FC, CS1, CS2, const MU: usize, const NU: usize, const H: bool>
 31    CanonicalSerialize for HyperNova<C1, GC1, C2, GC2, FC, CS1, CS2, MU, NU, H>
 32where
 33    C1: CurveGroup,
 34    GC1: CurveVar<C1, CF2<C1>> + ToConstraintFieldGadget<CF2<C1>>,
 35    C2: CurveGroup,
 36    GC2: CurveVar<C2, CF2<C2>>,
 37    FC: FCircuit<C1::ScalarField>,
 38    CS1: CommitmentScheme<C1, H>,
 39    CS2: CommitmentScheme<C2, H>,
 40{
 41    fn serialize_compressed<W: std::io::prelude::Write>(
 42        &self,
 43        writer: W,
 44    ) -> Result<(), ark_serialize::SerializationError> {
 45        self.serialize_with_mode(writer, ark_serialize::Compress::Yes)
 46    }
 47
 48    fn compressed_size(&self) -> usize {
 49        self.serialized_size(ark_serialize::Compress::Yes)
 50    }
 51
 52    fn serialize_uncompressed<W: std::io::prelude::Write>(
 53        &self,
 54        writer: W,
 55    ) -> Result<(), ark_serialize::SerializationError> {
 56        self.serialize_with_mode(writer, ark_serialize::Compress::No)
 57    }
 58
 59    fn uncompressed_size(&self) -> usize {
 60        self.serialized_size(ark_serialize::Compress::No)
 61    }
 62
 63    fn serialize_with_mode<W: std::io::prelude::Write>(
 64        &self,
 65        mut writer: W,
 66        compress: ark_serialize::Compress,
 67    ) -> Result<(), ark_serialize::SerializationError> {
 68        self.pp_hash.serialize_with_mode(&mut writer, compress)?;
 69        self.i.serialize_with_mode(&mut writer, compress)?;
 70        self.z_0.serialize_with_mode(&mut writer, compress)?;
 71        self.z_i.serialize_with_mode(&mut writer, compress)?;
 72        self.W_i.serialize_with_mode(&mut writer, compress)?;
 73        self.U_i.serialize_with_mode(&mut writer, compress)?;
 74        self.w_i.serialize_with_mode(&mut writer, compress)?;
 75        self.u_i.serialize_with_mode(&mut writer, compress)?;
 76        self.cf_W_i.serialize_with_mode(&mut writer, compress)?;
 77        self.cf_U_i.serialize_with_mode(&mut writer, compress)
 78    }
 79
 80    fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
 81        self.pp_hash.serialized_size(compress)
 82            + self.i.serialized_size(compress)
 83            + self.z_0.serialized_size(compress)
 84            + self.z_i.serialized_size(compress)
 85            + self.W_i.serialized_size(compress)
 86            + self.U_i.serialized_size(compress)
 87            + self.w_i.serialized_size(compress)
 88            + self.u_i.serialized_size(compress)
 89            + self.cf_W_i.serialized_size(compress)
 90            + self.cf_U_i.serialized_size(compress)
 91    }
 92}
 93
 94impl<C1, GC1, C2, GC2, FC, CS1, CS2, const MU: usize, const NU: usize, const H: bool>
 95    HyperNova<C1, GC1, C2, GC2, FC, CS1, CS2, MU, NU, H>
 96where
 97    C1: CurveGroup,
 98    GC1: CurveVar<C1, CF2<C1>> + ToConstraintFieldGadget<CF2<C1>>,
 99    C2: CurveGroup,
100    GC2: CurveVar<C2, CF2<C2>> + ToConstraintFieldGadget<CF2<C2>>,
101    FC: FCircuit<C1::ScalarField, Params = ()>,
102    CS1: CommitmentScheme<C1, H>,
103    CS2: CommitmentScheme<C2, H>,
104    <C1 as CurveGroup>::BaseField: PrimeField,
105    <C2 as CurveGroup>::BaseField: PrimeField,
106    <C1 as Group>::ScalarField: Absorb,
107    <C2 as Group>::ScalarField: Absorb,
108    C1: CurveGroup<BaseField = C2::ScalarField, ScalarField = C2::BaseField>,
109    for<'a> &'a GC1: GroupOpsBounds<'a, C1, GC1>,
110    for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>,
111{
112    #[allow(clippy::too_many_arguments)]
113    pub fn deserialize_hypernova<R: std::io::prelude::Read>(
114        mut reader: R,
115        compress: Compress,
116        validate: Validate,
117        poseidon_config: PoseidonConfig<C1::ScalarField>,
118        cs_pp: CS1::ProverParams,
119        cs_vp: CS1::VerifierParams,
120        cf_cs_pp: CS2::ProverParams,
121        cf_cs_vp: CS2::VerifierParams,
122    ) -> Result<Self, SerializationError> {
123        let f_circuit = FC::new(()).unwrap();
124        let prep_param = PreprocessorParam {
125            poseidon_config: poseidon_config.clone(),
126            F: f_circuit.clone(),
127            cs_pp: Some(cs_pp.clone()),
128            cs_vp: Some(cs_vp.clone()),
129            cf_cs_pp: Some(cf_cs_pp.clone()),
130            cf_cs_vp: Some(cf_cs_vp.clone()),
131        };
132        // `test_rng` won't be used in `preprocess`, since parameters have already been initialized
133        let (prover_params, verifier_params) = Self::preprocess(ark_std::test_rng(), &prep_param)
134            .or(Err(SerializationError::InvalidData))?;
135        let pp_hash = C1::ScalarField::deserialize_with_mode(&mut reader, compress, validate)?;
136        let i = C1::ScalarField::deserialize_with_mode(&mut reader, compress, validate)?;
137        let z_0 = Vec::<C1::ScalarField>::deserialize_with_mode(&mut reader, compress, validate)?;
138        let z_i = Vec::<C1::ScalarField>::deserialize_with_mode(&mut reader, compress, validate)?;
139        let W_i =
140            Witness::<C1::ScalarField>::deserialize_with_mode(&mut reader, compress, validate)?;
141        let U_i = LCCCS::<C1>::deserialize_with_mode(&mut reader, compress, validate)?;
142        let w_i =
143            Witness::<C1::ScalarField>::deserialize_with_mode(&mut reader, compress, validate)?;
144        let u_i = CCCS::<C1>::deserialize_with_mode(&mut reader, compress, validate)?;
145        let cf_W_i =
146            CycleFoldWitness::<C2>::deserialize_with_mode(&mut reader, compress, validate)?;
147        let cf_U_i = CycleFoldCommittedInstance::<C2>::deserialize_with_mode(
148            &mut reader,
149            compress,
150            validate,
151        )?;
152        let ccs = prover_params.ccs.ok_or(SerializationError::InvalidData)?;
153
154        Ok(HyperNova {
155            _gc1: PhantomData,
156            _c2: PhantomData,
157            _gc2: PhantomData,
158            ccs,
159            cf_r1cs: verifier_params.cf_r1cs,
160            poseidon_config,
161            cs_pp,
162            cf_cs_pp,
163            F: f_circuit,
164            pp_hash,
165            i,
166            z_0,
167            z_i,
168            W_i,
169            U_i,
170            w_i,
171            u_i,
172            cf_W_i,
173            cf_U_i,
174        })
175    }
176}
177
178impl<
179        C1: CurveGroup,
180        C2: CurveGroup,
181        CS1: CommitmentScheme<C1, H>,
182        CS2: CommitmentScheme<C2, H>,
183        const H: bool,
184    > CanonicalSerialize for ProverParams<C1, C2, CS1, CS2, H>
185{
186    fn serialize_compressed<W: std::io::prelude::Write>(
187        &self,
188        writer: W,
189    ) -> Result<(), SerializationError> {
190        self.serialize_with_mode(writer, Compress::Yes)
191    }
192
193    fn compressed_size(&self) -> usize {
194        self.serialized_size(Compress::Yes)
195    }
196
197    fn serialize_uncompressed<W: std::io::prelude::Write>(
198        &self,
199        writer: W,
200    ) -> Result<(), SerializationError> {
201        self.serialize_with_mode(writer, Compress::No)
202    }
203
204    fn uncompressed_size(&self) -> usize {
205        self.serialized_size(Compress::No)
206    }
207
208    fn serialize_with_mode<W: std::io::prelude::Write>(
209        &self,
210        mut writer: W,
211        compress: Compress,
212    ) -> Result<(), SerializationError> {
213        self.cs_pp.serialize_with_mode(&mut writer, compress)?;
214        self.cf_cs_pp.serialize_with_mode(&mut writer, compress)
215    }
216
217    fn serialized_size(&self, compress: Compress) -> usize {
218        self.cs_pp.serialized_size(compress) + self.cf_cs_pp.serialized_size(compress)
219    }
220}
221
222impl<
223        C1: CurveGroup,
224        C2: CurveGroup,
225        CS1: CommitmentScheme<C1, H>,
226        CS2: CommitmentScheme<C2, H>,
227        const H: bool,
228    > ProverParams<C1, C2, CS1, CS2, H>
229{
230    pub fn deserialize_prover_params<R: std::io::prelude::Read>(
231        mut reader: R,
232        compress: Compress,
233        validate: Validate,
234        ccs: &Option<CCS<C1::ScalarField>>,
235        poseidon_config: &PoseidonConfig<C1::ScalarField>,
236    ) -> Result<Self, SerializationError> {
237        let cs_pp = CS1::ProverParams::deserialize_with_mode(&mut reader, compress, validate)?;
238        let cf_cs_pp = CS2::ProverParams::deserialize_with_mode(&mut reader, compress, validate)?;
239
240        Ok(ProverParams {
241            cs_pp,
242            cf_cs_pp,
243            ccs: ccs.clone(),
244            poseidon_config: poseidon_config.clone(),
245        })
246    }
247}
248
249impl<
250        C1: CurveGroup,
251        C2: CurveGroup,
252        CS1: CommitmentScheme<C1, H>,
253        CS2: CommitmentScheme<C2, H>,
254        const H: bool,
255    > CanonicalSerialize for VerifierParams<C1, C2, CS1, CS2, H>
256{
257    fn serialize_compressed<W: std::io::prelude::Write>(
258        &self,
259        writer: W,
260    ) -> Result<(), SerializationError> {
261        self.serialize_with_mode(writer, Compress::Yes)
262    }
263
264    fn compressed_size(&self) -> usize {
265        self.serialized_size(Compress::Yes)
266    }
267
268    fn serialize_uncompressed<W: std::io::prelude::Write>(
269        &self,
270        writer: W,
271    ) -> Result<(), SerializationError> {
272        self.serialize_with_mode(writer, Compress::No)
273    }
274
275    fn uncompressed_size(&self) -> usize {
276        self.serialized_size(Compress::No)
277    }
278
279    fn serialize_with_mode<W: std::io::prelude::Write>(
280        &self,
281        mut writer: W,
282        compress: Compress,
283    ) -> Result<(), SerializationError> {
284        self.cf_r1cs.serialize_with_mode(&mut writer, compress)?;
285        self.cs_vp.serialize_with_mode(&mut writer, compress)?;
286        self.cf_cs_vp.serialize_with_mode(&mut writer, compress)
287    }
288
289    fn serialized_size(&self, compress: Compress) -> usize {
290        self.cf_r1cs.serialized_size(compress)
291            + self.cs_vp.serialized_size(compress)
292            + self.cf_cs_vp.serialized_size(compress)
293    }
294}
295
296impl<
297        C1: CurveGroup,
298        C2: CurveGroup,
299        CS1: CommitmentScheme<C1, H>,
300        CS2: CommitmentScheme<C2, H>,
301        const H: bool,
302    > VerifierParams<C1, C2, CS1, CS2, H>
303{
304    pub fn deserialize_verifier_params<R: std::io::Read>(
305        mut reader: R,
306        compress: Compress,
307        validate: Validate,
308        ccs: &CCS<C1::ScalarField>,
309        poseidon_config: &PoseidonConfig<C1::ScalarField>,
310    ) -> Result<Self, SerializationError> {
311        let cf_r1cs = R1CS::deserialize_with_mode(&mut reader, compress, validate)?;
312        let cs_vp = CS1::VerifierParams::deserialize_with_mode(&mut reader, compress, validate)?;
313        let cf_cs_vp = CS2::VerifierParams::deserialize_with_mode(&mut reader, compress, validate)?;
314        Ok(VerifierParams {
315            ccs: ccs.clone(),
316            poseidon_config: poseidon_config.clone(),
317            cf_r1cs,
318            cs_vp,
319            cf_cs_vp,
320        })
321    }
322}
323
324#[cfg(test)]
325pub mod tests {
326    use crate::FoldingScheme;
327    use crate::MultiFolding;
328    use ark_serialize::{Compress, Validate, Write};
329    use std::fs;
330
331    use crate::{
332        commitment::{kzg::KZG, pedersen::Pedersen},
333        folding::hypernova::{tests::test_ivc_opt, HyperNova},
334        frontend::{utils::CubicFCircuit, FCircuit},
335        transcript::poseidon::poseidon_canonical_config,
336    };
337    use ark_bn254::{constraints::GVar, Bn254, Fr, G1Projective as Projective};
338    use ark_grumpkin::{constraints::GVar as GVar2, Projective as Projective2};
339    use ark_serialize::CanonicalSerialize;
340
341    #[test]
342    fn test_serde_hypernova() {
343        let poseidon_config = poseidon_canonical_config::<Fr>();
344        let F_circuit = CubicFCircuit::<Fr>::new(()).unwrap();
345        let (mut hn, (_, verifier_params), _, _, _) = test_ivc_opt::<
346            KZG<Bn254>,
347            Pedersen<Projective2>,
348            false,
349        >(poseidon_config.clone(), F_circuit);
350
351        let mut writer = vec![];
352        assert!(hn.serialize_compressed(&mut writer).is_ok());
353        let mut writer = vec![];
354        assert!(hn.serialize_uncompressed(&mut writer).is_ok());
355
356        let mut file = fs::OpenOptions::new()
357            .create(true)
358            .write(true)
359            .open("./hypernova.serde")
360            .unwrap();
361
362        file.write_all(&writer).unwrap();
363
364        let bytes = fs::read("./hypernova.serde").unwrap();
365
366        let mut hn_deserialized = HyperNova::<
367            Projective,
368            GVar,
369            Projective2,
370            GVar2,
371            CubicFCircuit<Fr>,
372            KZG<Bn254>,
373            Pedersen<Projective2>,
374            2,
375            3,
376            false,
377        >::deserialize_hypernova(
378            bytes.as_slice(),
379            Compress::No,
380            Validate::No,
381            poseidon_config,
382            hn.cs_pp.clone(),
383            verifier_params.cs_vp,
384            hn.cf_cs_pp.clone(),
385            verifier_params.cf_cs_vp,
386        )
387        .unwrap();
388
389        assert_eq!(hn.i, hn_deserialized.i);
390
391        let mut rng = ark_std::test_rng();
392        for _ in 0..3 {
393            // prepare some new instances to fold in the multifolding step
394            let mut lcccs = vec![];
395            for j in 0..1 {
396                let instance_state = vec![Fr::from(j as u32 + 85_u32)];
397                let (U, W) = hn
398                    .new_running_instance(&mut rng, instance_state, vec![])
399                    .unwrap();
400                lcccs.push((U, W));
401            }
402            let mut cccs = vec![];
403            for j in 0..2 {
404                let instance_state = vec![Fr::from(j as u32 + 15_u32)];
405                let (u, w) = hn
406                    .new_incoming_instance(&mut rng, instance_state, vec![])
407                    .unwrap();
408                cccs.push((u, w));
409            }
410
411            hn.prove_step(&mut rng, vec![], Some((lcccs.clone(), cccs.clone())))
412                .unwrap();
413            hn_deserialized
414                .prove_step(&mut rng, vec![], Some((lcccs, cccs)))
415                .unwrap();
416        }
417
418        assert_eq!(hn.z_i, hn_deserialized.z_i);
419    }
420}