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 m = cs.to_matrices().unwrap();
12
13 let n_rows = cs.num_constraints;
14 let n_cols = cs.num_instance_variables + cs.num_witness_variables; // cs.num_instance_variables already counts the 1
15
16 let A = SparseMatrix::<F> {
17 n_rows,
18 n_cols,
19 coeffs: m.a,
20 };
21 let B = SparseMatrix::<F> {
22 n_rows,
23 n_cols,
24 coeffs: m.b,
25 };
26 let C = SparseMatrix::<F> {
27 n_rows,
28 n_cols,
29 coeffs: m.c,
30 };
31
32 // z = (1, x, w)
33 let z: Vec<F> = [
34 // 1 is already included in cs.instance_assignment
35 cs.instance_assignment.clone(),
36 cs.witness_assignment.clone(),
37 ]
38 .concat();
39
40 (
41 R1CS::<F> {
42 l: cs.num_instance_variables,
43 A,
44 B,
45 C,
46 },
47 z,
48 )
49}
50
51#[cfg(test)]
52pub mod tests {
53 use super::*;
54 use ark_ff::PrimeField;
55 use ark_pallas::Fr;
56 use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::fp::FpVar};
57 use ark_relations::r1cs::{
58 ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError,
59 };
60
61 // TestCircuit implements the R1CS for: x^3 + x + 5 = y (example from article
62 // https://www.vitalik.ca/general/2016/12/10/qap.html )
63 #[derive(Clone, Copy, Debug)]
64 pub struct TestCircuit<F: PrimeField> {
65 pub x: F,
66 pub y: F,
67 }
68 impl<F: PrimeField> ConstraintSynthesizer<F> for TestCircuit<F> {
69 fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
70 let x = FpVar::<F>::new_input(cs.clone(), || Ok(self.x))?;
71 let y = FpVar::<F>::new_witness(cs.clone(), || Ok(self.y))?;
72 let five = FpVar::<F>::new_constant(cs.clone(), F::from(5u32))?;
73
74 let comp_y = (&x * &x * &x) + &x + &five;
75 comp_y.enforce_equal(&y)?;
76 Ok(())
77 }
78 }
79
80 #[test]
81 fn test_cs_to_matrices() {
82 let cs = ConstraintSystem::<Fr>::new_ref();
83
84 let x = Fr::from(5_u32);
85 let y = x * x * x + x + Fr::from(5_u32);
86
87 let test_circuit = TestCircuit::<Fr> { x, y };
88 test_circuit.generate_constraints(cs.clone()).unwrap();
89 cs.finalize();
90 assert!(cs.is_satisfied().unwrap());
91
92 let cs = cs.into_inner().unwrap();
93
94 // ensure that num_instance_variables is 2: 1 + 1 public input
95 assert_eq!(cs.num_instance_variables, 2);
96
97 let (r1cs, z) = extract_r1cs_and_z::<Fr>(&cs);
98 r1cs.check_relation(&z).unwrap();
99 }
100}