arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/src/frontend/arkworks/mod.rs
src/frontend/arkworks/mod.rsRaw
  1/// arkworks frontend
  2use ark_ff::PrimeField;
  3use ark_relations::r1cs::ConstraintSystem;
  4
  5use crate::ccs::r1cs::R1CS;
  6use crate::utils::vec::SparseMatrix;
  7
  8/// extracts arkworks ConstraintSystem matrices into crate::utils::vec::SparseMatrix format, and
  9/// extracts public inputs and witness into z vector. Returns a tuple containing (R1CS, z).
 10pub fn extract_r1cs_and_z<F: PrimeField>(cs: &ConstraintSystem<F>) -> (R1CS<F>, Vec<F>) {
 11    let r1cs = extract_r1cs(cs);
 12
 13    // z = (1, x, w)
 14    let z = extract_z(cs);
 15
 16    (r1cs, z)
 17}
 18
 19/// extracts arkworks ConstraintSystem matrices into crate::utils::vec::SparseMatrix format as R1CS
 20/// struct.
 21pub fn extract_r1cs<F: PrimeField>(cs: &ConstraintSystem<F>) -> R1CS<F> {
 22    let m = cs.to_matrices().unwrap();
 23
 24    let n_rows = cs.num_constraints;
 25    let n_cols = cs.num_instance_variables + cs.num_witness_variables; // cs.num_instance_variables already counts the 1
 26
 27    let A = SparseMatrix::<F> {
 28        n_rows,
 29        n_cols,
 30        coeffs: m.a,
 31    };
 32    let B = SparseMatrix::<F> {
 33        n_rows,
 34        n_cols,
 35        coeffs: m.b,
 36    };
 37    let C = SparseMatrix::<F> {
 38        n_rows,
 39        n_cols,
 40        coeffs: m.c,
 41    };
 42
 43    R1CS::<F> {
 44        l: cs.num_instance_variables - 1, // -1 to substract the first '1'
 45        A,
 46        B,
 47        C,
 48    }
 49}
 50
 51/// extracts public inputs and witness into z vector from arkworks ConstraintSystem.
 52pub fn extract_z<F: PrimeField>(cs: &ConstraintSystem<F>) -> Vec<F> {
 53    // z = (1, x, w)
 54    [
 55        // 1 is already included in cs.instance_assignment
 56        cs.instance_assignment.clone(),
 57        cs.witness_assignment.clone(),
 58    ]
 59    .concat()
 60}
 61
 62/// extracts the witness and the public inputs from arkworks ConstraintSystem.
 63pub fn extract_w_x<F: PrimeField>(cs: &ConstraintSystem<F>) -> (Vec<F>, Vec<F>) {
 64    (
 65        cs.witness_assignment.clone(),
 66        // skip the first element which is '1'
 67        cs.instance_assignment[1..].to_vec(),
 68    )
 69}
 70
 71#[cfg(test)]
 72pub mod tests {
 73    use super::*;
 74    use ark_ff::PrimeField;
 75    use ark_pallas::Fr;
 76    use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::fp::FpVar};
 77    use ark_relations::r1cs::{
 78        ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError,
 79    };
 80
 81    // TestCircuit implements the R1CS for: x^3 + x + 5 = y (example from article
 82    // https://www.vitalik.ca/general/2016/12/10/qap.html )
 83    #[derive(Clone, Copy, Debug)]
 84    pub struct TestCircuit<F: PrimeField> {
 85        pub x: F,
 86        pub y: F,
 87    }
 88    impl<F: PrimeField> ConstraintSynthesizer<F> for TestCircuit<F> {
 89        fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
 90            let x = FpVar::<F>::new_input(cs.clone(), || Ok(self.x))?;
 91            let y = FpVar::<F>::new_witness(cs.clone(), || Ok(self.y))?;
 92            let five = FpVar::<F>::new_constant(cs.clone(), F::from(5u32))?;
 93
 94            let comp_y = (&x * &x * &x) + &x + &five;
 95            comp_y.enforce_equal(&y)?;
 96            Ok(())
 97        }
 98    }
 99
100    #[test]
101    fn test_cs_to_matrices() {
102        let cs = ConstraintSystem::<Fr>::new_ref();
103
104        let x = Fr::from(5_u32);
105        let y = x * x * x + x + Fr::from(5_u32);
106
107        let test_circuit = TestCircuit::<Fr> { x, y };
108        test_circuit.generate_constraints(cs.clone()).unwrap();
109        cs.finalize();
110        assert!(cs.is_satisfied().unwrap());
111
112        let cs = cs.into_inner().unwrap();
113
114        // ensure that num_instance_variables is 2: 1 + 1 public input
115        assert_eq!(cs.num_instance_variables, 2);
116
117        let (r1cs, z) = extract_r1cs_and_z::<Fr>(&cs);
118        r1cs.check_relation(&z).unwrap();
119        // ensure that number of public inputs (l) is 1
120        assert_eq!(r1cs.l, 1);
121    }
122}