sonobe/folding-schemes/src/folding/mod.rs
folding-schemes/src/folding/mod.rsRaw
1pub mod circuits;
2pub mod hypernova;
3pub mod nova;
4pub mod protogalaxy;
5pub mod traits;
6
7#[cfg(test)]
8pub mod tests {
9 use ark_ec::CurveGroup;
10 use ark_ff::PrimeField;
11 use ark_pallas::{constraints::GVar as GVar1, Fr, Projective as G1};
12 use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
13 use ark_vesta::{constraints::GVar as GVar2, Projective as G2};
14 use std::io::Write;
15
16 use crate::commitment::pedersen::Pedersen;
17 use crate::folding::{
18 hypernova::HyperNova,
19 nova::{Nova, PreprocessorParam as NovaPreprocessorParam},
20 protogalaxy::ProtoGalaxy,
21 };
22 use crate::frontend::utils::CubicFCircuit;
23 use crate::frontend::FCircuit;
24 use crate::transcript::poseidon::poseidon_canonical_config;
25 use crate::Error;
26 use crate::FoldingScheme;
27
28 /// tests the IVC proofs and its serializers for the 3 implemented IVCs: Nova, HyperNova and
29 /// ProtoGalaxy.
30 #[test]
31 fn test_serialize_ivc_nova_hypernova_protogalaxy() {
32 let poseidon_config = poseidon_canonical_config::<Fr>();
33 type FC = CubicFCircuit<Fr>;
34 let f_circuit = FC::new(()).unwrap();
35
36 // test Nova
37 type N = Nova<G1, GVar1, G2, GVar2, FC, Pedersen<G1>, Pedersen<G2>, false>;
38 let prep_param = NovaPreprocessorParam::new(poseidon_config.clone(), f_circuit);
39 test_serialize_ivc_opt::<G1, G2, FC, N>("nova".to_string(), prep_param.clone()).unwrap();
40
41 // test HyperNova
42 type HN = HyperNova<
43 G1,
44 GVar1,
45 G2,
46 GVar2,
47 FC,
48 Pedersen<G1>,
49 Pedersen<G2>,
50 1, // mu
51 1, // nu
52 false,
53 >;
54 test_serialize_ivc_opt::<G1, G2, FC, HN>("hypernova".to_string(), prep_param).unwrap();
55
56 // test ProtoGalaxy
57 type P = ProtoGalaxy<G1, GVar1, G2, GVar2, FC, Pedersen<G1>, Pedersen<G2>>;
58 let prep_param = (poseidon_config, f_circuit);
59 test_serialize_ivc_opt::<G1, G2, FC, P>("protogalaxy".to_string(), prep_param).unwrap();
60 }
61
62 fn test_serialize_ivc_opt<
63 C1: CurveGroup,
64 C2: CurveGroup,
65 FC: FCircuit<C1::ScalarField, Params = ()>,
66 FS: FoldingScheme<C1, C2, FC>,
67 >(
68 name: String,
69 prep_param: FS::PreprocessorParam,
70 ) -> Result<(), Error>
71 where
72 C1: CurveGroup<BaseField = C2::ScalarField, ScalarField = C2::BaseField>,
73 C2::BaseField: PrimeField,
74 FC: FCircuit<C1::ScalarField>,
75 {
76 let mut rng = ark_std::test_rng();
77 let F_circuit = FC::new(())?;
78
79 let fs_params = FS::preprocess(&mut rng, &prep_param)?;
80
81 let z_0 = vec![C1::ScalarField::from(3_u32)];
82 let mut fs = FS::init(&fs_params, F_circuit, z_0.clone()).unwrap();
83
84 // perform multiple IVC steps (internally folding)
85 let num_steps: usize = 3;
86 for _ in 0..num_steps {
87 fs.prove_step(&mut rng, vec![], None).unwrap();
88 }
89
90 // verify the IVCProof
91 let ivc_proof: FS::IVCProof = fs.ivc_proof();
92 FS::verify(fs_params.1.clone(), ivc_proof.clone()).unwrap();
93
94 // serialize the IVCProof and store it in a file
95 let mut writer = vec![];
96 assert!(ivc_proof.serialize_compressed(&mut writer).is_ok());
97
98 let mut file = std::fs::OpenOptions::new()
99 .create(true)
100 .write(true)
101 .open(format!("./ivc_proof-{}.serialized", name))
102 .unwrap();
103 file.write_all(&writer).unwrap();
104
105 // read the IVCProof from the file deserializing it
106 let bytes = std::fs::read(format!("./ivc_proof-{}.serialized", name)).unwrap();
107 let deserialized_ivc_proof =
108 FS::IVCProof::deserialize_compressed(bytes.as_slice()).unwrap();
109 // verify deserialized IVCProof
110 FS::verify(fs_params.1.clone(), deserialized_ivc_proof.clone()).unwrap();
111
112 // build the FS from the given IVCProof, FC::Params, ProverParams and VerifierParams
113 let mut new_fs = FS::from_ivc_proof(deserialized_ivc_proof, (), fs_params.clone()).unwrap();
114
115 // serialize the Nova params
116 let mut fs_pp_serialized = vec![];
117 fs_params
118 .0
119 .serialize_compressed(&mut fs_pp_serialized)
120 .unwrap();
121 let mut fs_vp_serialized = vec![];
122 fs_params
123 .1
124 .serialize_compressed(&mut fs_vp_serialized)
125 .unwrap();
126
127 // deserialize the Nova params. This would be done by the client reading from a file
128 let _fs_pp_deserialized = FS::pp_deserialize_with_mode(
129 &mut fs_pp_serialized.as_slice(),
130 ark_serialize::Compress::Yes,
131 ark_serialize::Validate::Yes,
132 (), // FCircuit's Params
133 )
134 .unwrap();
135
136 // perform several IVC steps on both the original FS instance and the recovered from the
137 // serialization new FS instance
138 let num_steps: usize = 3;
139 for _ in 0..num_steps {
140 new_fs.prove_step(&mut rng, vec![], None).unwrap();
141 fs.prove_step(&mut rng, vec![], None).unwrap();
142 }
143
144 // check that the IVCProofs from both FS instances are equal
145 assert_eq!(new_fs.ivc_proof(), fs.ivc_proof());
146
147 let fs_vp_deserialized = FS::vp_deserialize_with_mode(
148 &mut fs_vp_serialized.as_slice(),
149 ark_serialize::Compress::Yes,
150 ark_serialize::Validate::Yes,
151 (), // fcircuit_params
152 )
153 .unwrap();
154
155 // get the IVCProof
156 let ivc_proof: FS::IVCProof = new_fs.ivc_proof();
157
158 // serialize IVCProof
159 let mut ivc_proof_serialized = vec![];
160 assert!(ivc_proof
161 .serialize_compressed(&mut ivc_proof_serialized)
162 .is_ok());
163 // deserialize IVCProof
164 let ivc_proof_deserialized =
165 FS::IVCProof::deserialize_compressed(ivc_proof_serialized.as_slice()).unwrap();
166
167 // verify the last IVCProof from the recovered from serialization FS
168 FS::verify(fs_vp_deserialized.clone(), ivc_proof_deserialized).unwrap();
169
170 Ok(())
171 }
172}