Skip to content

Commit

Permalink
WIP: Use Spartan polynomial.rs, not virtual_poly
Browse files Browse the repository at this point in the history
Tests currently failing due to different order of evaluations inside the MLE. E.g:

```
[src/ccs/util/virtual_poly.rs:576] eq_x_r_old.Z.clone() = [
    0x34a2da9a5f67ca3e8955b20a35d0bb5e33f182e4821c672b7b60bee92cc210ae,
    0x1a4de95e591506758747746c9f5a8b82926547116f590b455add73e40043959d,
    0x1baaba6f39ed721fed5d82f989195a505a3990fa4657c770b059eb68e1efcb3d,
    0x156481980d95bd2c0205568fa1bb5ecf23fcd707db5c17d991f5b80bf10a8e7b,
]
[src/ccs/util/virtual_poly.rs:577] eq_x_r_new.Z.clone() = [
    0x34a2da9a5f67ca3e8955b20a35d0bb5e33f182e4821c672b7b60bee92cc210ae,
    0x1baaba6f39ed721fed5d82f989195a505a3990fa4657c770b059eb68e1efcb3d,
    0x1a4de95e591506758747746c9f5a8b82926547116f590b455add73e40043959d,
    0x156481980d95bd2c0205568fa1bb5ecf23fcd707db5c17d991f5b80bf10a8e7b,
]
```

Existing test failing: `cargo test test_compute_g`

Minimal reproducible test for ordering: `cargo test test_eq_x_r_equality`
  • Loading branch information
oskarth committed Jul 22, 2023
1 parent 58d0873 commit 567aa34
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 6 deletions.
8 changes: 6 additions & 2 deletions src/ccs/cccs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,12 @@ impl<G: Group> CCCSShape<G> {
beta: &[G::Scalar],
) -> Result<VirtualPolynomial<G::Scalar>, NovaError> {
let q = self.compute_q(z)?;
q.build_f_hat(beta)
let qfhat_old = q.build_f_hat_old(beta);
let qfhat_new = q.build_f_hat(beta);
dbg!(qfhat_old.clone());
dbg!(qfhat_new.clone());

qfhat_new
}

