diff --git a/src/hypernova/ccs.rs b/src/hypernova/ccs.rs new file mode 100644 index 0000000..30dc1fd --- /dev/null +++ b/src/hypernova/ccs.rs @@ -0,0 +1,69 @@ +use ark_ff::fields::PrimeField; + +use crate::nifs::R1CS; +use crate::utils::{hadamard_product, matrix_vector_product, vec_add, vector_elem_product}; + +pub struct CCS { + m: usize, + n: usize, + t: usize, + q: usize, + d: usize, + S: Vec>, + c: Vec, + M: Vec>>, +} + +impl R1CS { + pub fn to_ccs(self) -> CCS { + CCS:: { + m: self.A.len(), + n: self.A[0].len(), + t: 3, + q: 2, + d: 2, + S: vec![vec![0, 1], vec![2]], + c: vec![F::one(), F::one().neg()], + M: vec![self.A, self.B, self.C], + } + } +} + +impl CCS { + pub fn check_relation(self, z: Vec) -> bool { + let mut r: Vec = vec![F::zero(); self.m]; + for i in 0..self.q { + let mut hadamard_output = vec![F::one(); self.m]; + for j in self.S[i].clone() { + hadamard_output = + hadamard_product(hadamard_output, matrix_vector_product(&self.M[j], &z)); + } + r = vec_add(&r, &vector_elem_product(&hadamard_output, &self.c[i])); + } + + let zero: Vec = vec![F::zero(); self.m]; + + r == zero + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::transcript::poseidon_test_config; + use ark_mnt4_298::{Fr, G1Projective}; + use ark_std::One; + use ark_std::UniformRand; + + use crate::nifs::gen_test_values; + + #[test] + fn test_r1cs_to_ccs() { + let (r1cs, ws, _) = gen_test_values(2); + let w: Vec = ws[0].clone(); + + let ccs = r1cs.to_ccs(); + + assert!(ccs.check_relation(w)); + } +} diff --git a/src/hypernova/mod.rs b/src/hypernova/mod.rs new file mode 100644 index 0000000..ce82ffd --- /dev/null +++ b/src/hypernova/mod.rs @@ -0,0 +1 @@ +pub mod ccs; diff --git a/src/lib.rs b/src/lib.rs index c91499a..0342e9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,3 +12,6 @@ mod pedersen; mod sumcheck; mod transcript; mod utils; + +// hypernova related: +mod hypernova;