From 3c91628ea5e4a473c614c9afa2d26624b180b259 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Tue, 3 Sep 2024 17:14:00 +0200 Subject: [PATCH] backup wip --- src/commitments_approach.rs | 0 src/cyclefold_circuit.rs | 22 +++++++ src/lib.rs | 109 +--------------------------------- src/sparse_approach.rs | 113 ++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 108 deletions(-) create mode 100644 src/commitments_approach.rs create mode 100644 src/cyclefold_circuit.rs create mode 100644 src/sparse_approach.rs diff --git a/src/commitments_approach.rs b/src/commitments_approach.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/cyclefold_circuit.rs b/src/cyclefold_circuit.rs new file mode 100644 index 0000000..650cf68 --- /dev/null +++ b/src/cyclefold_circuit.rs @@ -0,0 +1,22 @@ + + + fn init(pp: &Self::ProverParam, F: FC, z_0: Vec) -> Result { + // prepare the circuit to obtain its R1CS + let cs = ConstraintSystem::::new_ref(); + let cs2 = ConstraintSystem::::new_ref(); + + let augmented_F_circuit = + AugmentedFCircuit::::empty(&pp.poseidon_config, F); + let cf_circuit = CycleFoldCircuit::::empty(); + + augmented_F_circuit.generate_constraints(cs.clone())?; + cs.finalize(); + let cs = cs.into_inner().ok_or(Error::NoInnerConstraintSystem)?; + let r1cs = extract_r1cs::(&cs); + + cf_circuit.generate_constraints(cs2.clone())?; + cs2.finalize(); + let cs2 = cs2.into_inner().ok_or(Error::NoInnerConstraintSystem)?; + let cf_r1cs = extract_r1cs::(&cs2); + } + diff --git a/src/lib.rs b/src/lib.rs index e8ca5ca..2653e18 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,112 +2,5 @@ #![allow(unused_doc_comments)] #![allow(dead_code)] -use ark_ff::PrimeField; -use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; -use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::FieldVar, R1CSVar}; -use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; -use core::marker::PhantomData; -use std::ops::Mul; - +mod sparse_approach; mod utils; -use utils::*; - -/// - F stands for the field that we represent -/// - CF stands for the ConstraintField over which we do the operations - -/// Implements the A * z matrix-vector-product by fixing the combinations of 'z'. -fn handcrafted_A_by_z( - cs: ConstraintSystemRef, - z: Vec>, -) -> Result>, SynthesisError> { - let five = NonNativeFieldVar::::new_constant(cs.clone(), F::from(5u32))?; - // directly hand-craft the output vector containing the operations in-place: - Ok(vec![ - z[1].clone() + five.clone() * z[4].clone(), - z[1].clone() + z[3].clone(), - z[1].clone() + z[4].clone(), - five * z[0].clone() + z[4].clone() + z[5].clone(), - ] - .clone()) -} - -/// Implements the A * z matrix-vector-product by doing the sparse matrix by vector algorithm, and -/// assuming that the elements of the matrix A are constants of the system. -pub fn mat_vec_mul_sparse_gadget( - m: SparseMatrixVar, - v: Vec>, -) -> Vec> { - let mut res = vec![NonNativeFieldVar::::zero(); m.n_rows]; - for (row_i, row) in m.coeffs.iter().enumerate() { - for (value, col_i) in row.iter() { - if value.value().unwrap() == F::one() { - res[row_i] += v[*col_i].clone(); // when value==1, no need to multiply by it - continue; - } - res[row_i] += value.clone().mul(&v[*col_i].clone()); - } - } - res -} - -/// Circuit that takes as constants the sparse matrix A, and as inputs the vectors z and y. It -/// computes the matrix by vector product between A and z, and checks that is equal to y -/// (ie. y == A*z) -struct MatrixVectorCircuit { - _cf: PhantomData, - pub A: SparseMatrix, - pub z: Vec, - pub y: Vec, -} -impl ConstraintSynthesizer for MatrixVectorCircuit { - fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { - // set A as circuit constants - let A = SparseMatrixVar::::new_constant(cs.clone(), self.A)?; - // set z and y as witness (private inputs) - let z: Vec> = Vec::new_witness(cs.clone(), || Ok(self.z.clone()))?; - let y: Vec> = Vec::new_witness(cs.clone(), || Ok(self.y.clone()))?; - - /// The next two lines are the ones that can be swapped to see the number of constraints - /// taken by the two approaches: - let Az = mat_vec_mul_sparse_gadget(A, z); - // let Az = handcrafted_A_by_z(cs, z)?; - - Az.enforce_equal(&y)?; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use ark_pallas::{Fq, Fr}; - use ark_relations::r1cs::ConstraintSystem; - - #[test] - fn test_relaxed_r1cs_nonnative_matrix_vector_product() { - let A = to_F_matrix::(vec![ - vec![0, 1, 0, 0, 5, 0], - vec![0, 1, 0, 1, 0, 0], - vec![0, 1, 0, 0, 1, 0], - vec![5, 0, 0, 0, 1, 1], - ]); - let z = to_F_vec(vec![1, 123, 35, 53, 80, 30]); - let y = mat_vec_mul_sparse(&A, &z); // y = A*z - println!("Matrix of size {} x {}", A.n_rows, A.n_cols); - println!("Vector of size {}", z.len()); - - println!( - "Build the circuit that computes the matrix-vector-product over a non-native field" - ); - let cs = ConstraintSystem::::new_ref(); - let circuit = MatrixVectorCircuit:: { - _cf: PhantomData, - A, - z, - y, - }; - circuit.generate_constraints(cs.clone()).unwrap(); - println!("Number of constraints: {}", cs.num_constraints()); - assert!(cs.is_satisfied().unwrap()); - } -} diff --git a/src/sparse_approach.rs b/src/sparse_approach.rs new file mode 100644 index 0000000..1a41611 --- /dev/null +++ b/src/sparse_approach.rs @@ -0,0 +1,113 @@ +/// Isolated test which gets the number of constraints for two 'naive' approaches for the +/// matrix-vector-product: +/// - handcrafted_A_by_z method +/// - mat_vec_mul_sparse_gadget +/// +use ark_ff::PrimeField; +use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; +use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::FieldVar, R1CSVar}; +use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; +use core::marker::PhantomData; +use std::ops::Mul; + +use crate::utils::*; + +/// - F stands for the field that we represent +/// - CF stands for the ConstraintField over which we do the operations + +/// Implements the A * z matrix-vector-product by fixing the combinations of 'z'. +fn handcrafted_A_by_z( + cs: ConstraintSystemRef, + z: Vec>, +) -> Result>, SynthesisError> { + let five = NonNativeFieldVar::::new_constant(cs.clone(), F::from(5u32))?; + // directly hand-craft the output vector containing the operations in-place: + Ok(vec![ + z[1].clone() + five.clone() * z[4].clone(), + z[1].clone() + z[3].clone(), + z[1].clone() + z[4].clone(), + five * z[0].clone() + z[4].clone() + z[5].clone(), + ] + .clone()) +} + +/// Implements the A * z matrix-vector-product by doing the sparse matrix by vector algorithm, and +/// assuming that the elements of the matrix A are constants of the system. +pub fn mat_vec_mul_sparse_gadget( + m: SparseMatrixVar, + v: Vec>, +) -> Vec> { + let mut res = vec![NonNativeFieldVar::::zero(); m.n_rows]; + for (row_i, row) in m.coeffs.iter().enumerate() { + for (value, col_i) in row.iter() { + if value.value().unwrap() == F::one() { + res[row_i] += v[*col_i].clone(); // when value==1, no need to multiply by it + continue; + } + res[row_i] += value.clone().mul(&v[*col_i].clone()); + } + } + res +} + +/// Circuit that takes as constants the sparse matrix A, and as inputs the vectors z and y. It +/// computes the matrix by vector product between A and z, and checks that is equal to y +/// (ie. y == A*z) +struct MatrixVectorCircuit { + _cf: PhantomData, + pub A: SparseMatrix, + pub z: Vec, + pub y: Vec, +} +impl ConstraintSynthesizer for MatrixVectorCircuit { + fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { + // set A as circuit constants + let A = SparseMatrixVar::::new_constant(cs.clone(), self.A)?; + // set z and y as witness (private inputs) + let z: Vec> = Vec::new_witness(cs.clone(), || Ok(self.z.clone()))?; + let y: Vec> = Vec::new_witness(cs.clone(), || Ok(self.y.clone()))?; + + /// The next two lines are the ones that can be swapped to see the number of constraints + /// taken by the two approaches: + let Az = mat_vec_mul_sparse_gadget(A, z); + // let Az = handcrafted_A_by_z(cs, z)?; + + Az.enforce_equal(&y)?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ark_pallas::{Fq, Fr}; + use ark_relations::r1cs::ConstraintSystem; + + #[test] + fn test_relaxed_r1cs_nonnative_matrix_vector_product() { + let A = to_F_matrix::(vec![ + vec![0, 1, 0, 0, 5, 0], + vec![0, 1, 0, 1, 0, 0], + vec![0, 1, 0, 0, 1, 0], + vec![5, 0, 0, 0, 1, 1], + ]); + let z = to_F_vec(vec![1, 123, 35, 53, 80, 30]); + let y = mat_vec_mul_sparse(&A, &z); // y = A*z + println!("Matrix of size {} x {}", A.n_rows, A.n_cols); + println!("Vector of size {}", z.len()); + + println!( + "Build the circuit that computes the matrix-vector-product over a non-native field" + ); + let cs = ConstraintSystem::::new_ref(); + let circuit = MatrixVectorCircuit:: { + _cf: PhantomData, + A, + z, + y, + }; + circuit.generate_constraints(cs.clone()).unwrap(); + println!("Number of constraints: {}", cs.num_constraints()); + assert!(cs.is_satisfied().unwrap()); + } +}