/// Perform the check of the CCCS instance described at section 4.1
Expand All @@ -115,7 +120,6 @@ impl<G: Group> CCCSShape<G> {

// check CCCS relation
let z: Vec<G::Scalar> = [vec![G::Scalar::ONE], x.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).unwrap();
for x in BooleanHypercube::new(self.ccs.s) {
Expand Down
7 changes: 6 additions & 1 deletion src/ccs/multifolding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl<G: Group> Multifolding<G> {
#[cfg(test)]
mod tests {
use super::*;
use crate::ccs::{test, util::virtual_poly::build_eq_x_r};
use crate::ccs::test;
use pasta_curves::{Ep, Fq};
use rand_core::OsRng;
// NIMFS: Non Interactive Multifolding Scheme
Expand Down Expand Up @@ -252,6 +252,11 @@ mod tests {

// evaluating g(x) over the boolean hypercube should give the same result as evaluating the
// sum of gamma^j * v_j over j \in [t]

// XXX: This fails, order of evaluations different for these two
dbg!(g_on_bhc);
dbg!(sum_v_j_gamma);

assert_eq!(g_on_bhc, sum_v_j_gamma);
}

Expand Down
95 changes: 92 additions & 3 deletions src/ccs/util/virtual_poly.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::hypercube::BooleanHypercube;
use crate::spartan::math::Math;
use crate::spartan::polynomial::MultilinearPolynomial;
use crate::spartan::polynomial::{EqPolynomial, MultilinearPolynomial};
use crate::{
constants::{BN_LIMB_WIDTH, BN_N_LIMBS, NUM_FE_FOR_RO, NUM_HASH_BITS},
errors::NovaError,
Expand Down Expand Up @@ -293,6 +293,19 @@ impl<F: PrimeField> VirtualPolynomial<F> {
Ok(poly)
}

// XXX: Remove me, temp for debugging
pub fn build_f_hat_old(&self, r: &[F]) -> Result<Self, NovaError> {
if self.aux_info.num_variables != r.len() {
return Err(NovaError::VpArith);
}

let eq_x_r_old = build_eq_x_r(r)?;
let mut res = self.clone();
res.mul_by_mle(eq_x_r_old, F::ONE)?;

Ok(res)
}

// Input poly f(x) and a random vector r, output
// \hat f(x) = \sum_{x_i \in eval_x} f(x_i) eq(x, r)
// where
Expand All @@ -304,9 +317,27 @@ impl<F: PrimeField> VirtualPolynomial<F> {
return Err(NovaError::VpArith);
}

let eq_x_r = build_eq_x_r(r)?;
// FIXME: eq_x_r_old and eq_x_r_new produce the same evals but in a different order
// Initial hypothesis that this was due to Gray coding or "inverted binary" (endianness) seems incorrect
//
// Here's the ordering for 2^3 entries:
// eq_x_r_old Z: [A, B, C, D, E, F, G, H]
// eq_x_r_new Z: [A, E, C, G, B, F, D, H]

// Old version of eq_x_r using `virtual_poly.rs`
let eq_x_r_old = build_eq_x_r(r)?;

// New version of eq_x_r using `polynomial.rs`
let eq_polynomial = EqPolynomial::new(r.to_vec());
let evaluations = eq_polynomial.evals();
let multilinear_poly = MultilinearPolynomial::new(evaluations);
let eq_x_r_new = Arc::new(multilinear_poly);

dbg!(eq_x_r_old.Z.clone());
dbg!(eq_x_r_new.Z.clone());

let mut res = self.clone();
res.mul_by_mle(eq_x_r, F::ONE)?;
res.mul_by_mle(eq_x_r_new, F::ONE)?;

Ok(res)
}
Expand Down Expand Up @@ -496,3 +527,61 @@ mod test {
Arc::new(mle)
}
}

#[cfg(test)]
mod tests {
use super::*;
use pasta_curves::Fq;
use rand_core::OsRng;

#[test]
fn test_build_f_hat() {
let mut rng = OsRng;
let num_vars = 3; // You can change this value according to your requirement

// Create a VirtualPolynomial
let poly = VirtualPolynomial::<Fq>::new(num_vars);
let r: Vec<Fq> = (0..num_vars).map(|_| Fq::random(&mut rng)).collect();

// Test with correct input length
let result = poly.build_f_hat(&r);
assert!(result.is_ok(), "Failed with correct input length");

// Test with incorrect input length
let bad_r: Vec<Fq> = (0..num_vars + 1).map(|_| Fq::random(&mut rng)).collect();
let result = poly.build_f_hat(&bad_r);
assert!(
matches!(result, Err(NovaError::VpArith)),
"Did not fail with incorrect input length"
);
}

#[test]
fn test_eq_x_r_equality() {
let mut rng = OsRng;

for num_vars in 1..=3 {
// Generate random inputs
let r: Vec<Fq> = (0..num_vars).map(|_| Fq::random(&mut rng)).collect();

// Old version of eq_x_r using `virtual_poly.rs`
let eq_x_r_old = build_eq_x_r(&r).unwrap().clone();

// New version of eq_x_r using `polynomial.rs`
let eq_polynomial = EqPolynomial::new(r.to_vec());
let evaluations = eq_polynomial.evals();
let multilinear_poly = MultilinearPolynomial::new(evaluations);
let eq_x_r_new = Arc::new(multilinear_poly);

dbg!(eq_x_r_old.Z.clone());
dbg!(eq_x_r_new.Z.clone());

// Check equality of the results
assert_eq!(
eq_x_r_old.Z, eq_x_r_new.Z,
"eq_x_r_old.Z and eq_x_r.Z outputs are not equal for num_vars = {}",
num_vars
);
}
}
}
3 changes: 3 additions & 0 deletions src/spartan/polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,13 @@ impl<Scalar: PrimeField> EqPolynomial<Scalar> {

size *= 2;
}

evals
}
}

// TODO Update these docs too

/// A multilinear extension of a polynomial $Z(\cdot)$, denote it as $\tilde{Z}(x_1, ..., x_m)$
/// where the degree of each variable is at most one.
///
Expand Down

0 comments on commit 567aa34

Please sign in to comment.