arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/folding-schemes/src/frontend/noname/mod.rs
folding-schemes/src/frontend/noname/mod.rsRaw
  1use crate::Error;
  2use ark_noname::sonobe::NonameSonobeCircuit;
  3use ark_r1cs_std::alloc::AllocVar;
  4use ark_r1cs_std::fields::fp::FpVar;
  5use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError};
  6use num_bigint::BigUint;
  7use std::marker::PhantomData;
  8
  9use self::utils::NonameInputs;
 10
 11use super::FCircuit;
 12use ark_ff::PrimeField;
 13use ark_noname::utils::compile_source_code;
 14use noname::backends::{r1cs::R1CS as R1CSNoname, BackendField};
 15use noname::witness::CompiledCircuit;
 16pub mod utils;
 17#[derive(Debug, Clone)]
 18pub struct NonameFCircuit<F: PrimeField, BF: BackendField> {
 19    pub state_len: usize,
 20    pub external_inputs_len: usize,
 21    pub circuit: CompiledCircuit<R1CSNoname<BF>>,
 22    _f: PhantomData<F>,
 23}
 24
 25impl<F: PrimeField, BF: BackendField> FCircuit<F> for NonameFCircuit<F, BF> {
 26    type Params = (String, usize, usize);
 27
 28    fn new(params: Self::Params) -> Result<Self, crate::Error> {
 29        let (code, state_len, external_inputs_len) = params;
 30        let compiled_circuit = compile_source_code::<BF>(&code).map_err(|_| {
 31            Error::Other("Encountered an error while compiling a noname circuit".to_owned())
 32        })?;
 33        Ok(NonameFCircuit {
 34            state_len,
 35            external_inputs_len,
 36            circuit: compiled_circuit,
 37            _f: PhantomData,
 38        })
 39    }
 40
 41    fn state_len(&self) -> usize {
 42        self.state_len
 43    }
 44
 45    fn external_inputs_len(&self) -> usize {
 46        self.external_inputs_len
 47    }
 48
 49    fn step_native(
 50        &self,
 51        _i: usize,
 52        z_i: Vec<F>,
 53        external_inputs: Vec<F>,
 54    ) -> Result<Vec<F>, crate::Error> {
 55        let wtns_external_inputs =
 56            NonameInputs::from((&external_inputs, "external_inputs".to_string()));
 57        let wtns_ivc_inputs = NonameInputs::from((&z_i, "ivc_inputs".to_string()));
 58
 59        let noname_witness = self
 60            .circuit
 61            .generate_witness(wtns_ivc_inputs.0, wtns_external_inputs.0)
 62            .map_err(|e| Error::WitnessCalculationError(e.to_string()))?;
 63
 64        let z_i1_end_index = z_i.len() + 1;
 65        let assigned_z_i1 = (1..z_i1_end_index)
 66            .map(|idx| {
 67                let value: BigUint = Into::into(noname_witness.witness[idx]);
 68                F::from(value)
 69            })
 70            .collect();
 71
 72        Ok(assigned_z_i1)
 73    }
 74
 75    fn generate_step_constraints(
 76        &self,
 77        cs: ConstraintSystemRef<F>,
 78        _i: usize,
 79        z_i: Vec<FpVar<F>>,
 80        external_inputs: Vec<FpVar<F>>,
 81    ) -> Result<Vec<FpVar<F>>, SynthesisError> {
 82        let wtns_external_inputs =
 83            NonameInputs::from_fpvars((&external_inputs, "external_inputs".to_string()))?;
 84        let wtns_ivc_inputs = NonameInputs::from_fpvars((&z_i, "ivc_inputs".to_string()))?;
 85        let noname_witness = self
 86            .circuit
 87            .generate_witness(wtns_ivc_inputs.0, wtns_external_inputs.0)
 88            .map_err(|_| SynthesisError::Unsatisfiable)?;
 89        let z_i1_end_index = z_i.len() + 1;
 90        let assigned_z_i1: Vec<FpVar<F>> = (1..z_i1_end_index)
 91            .map(|idx| -> Result<FpVar<F>, SynthesisError> {
 92                // the assigned zi1 is of the same size than the initial zi and is located in the
 93                // output of the witness vector
 94                // we prefer to assign z_i1 here since (1) we have to return it, (2) we cant return
 95                // anything with the `generate_constraints` method used below
 96                let value: BigUint = Into::into(noname_witness.witness[idx]);
 97                let field_element = F::from(value);
 98                FpVar::<F>::new_witness(cs.clone(), || Ok(field_element))
 99            })
100            .collect::<Result<Vec<FpVar<F>>, SynthesisError>>()?;
101
102        let noname_circuit = NonameSonobeCircuit {
103            compiled_circuit: self.circuit.clone(),
104            witness: noname_witness,
105            assigned_z_i: &z_i,
106            assigned_external_inputs: &external_inputs,
107            assigned_z_i1: &assigned_z_i1,
108        };
109        noname_circuit.generate_constraints(cs.clone())?;
110
111        Ok(assigned_z_i1)
112    }
113}
114
115#[cfg(test)]
116mod tests {
117
118    use ark_bn254::Fr;
119    use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar};
120    use noname::backends::r1cs::R1csBn254Field;
121
122    use crate::frontend::FCircuit;
123
124    use super::NonameFCircuit;
125    use ark_relations::r1cs::ConstraintSystem;
126
127    const NONAME_CIRCUIT_EXTERNAL_INPUTS: &str =
128        "fn main(pub ivc_inputs: [Field; 2], external_inputs: [Field; 2]) -> [Field; 2] {
129    let xx = external_inputs[0] + ivc_inputs[0];
130    let yy = external_inputs[1] * ivc_inputs[1];
131    assert_eq(yy, xx);
132    return [xx, yy];
133}";
134
135    const NONAME_CIRCUIT_NO_EXTERNAL_INPUTS: &str =
136        "fn main(pub ivc_inputs: [Field; 2]) -> [Field; 2] {
137    let out = ivc_inputs[0] * ivc_inputs[1];
138    return [out, ivc_inputs[1]];
139}";
140
141    #[test]
142    fn test_step_native() {
143        let cs = ConstraintSystem::<Fr>::new_ref();
144        let params = (NONAME_CIRCUIT_EXTERNAL_INPUTS.to_owned(), 2, 2);
145        let circuit = NonameFCircuit::<Fr, R1csBn254Field>::new(params).unwrap();
146        let inputs_public = vec![Fr::from(2), Fr::from(5)];
147        let inputs_private = vec![Fr::from(8), Fr::from(2)];
148
149        let ivc_inputs_var =
150            Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(inputs_public.clone())).unwrap();
151        let external_inputs_var =
152            Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(inputs_private.clone())).unwrap();
153
154        let z_i1 = circuit
155            .generate_step_constraints(cs.clone(), 0, ivc_inputs_var, external_inputs_var)
156            .unwrap();
157        let z_i1_native = circuit
158            .step_native(0, inputs_public, inputs_private)
159            .unwrap();
160
161        assert_eq!(z_i1[0].value().unwrap(), z_i1_native[0]);
162        assert_eq!(z_i1[1].value().unwrap(), z_i1_native[1]);
163    }
164
165    #[test]
166    fn test_step_constraints() {
167        let cs = ConstraintSystem::<Fr>::new_ref();
168        let params = (NONAME_CIRCUIT_EXTERNAL_INPUTS.to_owned(), 2, 2);
169        let circuit = NonameFCircuit::<Fr, R1csBn254Field>::new(params).unwrap();
170        let inputs_public = vec![Fr::from(2), Fr::from(5)];
171        let inputs_private = vec![Fr::from(8), Fr::from(2)];
172
173        let ivc_inputs_var =
174            Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(inputs_public)).unwrap();
175        let external_inputs_var =
176            Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(inputs_private)).unwrap();
177
178        let z_i1 = circuit
179            .generate_step_constraints(cs.clone(), 0, ivc_inputs_var, external_inputs_var)
180            .unwrap();
181        assert!(cs.is_satisfied().unwrap());
182        assert_eq!(z_i1[0].value().unwrap(), Fr::from(10_u8));
183        assert_eq!(z_i1[1].value().unwrap(), Fr::from(10_u8));
184    }
185
186    #[test]
187    fn test_generate_constraints_no_external_inputs() {
188        let cs = ConstraintSystem::<Fr>::new_ref();
189        let params = (NONAME_CIRCUIT_NO_EXTERNAL_INPUTS.to_owned(), 2, 0);
190        let inputs_public = vec![Fr::from(2), Fr::from(5)];
191
192        let ivc_inputs_var =
193            Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(inputs_public)).unwrap();
194
195        let f_circuit = NonameFCircuit::<Fr, R1csBn254Field>::new(params).unwrap();
196        f_circuit
197            .generate_step_constraints(cs.clone(), 0, ivc_inputs_var, vec![])
198            .unwrap();
199        assert!(cs.is_satisfied().unwrap());
200    }
201}