Skip to content

Commit

Permalink
refactor!: change sumcheck proof to use coefficients instead of evalu…
Browse files Browse the repository at this point in the history
…ations (#205)

# Rationale for this change

The verifier currently has to use interpolation in order to handle the
sumcheck proof format. It is more efficient for the verifier for the
proof to be the coefficients of the polynomial messages instead of the
evaluations.

# What changes are included in this PR?

See the individual commits.

* Inlined the `Subclaim::create` method.
* Modified sumcheck to use coefficients in the proof instead of
evaluations.

# Are these changes tested?

Yes.
  • Loading branch information
JayWhite2357 authored Oct 3, 2024
2 parents 04c42f3 + 4f20785 commit 3350567
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 68 deletions.
2 changes: 1 addition & 1 deletion crates/proof-of-sql/src/base/polynomial/interpolate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use num_traits::{Inv, One, Zero};
/// For any polynomial, `f(x)`, with degree less than or equal to `d`, we have that:
/// `f(x) = sum_{i=0}^{d} (-1)^(d-i) * (f(i) / (i! * (d-i)! * (x-i))) * prod_{i=0}^{d} (x-i)`
/// unless x is one of 0,1,...,d, in which case, f(x) is already known.
#[allow(dead_code)]
pub fn interpolate_uni_poly<F>(polynomial: &[F], x: F) -> F
where
F: Copy
Expand Down Expand Up @@ -72,7 +73,6 @@ where
/// 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
Expand Down
3 changes: 0 additions & 3 deletions crates/proof-of-sql/src/proof_primitive/sumcheck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ pub use proof::SumcheckProof;
mod prover_state;
use prover_state::ProverState;

mod subclaim;
pub use subclaim::Subclaim;

mod prover_round;
use prover_round::prove_round;

Expand Down
64 changes: 48 additions & 16 deletions crates/proof-of-sql/src/proof_primitive/sumcheck/proof.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::{
base::{
polynomial::{CompositePolynomial, CompositePolynomialInfo},
polynomial::{
interpolate_evaluations_to_reverse_coefficients, CompositePolynomial,
CompositePolynomialInfo,
},
proof::{ProofError, Transcript},
scalar::Scalar,
},
proof_primitive::sumcheck::{prove_round, ProverState, Subclaim},
proof_primitive::sumcheck::{prove_round, ProverState},
};
/**
* Adopted from arkworks
Expand All @@ -16,7 +19,11 @@ use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SumcheckProof<S: Scalar> {
pub(super) evaluations: Vec<Vec<S>>,
pub(super) coefficients: Vec<S>,
}
pub struct Subclaim<S: Scalar> {
pub evaluation_point: Vec<S>,
pub expected_evaluation: S,
}

impl<S: Scalar> SumcheckProof<S> {
Expand All @@ -35,16 +42,18 @@ impl<S: Scalar> SumcheckProof<S> {
transcript.scalar_challenge_as_be::<S>();
let mut r = None;
let mut state = ProverState::create(polynomial);
let mut evaluations = Vec::with_capacity(polynomial.num_variables);
let mut coefficients = Vec::with_capacity(polynomial.num_variables);
for scalar in evaluation_point.iter_mut().take(polynomial.num_variables) {
let round_evaluations = prove_round(&mut state, &r);
transcript.extend_scalars_as_be(&round_evaluations);
let round_coefficients =
interpolate_evaluations_to_reverse_coefficients(&round_evaluations);
transcript.extend_scalars_as_be(&round_coefficients);
coefficients.extend(round_coefficients);
*scalar = transcript.scalar_challenge_as_be();
evaluations.push(round_evaluations);
r = Some(*scalar);
}

SumcheckProof { evaluations }
SumcheckProof { coefficients }
}

#[tracing::instrument(
Expand All @@ -64,21 +73,44 @@ impl<S: Scalar> SumcheckProof<S> {
]);
// This challenge is in order to keep transcript messages grouped. (This simplifies the Solidity implementation.)
transcript.scalar_challenge_as_be::<S>();
if self.evaluations.len() != polynomial_info.num_variables {
if self.coefficients.len()
!= polynomial_info.num_variables * (polynomial_info.max_multiplicands + 1)
{
return Err(ProofError::VerificationError {
error: "invalid number of evaluations",
error: "invalid proof size",
});
}
let mut evaluation_point = Vec::with_capacity(polynomial_info.num_variables);

let mut expected_evaluation = *claimed_sum;
for round_index in 0..polynomial_info.num_variables {
transcript.extend_scalars_as_be(&self.evaluations[round_index]);
evaluation_point.push(transcript.scalar_challenge_as_be());
let start_index = round_index * (polynomial_info.max_multiplicands + 1);
transcript.extend_scalars_as_be(
&self.coefficients
[start_index..start_index + polynomial_info.max_multiplicands + 1],
);
let round_evaluation_point = transcript.scalar_challenge_as_be();
evaluation_point.push(round_evaluation_point);
let mut round_evaluation = self.coefficients[start_index];
let mut actual_sum = round_evaluation
+ self.coefficients[start_index + polynomial_info.max_multiplicands];
for coefficient_index in
start_index + 1..start_index + polynomial_info.max_multiplicands + 1
{
round_evaluation *= round_evaluation_point;
round_evaluation += self.coefficients[coefficient_index];
actual_sum += self.coefficients[coefficient_index];
}
if actual_sum != expected_evaluation {
return Err(ProofError::VerificationError {
error: "round evaluation does not match claimed sum",
});
}
expected_evaluation = round_evaluation;
}
Subclaim::create(
Ok(Subclaim {
evaluation_point,
&self.evaluations,
polynomial_info.max_multiplicands,
claimed_sum,
)
expected_evaluation,
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ fn test_create_verify_proof() {
assert!(subclaim.is_err());

// verify fails if evaluations are changed
proof.evaluations[0][1] += Curve25519Scalar::from(3u64);
proof.coefficients[0] += Curve25519Scalar::from(3u64);
let subclaim = proof.verify_without_evaluation(
&mut transcript,
poly.info(),
Expand Down Expand Up @@ -229,7 +229,7 @@ fn we_can_verify_many_random_test_cases() {
);

let mut modified_proof = proof;
modified_proof.evaluations[0][0] += TestScalar::ONE;
modified_proof.coefficients[0] += TestScalar::ONE;
let mut transcript = Transcript::new(b"sumchecktest");
assert!(
modified_proof
Expand Down
45 changes: 0 additions & 45 deletions crates/proof-of-sql/src/proof_primitive/sumcheck/subclaim.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn sumcheck_test_cases<S: Scalar>(
rng: &mut (impl ark_std::rand::Rng + ?Sized),
) -> impl Iterator<Item = SumcheckTestCase<S>> + '_ {
(1..=8)
.cartesian_product(1..=5)
.cartesian_product(0..=5)
.flat_map(|(num_vars, max_multiplicands)| {
[
Some(vec![]),
Expand Down

0 comments on commit 3350567

Please sign in to comment.