Skip to content

Commit

Permalink
feat: add function converting evaluations to coefficients (#125)
Browse files Browse the repository at this point in the history
# Rationale for this change

In order for the sumcheck verifier to be able to be verify proofs more
efficiently (and for the sake of the solidity port, with less code), the
proof should consist of polynomial coefficients rather than evaluations.
This PR adds the code to make the conversion. A later PR will do the
switch.

# What changes are included in this PR?

* A `interpolate_evaluations_to_reverse_coefficients` method is added.
* Tests for this method are added.

# Are these changes tested?

Yes
  • Loading branch information
JayWhite2357 authored Sep 4, 2024
1 parent b9ef335 commit d4d239c
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 6 deletions.
51 changes: 49 additions & 2 deletions crates/proof-of-sql/src/base/polynomial/interpolate.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use core::cmp::PartialEq;
/**
* Adapted from arkworks
*
* See third_party/license/arkworks.LICENSE
*/
use core::ops::{AddAssign, Mul, MulAssign, SubAssign};
use core::ops::{Add, AddAssign, Mul, MulAssign, SubAssign};
use core::{cmp::PartialEq, iter::Product};
use num_traits::{Inv, One, Zero};

/// Interpolate a uni-variate degree-`polynomial.len()-1` polynomial and evaluate this
Expand Down Expand Up @@ -67,3 +67,50 @@ where
}
sum * product
}

/// Let d be the evals.len() - 1 and let f be the polynomial such that f(i) = evals[i].
/// The output of this function is the vector of coefficients of f, leading coefficient first.
/// That is, `f(x) = evals[j]*x^(d-j)``.
#[allow(dead_code)]
pub fn interpolate_evaluations_to_reverse_coefficients<S>(evals: &[S]) -> Vec<S>
where
S: Zero
+ Copy
+ From<i32>
+ Mul<Output = S>
+ Add<Output = S>
+ Inv<Output = Option<S>>
+ Product,
{
let n = evals.len().max(1) - 1;
evals
.iter()
.enumerate()
.map(|(idx, &eval_i)| {
let i = idx as i32;
let mut scaled_lagrange_basis = vec![S::zero(); n + 1];
// First compute the constant factor of this lagrange basis polynomial:
scaled_lagrange_basis[0] = (i - n as i32..0)
.chain(1..=i)
.map(S::from)
.product::<S>()
.inv()
.unwrap()
* eval_i;
// Then multiply by the appropriate linear terms:
// for j in 0..=n if j != i {
for neg_j in (-(n as i32)..-i).chain(1 - i..=0).map(S::from) {
for k in (0..n).rev() {
scaled_lagrange_basis[k + 1] =
scaled_lagrange_basis[k + 1] + neg_j * scaled_lagrange_basis[k];
}
}
scaled_lagrange_basis
})
// Finally, sum up all the resulting polynomials
.reduce(|mut acc, b| {
acc.iter_mut().zip(b).for_each(|(a, b)| *a = *a + b);
acc
})
.unwrap_or(vec![])
}
73 changes: 70 additions & 3 deletions crates/proof-of-sql/src/base/polynomial/interpolate_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
*
* See third_party/license/arkworks.LICENSE
*/
use crate::base::polynomial::interpolate::*;
use crate::base::scalar::Curve25519Scalar;
use super::interpolate::*;
use crate::base::scalar::{Curve25519Scalar, Curve25519Scalar as S};
use ark_std::UniformRand;
use num_traits::Zero;
use num_traits::{Inv, Zero};

#[test]
fn test_interpolate_uni_poly_for_random_polynomials() {
Expand Down Expand Up @@ -93,3 +93,70 @@ fn interpolate_uni_poly_gives_correct_value_for_known_evaluation() {
);
}
}

#[test]
fn we_can_interpolate_evaluations_to_reverse_coefficients_with_empty_input() {
assert_eq!(
interpolate_evaluations_to_reverse_coefficients(&[] as &[S]),
vec![]
);
}

#[test]
fn we_can_interpolate_evaluations_to_reverse_coefficients_with_degree_0() {
assert_eq!(
interpolate_evaluations_to_reverse_coefficients(&[S::from(2)]),
vec![S::from(2)]
);
}

#[test]
fn we_can_interpolate_evaluations_to_reverse_coefficients_with_degree_1() {
assert_eq!(
interpolate_evaluations_to_reverse_coefficients(&[S::from(2), S::from(3)]),
vec![S::from(1), S::from(2)]
);
}

#[test]
fn we_can_interpolate_evaluations_to_reverse_coefficients_with_degree_2() {
assert_eq!(
interpolate_evaluations_to_reverse_coefficients(&[S::from(2), S::from(3), S::from(5)]),
vec![
S::from(1) * S::from(2).inv().unwrap(),
S::from(1) * S::from(2).inv().unwrap(),
S::from(2)
]
);
}

#[test]
fn we_can_interpolate_evaluations_to_reverse_coefficients_with_degree_3() {
assert_eq!(
interpolate_evaluations_to_reverse_coefficients(&[
S::from(2),
S::from(3),
S::from(5),
S::from(7)
]),
vec![
S::from(-1) * S::from(6).inv().unwrap(),
S::from(1),
S::from(1) * S::from(6).inv().unwrap(),
S::from(2)
]
);
}

#[test]
fn we_can_interpolate_evaluations_to_reverse_coefficients_with_degree_3_degenerate_evals() {
assert_eq!(
interpolate_evaluations_to_reverse_coefficients(&[
S::from(1),
S::from(3),
S::from(5),
S::from(7)
]),
vec![S::from(0), S::from(0), S::from(2), S::from(1)]
);
}
3 changes: 2 additions & 1 deletion crates/proof-of-sql/src/base/polynomial/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ mod composite_polynomial_test;
mod interpolate;
#[cfg(test)]
mod interpolate_test;
pub use interpolate::interpolate_uni_poly;
#[allow(unused_imports)]
pub use interpolate::{interpolate_evaluations_to_reverse_coefficients, interpolate_uni_poly};

mod evaluation_vector;
pub use evaluation_vector::compute_evaluation_vector;
Expand Down

0 comments on commit d4d239c

Please sign in to comment.