use ark_crypto_primitives::sponge::{poseidon::PoseidonConfig, Absorb}; use ark_ec::{CurveGroup, Group}; use ark_ff::fields::PrimeField; use ark_poly::{ evaluations::multivariate::multilinear::{MultilinearExtension, SparseMultilinearExtension}, multivariate::{SparsePolynomial, SparseTerm, Term}, univariate::DensePolynomial, DenseMVPolynomial, DenseUVPolynomial, Polynomial, }; use ark_std::log2; use std::marker::PhantomData; use crate::hypernova::ccs::CCS; use crate::hypernova::sumcheck::{Point, SumCheck}; use crate::pedersen::Commitment; use crate::transcript::Transcript; use ark_std::{One, Zero}; // Committed CCS instance pub struct CCCS { C: Commitment, x: Vec, } // Linearized Committed CCS instance pub struct LCCCS { C: Commitment, u: C::ScalarField, x: Vec, r: Vec, v: Vec, } // NIMFS: Non Interactive Multifolding Scheme pub struct NIMFS { _c: PhantomData, } impl NIMFS where ::ScalarField: Absorb, ::BaseField: Absorb, { // proof method folds and returns the proof of the multifolding pub fn proof( tr: &mut Transcript, poseidon_config: &PoseidonConfig, ccs: CCS, lcccs: LCCCS, cccs: CCCS, z1: Vec, z2: Vec, ) -> LCCCS { let s = log2(ccs.m) as usize; // s let s_ = log2(ccs.n) as usize; // s' let gamma = tr.get_challenge(); let beta = tr.get_challenge_vec(s); // get MLE of M_i let mut MLEs: Vec> = Vec::new(); let n_vars = (s + s_) as usize; for i in 0..ccs.M.len() { let M_i_MLE = matrix_to_mle(n_vars, ccs.m, ccs.n, &ccs.M[i]); MLEs.push(M_i_MLE); } // get MLE of z1 & z2 let z1_MLE = vector_to_mle(s_, ccs.n, z1); let z2_MLE = vector_to_mle(s_, ccs.n, z2); // compute Lj = eq(r_x,x) * \sum Mj * z1 let mut Lj_evals: Vec<(usize, C::ScalarField)> = Vec::new(); for i in 0..s_ {} // compute Q = eq(beta, x) * ( \sum c_i * \prod( \sum Mj * z1 ) ) // compute g // let g: SparsePolynomial; // let proof = SC::::prove(&poseidon_config, g); // fold C, u, x, v, w unimplemented!(); } } fn matrix_to_mle( n_vars: usize, // log2(m) + log2(n) m: usize, n: usize, M: &Vec>, ) -> SparseMultilinearExtension { let mut M_evals: Vec<(usize, F)> = Vec::new(); for i in 0..m { for j in 0..n { if !M[i][j].is_zero() { M_evals.push((i * n + j, M[i][j])); } } } SparseMultilinearExtension::::from_evaluations(n_vars, M_evals.iter()) } fn vector_to_mle(s: usize, n: usize, z: Vec) -> SparseMultilinearExtension { let mut z_evals: Vec<(usize, F)> = Vec::new(); for i in 0..n { if !z[i].is_zero() { z_evals.push((i, z[i])); } } SparseMultilinearExtension::::from_evaluations(s, z_evals.iter()) } type SC = SumCheck< C::ScalarField, C, DensePolynomial, SparsePolynomial, >; #[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; type P = Point; #[test] fn test_cccs_mles() { let (r1cs, ws, _) = gen_test_values(2); let z1: Vec = ws[0].clone(); println!("z1 {:?}", z1); let ccs = r1cs.to_ccs(); let s = log2(ccs.m) as usize; // s let s_ = log2(ccs.n) as usize; // s' let pow_s_ = (2 as usize).pow(s_ as u32); let mut M_MLEs: Vec> = Vec::new(); let n_vars = (s + s_) as usize; for i in 0..ccs.M.len() { let M_i_MLE = matrix_to_mle(n_vars, ccs.m, ccs.n, &ccs.M[i]); println!("i:{}, M_i_mle: {:?}", i, M_i_MLE); M_MLEs.push(M_i_MLE); } let z1_MLE = vector_to_mle(s_, ccs.n, z1); println!("z1_MLE: {:?}", z1_MLE); let beta = Point::::point_normal(s, 2); // imagine that this comes from random println!("beta: {:?}", beta); // check Committed CCS relation let mut r: Fr = Fr::zero(); for i in 0..ccs.q { let mut prod_res = Fr::one(); // for j in 0..ccs.S.len() { for j in ccs.S[i].clone() { let mut Mj_z_eval = Fr::zero(); // for k in 0..s_ { // over the boolean hypercube un s' vars, but only the combinations that lead to // some non-zero z() for k in 0..ccs.n { // over the whole boolean hypercube on s' vars // for k in 0..pow_s_ { let point_in_s_ = Point::::point_normal(s_, k); // println!("point_in_s {:?}", point_in_s_); let z_eval = z1_MLE.evaluate(&point_in_s_).unwrap(); // println!(" ===================================z_eval {:?}", z_eval); // let point_in_s_plus_s_ = Point::::point_complete(beta.clone(), s + s_, k); let mut point_in_s_plus_s_ = Point::::point_normal(s_, i); point_in_s_plus_s_.append(&mut beta.clone()); // println!("point_in_s_plus_s_ {:?}", point_in_s_plus_s_); // println!("j: {}, Mj {:?}", j, M_MLEs[j]); let Mj_eval = M_MLEs[j].evaluate(&point_in_s_plus_s_).unwrap(); if Mj_eval * z_eval != Fr::zero() { println!(" j: {}, Mj_eval {:?}", j, Mj_eval); println!(" z_eval {:?}", z_eval); println!(" =(Mj*z)_eval {:?}", Mj_eval * z_eval); } Mj_z_eval += Mj_eval * z_eval; } println!("j: {}, {:?}\n", j, Mj_z_eval); prod_res += Mj_z_eval; } println!("i:{}, c: {:?}, {:?}\n", i, ccs.c[i], prod_res); r += ccs.c[i] * prod_res; } println!("r {:?}", r); assert!(r.is_zero()); } }