Skip to content

Commit

Permalink
HyperNova: move CCS struct outside of LCCCS & CCCS
Browse files Browse the repository at this point in the history
HyperNova nimfs: move CCS structure outside of LCCCS & CCCS, to avoid
carrying around the whole CCS and duplicating data when is not needed.
  • Loading branch information
arnaucube committed Aug 29, 2023
1 parent 6ef9adc commit 5fd57e2
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 106 deletions.
51 changes: 20 additions & 31 deletions src/folding/hypernova/cccs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ pub struct Witness<F: PrimeField> {
/// Committed CCS instance
#[derive(Debug, Clone)]
pub struct CCCS<C: CurveGroup> {
// Underlying CCS structure
pub ccs: CCS<C>,

// Commitment to witness
pub C: C,
// Public input/output
Expand All @@ -49,29 +46,26 @@ impl<C: CurveGroup> CCS<C> {

(
CCCS::<C> {
ccs: self.clone(),
C,
x: z[1..(1 + self.l)].to_vec(),
},
Witness::<C::ScalarField> { w, r_w },
)
}
}

impl<C: CurveGroup> CCCS<C> {
/// Computes q(x) = \sum^q c_i * \prod_{j \in S_i} ( \sum_{y \in {0,1}^s'} M_j(x, y) * z(y) )
/// polynomial over x
pub fn compute_q(&self, z: &Vec<C::ScalarField>) -> VirtualPolynomial<C::ScalarField> {
let z_mle = vec_to_mle(self.ccs.s_prime, z);
let mut q = VirtualPolynomial::<C::ScalarField>::new(self.ccs.s);
let z_mle = vec_to_mle(self.s_prime, z);
let mut q = VirtualPolynomial::<C::ScalarField>::new(self.s);

for i in 0..self.ccs.q {
for i in 0..self.q {
let mut prod: VirtualPolynomial<C::ScalarField> =
VirtualPolynomial::<C::ScalarField>::new(self.ccs.s);
for j in self.ccs.S[i].clone() {
let M_j = matrix_to_mle(self.ccs.M[j].clone());
VirtualPolynomial::<C::ScalarField>::new(self.s);
for j in self.S[i].clone() {
let M_j = matrix_to_mle(self.M[j].clone());

let sum_Mz = compute_sum_Mz(M_j, &z_mle, self.ccs.s_prime);
let sum_Mz = compute_sum_Mz(M_j, &z_mle, self.s_prime);

// Fold this sum into the running product
if prod.products.is_empty() {
Expand All @@ -86,7 +80,7 @@ impl<C: CurveGroup> CCCS<C> {
}
}
// Multiply by the product by the coefficient c_i
prod.scalar_mul(&self.ccs.c[i]);
prod.scalar_mul(&self.c[i]);
// Add it to the running sum
q = q.add(&prod);
}
Expand All @@ -104,11 +98,14 @@ impl<C: CurveGroup> CCCS<C> {
let q = self.compute_q(z);
q.build_f_hat(beta).unwrap()
}
}

impl<C: CurveGroup> CCCS<C> {
/// Perform the check of the CCCS instance described at section 4.1
pub fn check_relation(
&self,
pedersen_params: &PedersenParams<C>,
ccs: &CCS<C>,
w: &Witness<C::ScalarField>,
) -> Result<(), Error> {
// check that C is the commitment of w. Notice that this is not verifying a Pedersen
Expand All @@ -120,8 +117,8 @@ impl<C: CurveGroup> CCCS<C> {
[vec![C::ScalarField::one()], self.x.clone(), w.w.to_vec()].concat();

// A CCCS relation is satisfied if the q(x) multivariate polynomial evaluates to zero in the hypercube
let q_x = self.compute_q(&z);
for x in BooleanHypercube::new(self.ccs.s) {
let q_x = ccs.compute_q(&z);
for x in BooleanHypercube::new(ccs.s) {
if !q_x.evaluate(&x).unwrap().is_zero() {
return Err(Error::NotSatisfied);
}
Expand Down Expand Up @@ -149,9 +146,7 @@ pub mod test {
let ccs = get_test_ccs::<G1Projective>();
let z = get_test_z(3);

let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, ccs.n - ccs.l - 1);
let (cccs, _) = ccs.to_cccs(&mut rng, &pedersen_params, &z);
let q = cccs.compute_q(&z);
let q = ccs.compute_q(&z);

// Evaluate inside the hypercube
for x in BooleanHypercube::new(ccs.s) {
Expand All @@ -168,17 +163,14 @@ pub mod test {
fn test_compute_Q() {
let mut rng = test_rng();

let ccs = get_test_ccs();
let ccs: CCS<G1Projective> = get_test_ccs();
let z = get_test_z(3);
ccs.check_relation(&z).unwrap();

let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, ccs.n - ccs.l - 1);
let (cccs, _) = ccs.to_cccs(&mut rng, &pedersen_params, &z);

let beta: Vec<Fr> = (0..ccs.s).map(|_| Fr::rand(&mut rng)).collect();

// Compute Q(x) = eq(beta, x) * q(x).
let Q = cccs.compute_Q(&z, &beta);
let Q = ccs.compute_Q(&z, &beta);

// Let's consider the multilinear polynomial G(x) = \sum_{y \in {0, 1}^s} eq(x, y) q(y)
// which interpolates the multivariate polynomial q(x) inside the hypercube.
Expand All @@ -205,18 +197,15 @@ pub mod test {
fn test_Q_against_q() {
let mut rng = test_rng();

let ccs = get_test_ccs();
let ccs: CCS<G1Projective> = get_test_ccs();
let z = get_test_z(3);
ccs.check_relation(&z).unwrap();

let pedersen_params = Pedersen::<G1Projective>::new_params(&mut rng, ccs.n - ccs.l - 1);
let (cccs, _) = ccs.to_cccs(&mut rng, &pedersen_params, &z);

// Now test that if we create Q(x) with eq(d,y) where d is inside the hypercube, \sum Q(x) should be G(d) which
// should be equal to q(d), since G(x) interpolates q(x) inside the hypercube
let q = cccs.compute_q(&z);
let q = ccs.compute_q(&z);
for d in BooleanHypercube::new(ccs.s) {
let Q_at_d = cccs.compute_Q(&z, &d);
let Q_at_d = ccs.compute_Q(&z, &d);

// Get G(d) by summing over Q_d(x) over the hypercube
let G_at_d = BooleanHypercube::new(ccs.s)
Expand All @@ -227,7 +216,7 @@ pub mod test {

// Now test that they should disagree outside of the hypercube
let r: Vec<Fr> = (0..ccs.s).map(|_| Fr::rand(&mut rng)).collect();
let Q_at_r = cccs.compute_Q(&z, &r);
let Q_at_r = ccs.compute_Q(&z, &r);

// Get G(d) by summing over Q_d(x) over the hypercube
let G_at_r = BooleanHypercube::new(ccs.s)
Expand Down
25 changes: 13 additions & 12 deletions src/folding/hypernova/lcccs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ use crate::utils::virtual_polynomial::VirtualPolynomial;
/// Linearized Committed CCS instance
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct LCCCS<C: CurveGroup> {
// Underlying CCS structure
pub ccs: CCS<C>, // TODO maybe move CCS structure outside of LCCCS

// Commitment to witness
pub C: C,
// Relaxation factor of z for folded LCCCS
Expand Down Expand Up @@ -54,7 +51,6 @@ impl<C: CurveGroup> CCS<C> {

(
LCCCS::<C> {
ccs: self.clone(),
C,
u: C::ScalarField::one(),
x: z[1..(1 + self.l)].to_vec(),
Expand All @@ -68,15 +64,19 @@ impl<C: CurveGroup> CCS<C> {

impl<C: CurveGroup> LCCCS<C> {
/// Compute all L_j(x) polynomials
pub fn compute_Ls(&self, z: &Vec<C::ScalarField>) -> Vec<VirtualPolynomial<C::ScalarField>> {
let z_mle = vec_to_mle(self.ccs.s_prime, z);
pub fn compute_Ls(
&self,
ccs: &CCS<C>,
z: &Vec<C::ScalarField>,
) -> Vec<VirtualPolynomial<C::ScalarField>> {
let z_mle = vec_to_mle(ccs.s_prime, z);
// Convert all matrices to MLE
let M_x_y_mle: Vec<DenseMultilinearExtension<C::ScalarField>> =
self.ccs.M.clone().into_iter().map(matrix_to_mle).collect();
ccs.M.clone().into_iter().map(matrix_to_mle).collect();

let mut vec_L_j_x = Vec::with_capacity(self.ccs.t);
let mut vec_L_j_x = Vec::with_capacity(ccs.t);
for M_j in M_x_y_mle {
let sum_Mz = compute_sum_Mz(M_j, &z_mle, self.ccs.s_prime);
let sum_Mz = compute_sum_Mz(M_j, &z_mle, ccs.s_prime);
let sum_Mz_virtual =
VirtualPolynomial::new_from_mle(&Arc::new(sum_Mz.clone()), C::ScalarField::one());
let L_j_x = sum_Mz_virtual.build_f_hat(&self.r_x).unwrap();
Expand All @@ -90,6 +90,7 @@ impl<C: CurveGroup> LCCCS<C> {
pub fn check_relation(
&self,
pedersen_params: &PedersenParams<C>,
ccs: &CCS<C>,
w: &Witness<C::ScalarField>,
) -> Result<(), Error> {
// check that C is the commitment of w. Notice that this is not verifying a Pedersen
Expand All @@ -98,7 +99,7 @@ impl<C: CurveGroup> LCCCS<C> {

// check CCS relation
let z: Vec<C::ScalarField> = [vec![self.u], self.x.clone(), w.w.to_vec()].concat();
let computed_v = compute_all_sum_Mz_evals(&self.ccs.M, &z, &self.r_x, self.ccs.s_prime);
let computed_v = compute_all_sum_Mz_evals(&ccs.M, &z, &self.r_x, ccs.s_prime);
assert_eq!(computed_v, self.v);
Ok(())
}
Expand Down Expand Up @@ -129,7 +130,7 @@ pub mod test {
// with our test vector comming from R1CS, v should have length 3
assert_eq!(lcccs.v.len(), 3);

let vec_L_j_x = lcccs.compute_Ls(&z);
let vec_L_j_x = lcccs.compute_Ls(&ccs, &z);
assert_eq!(vec_L_j_x.len(), lcccs.v.len());

for (v_i, L_j_x) in lcccs.v.into_iter().zip(vec_L_j_x) {
Expand Down Expand Up @@ -161,7 +162,7 @@ pub mod test {
assert_eq!(lcccs.v.len(), 3);

// Bad compute L_j(x) with the bad z
let vec_L_j_x = lcccs.compute_Ls(&bad_z);
let vec_L_j_x = lcccs.compute_Ls(&ccs, &bad_z);
assert_eq!(vec_L_j_x.len(), lcccs.v.len());

// Make sure that the LCCCS is not satisfied given these L_j(x)
Expand Down
Loading

0 comments on commit 5fd57e2

Please sign in to comment.