From a922e1ba3a65235bf72ec1511c8c82d1df369656 Mon Sep 17 00:00:00 2001 From: Ian Joiner <14581281+iajoiner@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:36:10 -0500 Subject: [PATCH] feat: allow `FirstRoundBuilder` to produce MLEs --- .../src/sql/proof/first_round_builder.rs | 74 ++++++- .../src/sql/proof/first_round_builder_test.rs | 75 +++++++ crates/proof-of-sql/src/sql/proof/mod.rs | 2 + .../proof-of-sql/src/sql/proof/proof_plan.rs | 2 +- .../proof-of-sql/src/sql/proof/query_proof.rs | 125 +++++++---- .../src/sql/proof/query_proof_test.rs | 203 +++++++++++++++++- .../src/sql/proof/sumcheck_mle_evaluations.rs | 15 +- .../proof/sumcheck_mle_evaluations_test.rs | 1 + .../sql/proof/verifiable_query_result_test.rs | 4 +- .../verifiable_query_result_test_utility.rs | 19 +- .../src/sql/proof/verification_builder.rs | 50 +++-- .../src/sql/proof_exprs/and_expr.rs | 2 +- .../src/sql/proof_exprs/equals_expr.rs | 4 +- .../src/sql/proof_exprs/multiply_expr.rs | 2 +- .../src/sql/proof_exprs/or_expr.rs | 2 +- .../src/sql/proof_gadgets/range_check.rs | 8 +- .../src/sql/proof_gadgets/range_check_test.rs | 2 +- .../src/sql/proof_gadgets/sign_expr.rs | 2 +- .../src/sql/proof_gadgets/sign_expr_test.rs | 2 + .../src/sql/proof_plans/demo_mock_plan.rs | 2 +- .../src/sql/proof_plans/empty_exec.rs | 2 +- .../src/sql/proof_plans/filter_exec.rs | 8 +- .../filter_exec_test_dishonest_prover.rs | 2 +- .../src/sql/proof_plans/group_by_exec.rs | 13 +- .../src/sql/proof_plans/projection_exec.rs | 5 +- .../src/sql/proof_plans/slice_exec.rs | 5 +- .../src/sql/proof_plans/table_exec.rs | 2 +- .../src/sql/proof_plans/union_exec.rs | 9 +- 28 files changed, 532 insertions(+), 110 deletions(-) create mode 100644 crates/proof-of-sql/src/sql/proof/first_round_builder_test.rs diff --git a/crates/proof-of-sql/src/sql/proof/first_round_builder.rs b/crates/proof-of-sql/src/sql/proof/first_round_builder.rs index 15989adf4..432c04123 100644 --- a/crates/proof-of-sql/src/sql/proof/first_round_builder.rs +++ b/crates/proof-of-sql/src/sql/proof/first_round_builder.rs @@ -1,6 +1,16 @@ -use alloc::vec::Vec; +use crate::{ + base::{ + commitment::{Commitment, CommittableColumn, VecCommitmentExt}, + polynomial::MultilinearExtension, + scalar::Scalar, + }, + utils::log, +}; +use alloc::{boxed::Box, vec::Vec}; /// Track the result created by a query -pub struct FirstRoundBuilder { +pub struct FirstRoundBuilder<'a, S> { + commitment_descriptor: Vec>, + pcs_proof_mles: Vec + 'a>>, /// The number of challenges used in the proof. /// Specifically, these are the challenges that the verifier sends to /// the prover after the prover sends the result, but before the prover @@ -10,20 +20,26 @@ pub struct FirstRoundBuilder { one_evaluation_lengths: Vec, } -impl Default for FirstRoundBuilder { +impl<'a, S: Scalar> Default for FirstRoundBuilder<'a, S> { fn default() -> Self { Self::new() } } -impl FirstRoundBuilder { +impl<'a, S: Scalar> FirstRoundBuilder<'a, S> { pub fn new() -> Self { Self { + commitment_descriptor: Vec::new(), + pcs_proof_mles: Vec::new(), num_post_result_challenges: 0, one_evaluation_lengths: Vec::new(), } } + pub fn pcs_proof_mles(&self) -> &[Box + 'a>] { + &self.pcs_proof_mles + } + /// Get the one evaluation lengths used in the proof. pub(crate) fn one_evaluation_lengths(&self) -> &[usize] { &self.one_evaluation_lengths @@ -34,6 +50,56 @@ impl FirstRoundBuilder { self.one_evaluation_lengths.push(length); } + /// Produce an MLE for a intermediate computed column that we can reference in sumcheck. + /// + /// Because the verifier doesn't have access to the MLE's commitment, we will need to + /// commit to the MLE before we form the sumcheck polynomial. + pub fn produce_intermediate_mle( + &mut self, + data: impl MultilinearExtension + Into> + Copy + 'a, + ) { + self.commitment_descriptor.push(data.into()); + self.pcs_proof_mles.push(Box::new(data)); + } + + /// Compute commitments of all the interemdiate MLEs used in sumcheck + #[tracing::instrument( + name = "FirstRoundBuilder::commit_intermediate_mles", + level = "debug", + skip_all + )] + pub fn commit_intermediate_mles( + &self, + offset_generators: usize, + setup: &C::PublicSetup<'_>, + ) -> Vec { + Vec::from_commitable_columns_with_offset( + &self.commitment_descriptor, + offset_generators, + setup, + ) + } + + /// Given the evaluation vector, compute evaluations of all the MLEs used in sumcheck except + /// for those that correspond to result columns sent to the verifier. + #[tracing::instrument( + name = "FirstRoundBuilder::evaluate_pcs_proof_mles", + level = "debug", + skip_all + )] + pub fn evaluate_pcs_proof_mles(&self, evaluation_vec: &[S]) -> Vec { + log::log_memory_usage("Start"); + + let mut res = Vec::with_capacity(self.pcs_proof_mles.len()); + for evaluator in &self.pcs_proof_mles { + res.push(evaluator.inner_product(evaluation_vec)); + } + + log::log_memory_usage("End"); + + res + } + /// The number of challenges used in the proof. /// Specifically, these are the challenges that the verifier sends to /// the prover after the prover sends the result, but before the prover diff --git a/crates/proof-of-sql/src/sql/proof/first_round_builder_test.rs b/crates/proof-of-sql/src/sql/proof/first_round_builder_test.rs new file mode 100644 index 000000000..15171fc37 --- /dev/null +++ b/crates/proof-of-sql/src/sql/proof/first_round_builder_test.rs @@ -0,0 +1,75 @@ +use super::FirstRoundBuilder; +use crate::base::{ + commitment::{Commitment, CommittableColumn}, + scalar::Curve25519Scalar, +}; +use curve25519_dalek::RistrettoPoint; + +#[test] +fn we_can_compute_commitments_for_intermediate_mles_using_a_zero_offset() { + let mle1 = [1, 2]; + let mle2 = [10i64, 20]; + let mut builder = FirstRoundBuilder::::new(); + builder.produce_intermediate_mle(&mle1[..]); + builder.produce_intermediate_mle(&mle2[..]); + let offset_generators = 0_usize; + let commitments: Vec = builder.commit_intermediate_mles(offset_generators, &()); + let expected_commitments: Vec = RistrettoPoint::compute_commitments( + &[ + CommittableColumn::from(&mle1[..]), + CommittableColumn::from(&mle2[..]), + ], + offset_generators, + &(), + ); + assert_eq!(commitments, expected_commitments,); +} + +#[test] +fn we_can_compute_commitments_for_intermediate_mles_using_a_non_zero_offset() { + let mle1 = [1, 2]; + let mle2 = [10i64, 20]; + let mut builder = FirstRoundBuilder::::new(); + builder.produce_intermediate_mle(&mle1[..]); + builder.produce_intermediate_mle(&mle2[..]); + let offset_generators = 123_usize; + let commitments: Vec = builder.commit_intermediate_mles(offset_generators, &()); + let expected_commitments: Vec = RistrettoPoint::compute_commitments( + &[ + CommittableColumn::from(&mle1[..]), + CommittableColumn::from(&mle2[..]), + ], + offset_generators, + &(), + ); + assert_eq!(commitments, expected_commitments,); +} + +#[test] +fn we_can_evaluate_pcs_proof_mles() { + let mle1 = [1, 2]; + let mle2 = [10i64, 20]; + let mut builder = FirstRoundBuilder::::new(); + builder.produce_intermediate_mle(&mle1[..]); + builder.produce_intermediate_mle(&mle2[..]); + let evaluation_vec = [ + Curve25519Scalar::from(100u64), + Curve25519Scalar::from(10u64), + ]; + let evals = builder.evaluate_pcs_proof_mles(&evaluation_vec); + let expected_evals = [ + Curve25519Scalar::from(120u64), + Curve25519Scalar::from(1200u64), + ]; + assert_eq!(evals, expected_evals); +} + +#[test] +fn we_can_add_post_result_challenges() { + let mut builder = FirstRoundBuilder::::new(); + assert_eq!(builder.num_post_result_challenges(), 0); + builder.request_post_result_challenges(1); + assert_eq!(builder.num_post_result_challenges(), 1); + builder.request_post_result_challenges(2); + assert_eq!(builder.num_post_result_challenges(), 3); +} diff --git a/crates/proof-of-sql/src/sql/proof/mod.rs b/crates/proof-of-sql/src/sql/proof/mod.rs index 96dfc5874..7b64a99d5 100644 --- a/crates/proof-of-sql/src/sql/proof/mod.rs +++ b/crates/proof-of-sql/src/sql/proof/mod.rs @@ -63,6 +63,8 @@ pub(crate) use result_element_serialization::{ mod first_round_builder; pub(crate) use first_round_builder::FirstRoundBuilder; +#[cfg(all(test, feature = "blitzar"))] +mod first_round_builder_test; #[cfg(all(test, feature = "arrow"))] mod provable_query_result_test; diff --git a/crates/proof-of-sql/src/sql/proof/proof_plan.rs b/crates/proof-of-sql/src/sql/proof/proof_plan.rs index a84dcdab7..f5c5c5fbe 100644 --- a/crates/proof-of-sql/src/sql/proof/proof_plan.rs +++ b/crates/proof-of-sql/src/sql/proof/proof_plan.rs @@ -36,7 +36,7 @@ pub trait ProverEvaluate { /// Evaluate the query, modify `FirstRoundBuilder` and return the result. fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S>; diff --git a/crates/proof-of-sql/src/sql/proof/query_proof.rs b/crates/proof-of-sql/src/sql/proof/query_proof.rs index 708b330d1..bfbfd2f9d 100644 --- a/crates/proof-of-sql/src/sql/proof/query_proof.rs +++ b/crates/proof-of-sql/src/sql/proof/query_proof.rs @@ -57,12 +57,16 @@ pub(super) struct QueryProof { pub bit_distributions: Vec, /// One evaluation lengths pub one_evaluation_lengths: Vec, - /// Commitments - pub commitments: Vec, + /// First Round Commitments + pub first_round_commitments: Vec, + /// Final Round Commitments + pub final_round_commitments: Vec, /// Sumcheck Proof pub sumcheck_proof: SumcheckProof, - /// MLEs used in sumcheck except for the result columns - pub pcs_proof_evaluations: Vec, + /// MLEs used in first round sumcheck except for the result columns + pub first_round_pcs_proof_evaluations: Vec, + /// MLEs used in final round sumcheck except for the result columns + pub final_round_pcs_proof_evaluations: Vec, /// Inner product proof of the MLEs' evaluations pub evaluation_proof: CP, /// Length of the range of generators we use @@ -100,7 +104,7 @@ impl QueryProof { .collect(); // Prover First Round: Evaluate the query && get the right number of post result challenges - let mut first_round_builder = FirstRoundBuilder::new(); + let mut first_round_builder = FirstRoundBuilder::::new(); let query_result = expr.first_round_evaluate(&mut first_round_builder, &alloc, &table_map); let owned_table_result = OwnedTable::from(&query_result); let provable_result = query_result.into(); @@ -117,6 +121,10 @@ impl QueryProof { assert!(num_sumcheck_variables > 0); let post_result_challenge_count = first_round_builder.num_post_result_challenges(); + // commit to any intermediate MLEs + let first_round_commitments = + first_round_builder.commit_intermediate_mles(min_row_num, setup); + // construct a transcript for the proof let mut transcript: Keccak256Transcript = make_transcript( expr, @@ -125,6 +133,7 @@ impl QueryProof { min_row_num, one_evaluation_lengths, post_result_challenge_count, + &first_round_commitments, ); // These are the challenges that will be consumed by the proof @@ -137,35 +146,37 @@ impl QueryProof { .take(post_result_challenge_count) .collect(); - let mut builder = FinalRoundBuilder::new(num_sumcheck_variables, post_result_challenges); + let mut final_round_builder = + FinalRoundBuilder::new(num_sumcheck_variables, post_result_challenges); for col_ref in total_col_refs { - builder.produce_anchored_mle(accessor.get_column(col_ref)); + final_round_builder.produce_anchored_mle(accessor.get_column(col_ref)); } - expr.final_round_evaluate(&mut builder, &alloc, &table_map); + expr.final_round_evaluate(&mut final_round_builder, &alloc, &table_map); - let num_sumcheck_variables = builder.num_sumcheck_variables(); + let num_sumcheck_variables = final_round_builder.num_sumcheck_variables(); // commit to any intermediate MLEs - let commitments = builder.commit_intermediate_mles(min_row_num, setup); + let final_round_commitments = + final_round_builder.commit_intermediate_mles(min_row_num, setup); // add the commitments, bit distributions and one evaluation lengths to the proof extend_transcript_with_commitments( &mut transcript, - &commitments, - builder.bit_distributions(), + &final_round_commitments, + final_round_builder.bit_distributions(), ); // construct the sumcheck polynomial - let subpolynomial_constraint_count = builder.num_sumcheck_subpolynomials(); + let subpolynomial_constraint_count = final_round_builder.num_sumcheck_subpolynomials(); let num_random_scalars = num_sumcheck_variables + subpolynomial_constraint_count; let random_scalars: Vec<_> = core::iter::repeat_with(|| transcript.scalar_challenge_as_be()) .take(num_random_scalars) .collect(); let state = make_sumcheck_prover_state( - builder.sumcheck_subpolynomials(), + final_round_builder.sumcheck_subpolynomials(), num_sumcheck_variables, &SumcheckRandomScalars::new(&random_scalars, range_length, num_sumcheck_variables), ); @@ -177,21 +188,36 @@ impl QueryProof { // evaluate the MLEs used in sumcheck except for the result columns let mut evaluation_vec = vec![Zero::zero(); range_length]; compute_evaluation_vector(&mut evaluation_vec, &evaluation_point); - let pcs_proof_evaluations = builder.evaluate_pcs_proof_mles(&evaluation_vec); + let first_round_pcs_proof_evaluations = + first_round_builder.evaluate_pcs_proof_mles(&evaluation_vec); + let final_round_pcs_proof_evaluations = + final_round_builder.evaluate_pcs_proof_mles(&evaluation_vec); // commit to the MLE evaluations - transcript.extend_canonical_serialize_as_le(&pcs_proof_evaluations); + transcript.extend_canonical_serialize_as_le(&first_round_pcs_proof_evaluations); + transcript.extend_canonical_serialize_as_le(&final_round_pcs_proof_evaluations); // fold together the pre result MLEs -- this will form the input to an inner product proof // of their evaluations (fold in this context means create a random linear combination) let random_scalars: Vec<_> = core::iter::repeat_with(|| transcript.scalar_challenge_as_be()) - .take(pcs_proof_evaluations.len()) + .take( + first_round_pcs_proof_evaluations.len() + + final_round_pcs_proof_evaluations.len(), + ) .collect(); - assert_eq!(random_scalars.len(), builder.pcs_proof_mles().len()); + assert_eq!( + random_scalars.len(), + first_round_builder.pcs_proof_mles().len() + final_round_builder.pcs_proof_mles().len() + ); let mut folded_mle = vec![Zero::zero(); range_length]; - for (multiplier, evaluator) in random_scalars.iter().zip(builder.pcs_proof_mles().iter()) { + for (multiplier, evaluator) in random_scalars.iter().zip( + first_round_builder + .pcs_proof_mles() + .iter() + .chain(final_round_builder.pcs_proof_mles().iter()), + ) { evaluator.mul_add(&mut folded_mle, multiplier); } @@ -205,11 +231,13 @@ impl QueryProof { ); let proof = Self { - bit_distributions: builder.bit_distributions().to_vec(), + bit_distributions: final_round_builder.bit_distributions().to_vec(), one_evaluation_lengths: one_evaluation_lengths.to_vec(), - commitments, + first_round_commitments, + final_round_commitments, sumcheck_proof, - pcs_proof_evaluations, + first_round_pcs_proof_evaluations, + final_round_pcs_proof_evaluations, evaluation_proof, range_length, subpolynomial_constraint_count, @@ -260,6 +288,7 @@ impl QueryProof { min_row_num, &self.one_evaluation_lengths, self.post_result_challenge_count, + &self.first_round_commitments, ); // These are the challenges that will be consumed by the proof @@ -272,10 +301,10 @@ impl QueryProof { .take(self.post_result_challenge_count) .collect(); - // add the commitments and bit disctibutions to the proof + // add the commitments and bit distributions to the proof extend_transcript_with_commitments( &mut transcript, - &self.commitments, + &self.final_round_commitments, &self.bit_distributions, ); @@ -298,13 +327,17 @@ impl QueryProof { )?; // commit to mle evaluations - transcript.extend_canonical_serialize_as_le(&self.pcs_proof_evaluations); + transcript.extend_canonical_serialize_as_le(&self.first_round_pcs_proof_evaluations); + transcript.extend_canonical_serialize_as_le(&self.final_round_pcs_proof_evaluations); // draw the random scalars for the evaluation proof // (i.e. the folding/random linear combination of the pcs_proof_mles) let evaluation_random_scalars: Vec<_> = core::iter::repeat_with(|| transcript.scalar_challenge_as_be()) - .take(self.pcs_proof_evaluations.len()) + .take( + self.first_round_pcs_proof_evaluations.len() + + self.final_round_pcs_proof_evaluations.len(), + ) .collect(); // Always prepend input lengths to the one evaluation lengths @@ -324,7 +357,8 @@ impl QueryProof { one_evaluation_lengths, &subclaim.evaluation_point, &sumcheck_random_scalars, - &self.pcs_proof_evaluations, + &self.first_round_pcs_proof_evaluations, + &self.final_round_pcs_proof_evaluations, ); let one_eval_map: IndexMap = table_length_map .iter() @@ -340,14 +374,20 @@ impl QueryProof { subclaim.max_multiplicands, ); - let pcs_proof_commitments: Vec<_> = column_references + let pcs_proof_commitments: Vec<_> = self + .first_round_commitments .iter() - .map(|col| accessor.get_commitment(col.clone())) - .chain(self.commitments.iter().cloned()) + .cloned() + .chain( + column_references + .iter() + .map(|col| accessor.get_commitment(col.clone())), + ) + .chain(self.final_round_commitments.iter().cloned()) .collect(); let evaluation_accessor: IndexMap<_, _> = column_references .into_iter() - .map(|col| Ok((col, builder.try_consume_mle_evaluation()?))) + .map(|col| Ok((col, builder.try_consume_final_round_mle_evaluation()?))) .collect::>()?; let verifier_evaluations = expr.verifier_evaluate( @@ -372,13 +412,20 @@ impl QueryProof { })?; } + let pcs_proof_evaluations: Vec<_> = self + .first_round_pcs_proof_evaluations + .iter() + .chain(self.final_round_pcs_proof_evaluations.iter()) + .copied() + .collect(); + // finally, check the MLE evaluations with the inner product proof self.evaluation_proof .verify_batched_proof( &mut transcript, &pcs_proof_commitments, &evaluation_random_scalars, - &self.pcs_proof_evaluations, + &pcs_proof_evaluations, &subclaim.evaluation_point, min_row_num as u64, self.range_length, @@ -412,17 +459,20 @@ impl QueryProof { /// * `range_length` - The length of the range of generators used. /// * `min_row_num` - The minimum row number in the index range of the tables referenced by the query. /// * `one_evaluation_lengths` - The lengths of the one evaluations. +/// * `post_result_challenge_count` - The number of post-result challenges. +/// * `first_round_commitments` - A slice of commitments produced before post-result challenges that are part of the proof. /// /// # Returns /// /// A transcript initialized with the provided data. -fn make_transcript( +fn make_transcript( expr: &(impl ProofPlan + Serialize), - result: &OwnedTable, + result: &OwnedTable, range_length: usize, min_row_num: usize, one_evaluation_lengths: &[usize], post_result_challenge_count: usize, + first_round_commitments: &[C], ) -> T { let mut transcript = T::new(); extend_transcript_with_owned_table(&mut transcript, result); @@ -431,6 +481,9 @@ fn make_transcript( transcript.extend_serialize_as_le(&min_row_num); transcript.extend_serialize_as_le(one_evaluation_lengths); transcript.extend_serialize_as_le(&post_result_challenge_count); + for commitment in first_round_commitments { + commitment.append_to_transcript(&mut transcript); + } transcript } @@ -486,10 +539,10 @@ fn extend_transcript_with_owned_table( /// * `bit_distributions` - The bit distributions to add to the transcript. fn extend_transcript_with_commitments( transcript: &mut impl Transcript, - commitments: &[C], + final_round_commitments: &[C], bit_distributions: &[BitDistribution], ) { - for commitment in commitments { + for commitment in final_round_commitments { commitment.append_to_transcript(transcript); } transcript.extend_serialize_as_le(bit_distributions); diff --git a/crates/proof-of-sql/src/sql/proof/query_proof_test.rs b/crates/proof-of-sql/src/sql/proof/query_proof_test.rs index e88c7ba7b..878a5915b 100644 --- a/crates/proof-of-sql/src/sql/proof/query_proof_test.rs +++ b/crates/proof-of-sql/src/sql/proof/query_proof_test.rs @@ -48,7 +48,7 @@ impl Default for TrivialTestProofPlan { impl ProverEvaluate for TrivialTestProofPlan { fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, _table_map: &IndexMap>, ) -> Table<'a, S> { @@ -89,7 +89,7 @@ impl ProofPlan for TrivialTestProofPlan { _result: Option<&OwnedTable>, _one_eval_map: &IndexMap, ) -> Result, ProofError> { - assert_eq!(builder.try_consume_mle_evaluation()?, S::ZERO); + assert_eq!(builder.try_consume_final_round_mle_evaluation()?, S::ZERO); builder.try_produce_sumcheck_subpolynomial_evaluation( SumcheckSubpolynomialType::ZeroSum, S::from(self.evaluation), @@ -263,7 +263,7 @@ impl Default for SquareTestProofPlan { impl ProverEvaluate for SquareTestProofPlan { fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, _table_map: &IndexMap>, ) -> Table<'a, S> { @@ -311,7 +311,7 @@ impl ProofPlan for SquareTestProofPlan { ColumnType::BigInt, )) .unwrap(); - let res_eval = builder.try_consume_mle_evaluation()?; + let res_eval = builder.try_consume_final_round_mle_evaluation()?; builder.try_produce_sumcheck_subpolynomial_evaluation( SumcheckSubpolynomialType::Identity, res_eval - x_eval * x_eval, @@ -442,7 +442,7 @@ impl Default for DoubleSquareTestProofPlan { impl ProverEvaluate for DoubleSquareTestProofPlan { fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, _table_map: &IndexMap>, ) -> Table<'a, S> { @@ -502,8 +502,8 @@ impl ProofPlan for DoubleSquareTestProofPlan { ColumnType::BigInt, )) .unwrap(); - let z_eval = builder.try_consume_mle_evaluation()?; - let res_eval = builder.try_consume_mle_evaluation()?; + let z_eval = builder.try_consume_final_round_mle_evaluation()?; + let res_eval = builder.try_consume_final_round_mle_evaluation()?; // poly1 builder.try_produce_sumcheck_subpolynomial_evaluation( @@ -600,7 +600,8 @@ fn verify_fails_if_an_intermediate_commitment_doesnt_match() { (), ); let (mut proof, result) = QueryProof::::new(&expr, &accessor, &()); - proof.commitments[0] = proof.commitments[0] * Curve25519Scalar::from(2u64); + proof.final_round_commitments[0] = + proof.final_round_commitments[0] * Curve25519Scalar::from(2u64); assert!(proof.verify(&expr, &accessor, result, &()).is_err()); } @@ -652,7 +653,7 @@ struct ChallengeTestProofPlan {} impl ProverEvaluate for ChallengeTestProofPlan { fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, _table_map: &IndexMap>, ) -> Table<'a, S> { @@ -704,7 +705,7 @@ impl ProofPlan for ChallengeTestProofPlan { ColumnType::BigInt, )) .unwrap(); - let res_eval = builder.try_consume_mle_evaluation()?; + let res_eval = builder.try_consume_final_round_mle_evaluation()?; builder.try_produce_sumcheck_subpolynomial_evaluation( SumcheckSubpolynomialType::Identity, alpha * res_eval - alpha * x_eval * x_eval, @@ -773,3 +774,185 @@ fn we_can_verify_a_proof_with_a_post_result_challenge_and_with_a_zero_offset() { fn we_can_verify_a_proof_with_a_post_result_challenge_and_with_a_non_zero_offset() { verify_a_proof_with_a_post_result_challenge_and_given_offset(123); } + +/// prove and verify an artificial query where +/// `res_i = x_i * x_i` +/// where the commitment for x is known +#[derive(Debug, Serialize)] +struct FirstRoundSquareTestProofPlan { + res: [i64; 2], + anchored_commit_multiplier: i64, +} +impl Default for FirstRoundSquareTestProofPlan { + fn default() -> Self { + Self { + res: [9, 25], + anchored_commit_multiplier: 1, + } + } +} +impl ProverEvaluate for FirstRoundSquareTestProofPlan { + fn first_round_evaluate<'a, S: Scalar>( + &self, + builder: &mut FirstRoundBuilder<'a, S>, + alloc: &'a Bump, + _table_map: &IndexMap>, + ) -> Table<'a, S> { + let res: &[_] = alloc.alloc_slice_copy(&self.res); + builder.produce_intermediate_mle(res); + builder.produce_one_evaluation_length(2); + table([borrowed_bigint("a1", self.res, alloc)]) + } + + fn final_round_evaluate<'a, S: Scalar>( + &self, + builder: &mut FinalRoundBuilder<'a, S>, + alloc: &'a Bump, + table_map: &IndexMap>, + ) -> Table<'a, S> { + let x = *table_map + .get(&TableRef::new("sxt.test".parse().unwrap())) + .unwrap() + .inner_table() + .get(&Ident::new("x")) + .unwrap(); + let res: &[_] = alloc.alloc_slice_copy(&self.res); + builder.produce_intermediate_mle(res); + builder.produce_sumcheck_subpolynomial( + SumcheckSubpolynomialType::Identity, + vec![ + (S::ONE, vec![Box::new(res)]), + (-S::ONE, vec![Box::new(x), Box::new(x)]), + ], + ); + table([borrowed_bigint("a1", self.res, alloc)]) + } +} +impl ProofPlan for FirstRoundSquareTestProofPlan { + fn verifier_evaluate( + &self, + builder: &mut VerificationBuilder, + accessor: &IndexMap, + _result: Option<&OwnedTable>, + _one_eval_map: &IndexMap, + ) -> Result, ProofError> { + let x_eval = S::from(self.anchored_commit_multiplier) + * *accessor + .get(&ColumnRef::new( + "sxt.test".parse().unwrap(), + "x".into(), + ColumnType::BigInt, + )) + .unwrap(); + let first_round_res_eval = builder.try_consume_first_round_mle_evaluation()?; + let final_round_res_eval = builder.try_consume_final_round_mle_evaluation()?; + assert_eq!(first_round_res_eval, final_round_res_eval); + builder.try_produce_sumcheck_subpolynomial_evaluation( + SumcheckSubpolynomialType::Identity, + final_round_res_eval - x_eval * x_eval, + 2, + )?; + Ok(TableEvaluation::new( + vec![final_round_res_eval], + builder.try_consume_one_evaluation()?, + )) + } + fn get_column_result_fields(&self) -> Vec { + vec![ColumnField::new("a1".into(), ColumnType::BigInt)] + } + fn get_column_references(&self) -> IndexSet { + indexset! {ColumnRef::new( + "sxt.test".parse().unwrap(), + "x".into(), + ColumnType::BigInt, + )} + } + fn get_table_references(&self) -> IndexSet { + indexset! {TableRef::new("sxt.test".parse().unwrap())} + } +} + +fn verify_a_proof_with_a_commitment_and_given_offset(offset_generators: usize) { + // prove and verify an artificial query where + // res_i = x_i * x_i + // where the commitment for x is known + let expr = FirstRoundSquareTestProofPlan { + ..Default::default() + }; + let accessor = OwnedTableTestAccessor::::new_from_table( + "sxt.test".parse().unwrap(), + owned_table([bigint("x", [3, 5])]), + offset_generators, + (), + ); + let (proof, result) = QueryProof::::new(&expr, &accessor, &()); + let QueryData { + verification_hash, + table, + } = proof + .clone() + .verify(&expr, &accessor, result.clone(), &()) + .unwrap(); + assert_ne!(verification_hash, [0; 32]); + let expected_result = owned_table([bigint("a1", [9, 25])]); + assert_eq!(table, expected_result); + + // invalid offset will fail to verify + let accessor = OwnedTableTestAccessor::::new_from_table( + "sxt.test".parse().unwrap(), + owned_table([bigint("x", [3, 5])]), + offset_generators + 1, + (), + ); + assert!(proof.verify(&expr, &accessor, result, &()).is_err()); +} + +#[test] +fn we_can_verify_a_proof_with_a_commitment_and_with_a_zero_offset() { + verify_a_proof_with_a_commitment_and_given_offset(0); +} + +#[test] +fn we_can_verify_a_proof_with_a_commitment_and_with_a_non_zero_offset() { + verify_a_proof_with_a_commitment_and_given_offset(123); +} + +#[test] +fn verify_fails_if_the_result_doesnt_satisfy_an_equation() { + // attempt to prove and verify an artificial query where + // res_i = x_i * x_i + // where the commitment for x is known and + // res_i != x_i * x_i + // for some i + let expr = FirstRoundSquareTestProofPlan { + res: [9, 26], + ..Default::default() + }; + let accessor = OwnedTableTestAccessor::::new_from_table( + "sxt.test".parse().unwrap(), + owned_table([bigint("x", [3, 5])]), + 0, + (), + ); + let (proof, result) = QueryProof::::new(&expr, &accessor, &()); + assert!(proof.verify(&expr, &accessor, result, &()).is_err()); +} + +#[test] +fn verify_fails_if_the_commitment_doesnt_match() { + // prove and verify an artificial query where + // res_i = x_i * x_i + // where the commitment for x is known + let expr = FirstRoundSquareTestProofPlan { + anchored_commit_multiplier: 2, + ..Default::default() + }; + let accessor = OwnedTableTestAccessor::::new_from_table( + "sxt.test".parse().unwrap(), + owned_table([bigint("x", [3, 5])]), + 0, + (), + ); + let (proof, result) = QueryProof::::new(&expr, &accessor, &()); + assert!(proof.verify(&expr, &accessor, result, &()).is_err()); +} diff --git a/crates/proof-of-sql/src/sql/proof/sumcheck_mle_evaluations.rs b/crates/proof-of-sql/src/sql/proof/sumcheck_mle_evaluations.rs index 81d516113..1297e626b 100644 --- a/crates/proof-of-sql/src/sql/proof/sumcheck_mle_evaluations.rs +++ b/crates/proof-of-sql/src/sql/proof/sumcheck_mle_evaluations.rs @@ -24,8 +24,10 @@ pub struct SumcheckMleEvaluations<'a, S: Scalar> { /// This is used within sumcheck to establish that a given expression /// is zero across all entries. pub random_evaluation: S, - /// The evaluations (at the random point generated by sumcheck) of the mles that are evaluated by the inner product argument. These are batched together and checked by a single IPA. - pub pcs_proof_evaluations: &'a [S], + /// The evaluations (at the random point generated by sumcheck) of the first round mles that are evaluated by the inner product argument. These are batched together and checked by a single IPA. + pub first_round_pcs_proof_evaluations: &'a [S], + /// The evaluations (at the random point generated by sumcheck) of the final round mles that are evaluated by the inner product argument. These are batched together and checked by a single IPA. + pub final_round_pcs_proof_evaluations: &'a [S], /// Evaluation (at the random point generated by sumcheck) of the function `rho_256` that is defined by `rho_256(x)` = x when 0 <= x < 256 and 0 otherwise. pub rho_256_evaluation: Option, @@ -41,13 +43,15 @@ impl<'a, S: Scalar> SumcheckMleEvaluations<'a, S> { /// # Inputs /// - `evaluation_point` - the point, outputted by sumcheck, at which to evaluate the MLEs /// - `sumcheck_random_scalars` - the random scalars used to batch the evaluations that are proven via IPA - /// - `pcs_proof_evaluations` - the evaluations of the MLEs that are proven via IPA + /// - `first_round_pcs_proof_evaluations` - the evaluations of the first round MLEs that are proven via IPA + /// - `final_round_pcs_proof_evaluations` - the evaluations of the final round MLEs that are proven via IPA pub fn new( range_length: usize, one_evaluation_lengths: impl IntoIterator, evaluation_point: &[S], sumcheck_random_scalars: &SumcheckRandomScalars, - pcs_proof_evaluations: &'a [S], + first_round_pcs_proof_evaluations: &'a [S], + final_round_pcs_proof_evaluations: &'a [S], ) -> Self { let rho_256_evaluation = if evaluation_point.len() < 8 { None @@ -92,7 +96,8 @@ impl<'a, S: Scalar> SumcheckMleEvaluations<'a, S> { one_evaluations, singleton_one_evaluation, random_evaluation, - pcs_proof_evaluations, + first_round_pcs_proof_evaluations, + final_round_pcs_proof_evaluations, rho_256_evaluation, } } diff --git a/crates/proof-of-sql/src/sql/proof/sumcheck_mle_evaluations_test.rs b/crates/proof-of-sql/src/sql/proof/sumcheck_mle_evaluations_test.rs index 4e60e5e47..a5dffd605 100644 --- a/crates/proof-of-sql/src/sql/proof/sumcheck_mle_evaluations_test.rs +++ b/crates/proof-of-sql/src/sql/proof/sumcheck_mle_evaluations_test.rs @@ -19,6 +19,7 @@ fn we_can_track_the_evaluation_of_mles_used_within_sumcheck() { &evaluation_point, &sumcheck_random_scalars, &pcs_proof_evaluations, + &[], ); let expected_eval = (Curve25519Scalar::one() - evaluation_point[0]) * (Curve25519Scalar::one() - evaluation_point[1]) diff --git a/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test.rs b/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test.rs index f49a75d94..7dbcc48ef 100644 --- a/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test.rs +++ b/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test.rs @@ -27,7 +27,7 @@ pub(super) struct EmptyTestQueryExpr { impl ProverEvaluate for EmptyTestQueryExpr { fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, _table_map: &IndexMap>, ) -> Table<'a, S> { @@ -67,7 +67,7 @@ impl ProofPlan for EmptyTestQueryExpr { _one_eval_map: &IndexMap, ) -> Result, ProofError> { assert_eq!( - builder.try_consume_mle_evaluations(self.columns)?, + builder.try_consume_final_round_mle_evaluations(self.columns)?, vec![S::ZERO; self.columns] ); Ok(TableEvaluation::new( diff --git a/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test_utility.rs b/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test_utility.rs index 461ae0c1a..35b27376f 100644 --- a/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test_utility.rs +++ b/crates/proof-of-sql/src/sql/proof/verifiable_query_result_test_utility.rs @@ -19,7 +19,7 @@ use serde::Serialize; /// Will panic if: /// - The verification of `res` does not succeed, causing the assertion `assert!(res.verify(...).is_ok())` to fail. /// - `res.proof` is `None`, causing `res.proof.as_ref().unwrap()` to panic. -/// - Attempting to modify `pcs_proof_evaluations` or `commitments` if `res_p.proof` is `None`, leading to a panic on `unwrap()`. +/// - Attempting to modify `final_round_pcs_proof_evaluations` or `commitments` if `res_p.proof` is `None`, leading to a panic on `unwrap()`. /// - `fake_accessor.update_offset` fails, causing a panic if it is designed to do so in the implementation. pub fn exercise_verification( res: &VerifiableQueryResult, @@ -43,9 +43,13 @@ pub fn exercise_verification( assert!(res_p.verify(expr, accessor, &()).is_err()); // try changing MLE evaluations - for i in 0..proof.pcs_proof_evaluations.len() { + for i in 0..proof.final_round_pcs_proof_evaluations.len() { let mut res_p = res.clone(); - res_p.proof.as_mut().unwrap().pcs_proof_evaluations[i] += Curve25519Scalar::one(); + res_p + .proof + .as_mut() + .unwrap() + .final_round_pcs_proof_evaluations[i] += Curve25519Scalar::one(); assert!(res_p.verify(expr, accessor, &()).is_err()); } @@ -59,9 +63,9 @@ pub fn exercise_verification( &(), )[0]; - for i in 0..proof.commitments.len() { + for i in 0..proof.final_round_commitments.len() { let mut res_p = res.clone(); - res_p.proof.as_mut().unwrap().commitments[i] = commit_p; + res_p.proof.as_mut().unwrap().final_round_commitments[i] = commit_p; assert!(res_p.verify(expr, accessor, &()).is_err()); } @@ -71,7 +75,10 @@ pub fn exercise_verification( // the inner product proof isn't dependent on the generators since it simply sends the input // vector; hence, changing the offset would have no effect. if accessor.get_length(table_ref) > 1 - || proof.commitments.iter().any(|&c| c != Identity::identity()) + || proof + .final_round_commitments + .iter() + .any(|&c| c != Identity::identity()) { let offset_generators = accessor.get_offset(table_ref); let mut fake_accessor = accessor.clone(); diff --git a/crates/proof-of-sql/src/sql/proof/verification_builder.rs b/crates/proof-of-sql/src/sql/proof/verification_builder.rs index f04435471..eec3dff15 100644 --- a/crates/proof-of-sql/src/sql/proof/verification_builder.rs +++ b/crates/proof-of-sql/src/sql/proof/verification_builder.rs @@ -11,7 +11,8 @@ pub struct VerificationBuilder<'a, S: Scalar> { sumcheck_evaluation: S, bit_distributions: &'a [BitDistribution], consumed_one_evaluations: usize, - consumed_pcs_proof_mles: usize, + consumed_first_round_pcs_proof_mles: usize, + consumed_final_round_pcs_proof_mles: usize, produced_subpolynomials: usize, /// The challenges used in creation of the constraints in the proof. /// Specifically, these are the challenges that the verifier sends to @@ -46,7 +47,8 @@ impl<'a, S: Scalar> VerificationBuilder<'a, S> { subpolynomial_multipliers, sumcheck_evaluation: S::zero(), consumed_one_evaluations: 0, - consumed_pcs_proof_mles: 0, + consumed_first_round_pcs_proof_mles: 0, + consumed_final_round_pcs_proof_mles: 0, produced_subpolynomials: 0, post_result_challenges, one_evaluation_length_queue, @@ -77,25 +79,44 @@ impl<'a, S: Scalar> VerificationBuilder<'a, S> { self.generator_offset } - /// Consume the evaluation of an anchored MLE used in sumcheck and provide the commitment of the MLE - /// - /// An anchored MLE is an MLE where the verifier has access to the commitment - pub fn try_consume_mle_evaluation(&mut self) -> Result { - let index = self.consumed_pcs_proof_mles; - self.consumed_pcs_proof_mles += 1; + /// Consume the evaluation of a first round MLE used in sumcheck and provide the commitment of the MLE + pub fn try_consume_first_round_mle_evaluation(&mut self) -> Result { + let index = self.consumed_first_round_pcs_proof_mles; + self.consumed_first_round_pcs_proof_mles += 1; + self.mle_evaluations + .first_round_pcs_proof_evaluations + .get(index) + .copied() + .ok_or(ProofSizeMismatch::TooFewMLEEvaluations) + } + + /// Consume multiple first round MLE evaluations + pub fn try_consume_first_round_mle_evaluations( + &mut self, + count: usize, + ) -> Result, ProofSizeMismatch> { + iter::repeat_with(|| self.try_consume_first_round_mle_evaluation()) + .take(count) + .collect() + } + + /// Consume the evaluation of a final round MLE used in sumcheck and provide the commitment of the MLE + pub fn try_consume_final_round_mle_evaluation(&mut self) -> Result { + let index = self.consumed_final_round_pcs_proof_mles; + self.consumed_final_round_pcs_proof_mles += 1; self.mle_evaluations - .pcs_proof_evaluations + .final_round_pcs_proof_evaluations .get(index) .copied() .ok_or(ProofSizeMismatch::TooFewMLEEvaluations) } - /// Consume multiple MLE evaluations - pub fn try_consume_mle_evaluations( + /// Consume multiple final round MLE evaluations + pub fn try_consume_final_round_mle_evaluations( &mut self, count: usize, ) -> Result, ProofSizeMismatch> { - iter::repeat_with(|| self.try_consume_mle_evaluation()) + iter::repeat_with(|| self.try_consume_final_round_mle_evaluation()) .take(count) .collect() } @@ -156,7 +177,10 @@ impl<'a, S: Scalar> VerificationBuilder<'a, S> { fn completed(&self) -> bool { self.bit_distributions.is_empty() && self.produced_subpolynomials == self.subpolynomial_multipliers.len() - && self.consumed_pcs_proof_mles == self.mle_evaluations.pcs_proof_evaluations.len() + && self.consumed_first_round_pcs_proof_mles + == self.mle_evaluations.first_round_pcs_proof_evaluations.len() + && self.consumed_final_round_pcs_proof_mles + == self.mle_evaluations.final_round_pcs_proof_evaluations.len() && self.post_result_challenges.is_empty() } diff --git a/crates/proof-of-sql/src/sql/proof_exprs/and_expr.rs b/crates/proof-of-sql/src/sql/proof_exprs/and_expr.rs index 7bfab82c0..f35f5b56d 100644 --- a/crates/proof-of-sql/src/sql/proof_exprs/and_expr.rs +++ b/crates/proof-of-sql/src/sql/proof_exprs/and_expr.rs @@ -97,7 +97,7 @@ impl ProofExpr for AndExpr { let rhs = self.rhs.verifier_evaluate(builder, accessor, one_eval)?; // lhs_and_rhs - let lhs_and_rhs = builder.try_consume_mle_evaluation()?; + let lhs_and_rhs = builder.try_consume_final_round_mle_evaluation()?; // subpolynomial: lhs_and_rhs - lhs * rhs builder.try_produce_sumcheck_subpolynomial_evaluation( diff --git a/crates/proof-of-sql/src/sql/proof_exprs/equals_expr.rs b/crates/proof-of-sql/src/sql/proof_exprs/equals_expr.rs index c88b10aff..9ec0d78f3 100644 --- a/crates/proof-of-sql/src/sql/proof_exprs/equals_expr.rs +++ b/crates/proof-of-sql/src/sql/proof_exprs/equals_expr.rs @@ -161,8 +161,8 @@ pub fn verifier_evaluate_equals_zero( one_eval: S, ) -> Result { // consume mle evaluations - let lhs_pseudo_inv_eval = builder.try_consume_mle_evaluation()?; - let selection_not_eval = builder.try_consume_mle_evaluation()?; + let lhs_pseudo_inv_eval = builder.try_consume_final_round_mle_evaluation()?; + let selection_not_eval = builder.try_consume_final_round_mle_evaluation()?; let selection_eval = one_eval - selection_not_eval; // subpolynomial: selection * lhs diff --git a/crates/proof-of-sql/src/sql/proof_exprs/multiply_expr.rs b/crates/proof-of-sql/src/sql/proof_exprs/multiply_expr.rs index 867221b55..b85863638 100644 --- a/crates/proof-of-sql/src/sql/proof_exprs/multiply_expr.rs +++ b/crates/proof-of-sql/src/sql/proof_exprs/multiply_expr.rs @@ -92,7 +92,7 @@ impl ProofExpr for MultiplyExpr { let rhs = self.rhs.verifier_evaluate(builder, accessor, one_eval)?; // lhs_times_rhs - let lhs_times_rhs = builder.try_consume_mle_evaluation()?; + let lhs_times_rhs = builder.try_consume_final_round_mle_evaluation()?; // subpolynomial: lhs_times_rhs - lhs * rhs builder.try_produce_sumcheck_subpolynomial_evaluation( diff --git a/crates/proof-of-sql/src/sql/proof_exprs/or_expr.rs b/crates/proof-of-sql/src/sql/proof_exprs/or_expr.rs index 5e0a77177..58d02e258 100644 --- a/crates/proof-of-sql/src/sql/proof_exprs/or_expr.rs +++ b/crates/proof-of-sql/src/sql/proof_exprs/or_expr.rs @@ -140,7 +140,7 @@ pub fn verifier_evaluate_or( rhs: &S, ) -> Result { // lhs_and_rhs - let lhs_and_rhs = builder.try_consume_mle_evaluation()?; + let lhs_and_rhs = builder.try_consume_final_round_mle_evaluation()?; // subpolynomial: lhs_and_rhs - lhs * rhs builder.try_produce_sumcheck_subpolynomial_evaluation( diff --git a/crates/proof-of-sql/src/sql/proof_gadgets/range_check.rs b/crates/proof-of-sql/src/sql/proof_gadgets/range_check.rs index 5ebc7e42e..cd7b9c0de 100644 --- a/crates/proof-of-sql/src/sql/proof_gadgets/range_check.rs +++ b/crates/proof-of-sql/src/sql/proof_gadgets/range_check.rs @@ -346,8 +346,8 @@ where let (sum, w_plus_alpha_inv_evals) = (0..31) .map(|i| { - let w_eval = builder.try_consume_mle_evaluation()?; - let words_inv = builder.try_consume_mle_evaluation()?; + let w_eval = builder.try_consume_final_round_mle_evaluation()?; + let words_inv = builder.try_consume_final_round_mle_evaluation()?; let word_eval = words_inv * (w_eval + alpha); let power = (0..i).fold(C::from(1), |acc, _| acc * C::from(256)); @@ -383,7 +383,7 @@ where .ok_or(ProofSizeMismatch::TooFewSumcheckVariables)?; // Ensures that we have enough sumcheck variables let _ = builder.try_consume_one_evaluation()?; - let word_vals_plus_alpha_inv = builder.try_consume_mle_evaluation()?; + let word_vals_plus_alpha_inv = builder.try_consume_final_round_mle_evaluation()?; let word_value_constraint = word_vals_plus_alpha_inv * (word_vals_eval + alpha); builder.try_produce_sumcheck_subpolynomial_evaluation( @@ -392,7 +392,7 @@ where 2, )?; - let count_eval = builder.try_consume_mle_evaluation()?; + let count_eval = builder.try_consume_final_round_mle_evaluation()?; let row_sum_eval: C = w_plus_alpha_inv_evals.iter().copied().sum(); let count_value_product_eval = count_eval * word_vals_plus_alpha_inv; diff --git a/crates/proof-of-sql/src/sql/proof_gadgets/range_check_test.rs b/crates/proof-of-sql/src/sql/proof_gadgets/range_check_test.rs index 1909b2ed6..e7f7217a4 100644 --- a/crates/proof-of-sql/src/sql/proof_gadgets/range_check_test.rs +++ b/crates/proof-of-sql/src/sql/proof_gadgets/range_check_test.rs @@ -22,7 +22,7 @@ impl ProverEvaluate for RangeCheckTestPlan { #[doc = " Evaluate the query, modify `FirstRoundBuilder` and return the result."] fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, _alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { diff --git a/crates/proof-of-sql/src/sql/proof_gadgets/sign_expr.rs b/crates/proof-of-sql/src/sql/proof_gadgets/sign_expr.rs index 85821bf26..cf591de76 100644 --- a/crates/proof-of-sql/src/sql/proof_gadgets/sign_expr.rs +++ b/crates/proof-of-sql/src/sql/proof_gadgets/sign_expr.rs @@ -113,7 +113,7 @@ pub fn verifier_evaluate_sign( // bits of the expression let mut bit_evals = Vec::with_capacity(num_varying_bits); for _ in 0..num_varying_bits { - let eval = builder.try_consume_mle_evaluation()?; + let eval = builder.try_consume_final_round_mle_evaluation()?; bit_evals.push(eval); } diff --git a/crates/proof-of-sql/src/sql/proof_gadgets/sign_expr_test.rs b/crates/proof-of-sql/src/sql/proof_gadgets/sign_expr_test.rs index 215f4b4f2..73d7ccc4e 100644 --- a/crates/proof-of-sql/src/sql/proof_gadgets/sign_expr_test.rs +++ b/crates/proof-of-sql/src/sql/proof_gadgets/sign_expr_test.rs @@ -46,6 +46,7 @@ fn we_can_verify_a_constant_decomposition() { &evaluation_point, &sumcheck_random_scalars, &[], + &[], ); let one_evals = sumcheck_evaluations.one_evaluations.clone(); let one_eval = one_evals.values().next().unwrap(); @@ -78,6 +79,7 @@ fn verification_of_constant_data_fails_if_the_commitment_doesnt_match_the_bit_di &evaluation_point, &sumcheck_random_scalars, &[], + &[], ); let one_evals = sumcheck_evaluations.one_evaluations.clone(); let one_eval = one_evals.values().next().unwrap(); diff --git a/crates/proof-of-sql/src/sql/proof_plans/demo_mock_plan.rs b/crates/proof-of-sql/src/sql/proof_plans/demo_mock_plan.rs index 7a3352caa..1ddf3c796 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/demo_mock_plan.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/demo_mock_plan.rs @@ -53,7 +53,7 @@ impl ProofPlan for DemoMockPlan { impl ProverEvaluate for DemoMockPlan { fn first_round_evaluate<'a, S: Scalar>( &self, - _builder: &mut FirstRoundBuilder, + _builder: &mut FirstRoundBuilder<'a, S>, _alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { diff --git a/crates/proof-of-sql/src/sql/proof_plans/empty_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/empty_exec.rs index 9f3cf0815..d4b8107ef 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/empty_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/empty_exec.rs @@ -67,7 +67,7 @@ impl ProverEvaluate for EmptyExec { #[tracing::instrument(name = "EmptyExec::first_round_evaluate", level = "debug", skip_all)] fn first_round_evaluate<'a, S: Scalar>( &self, - _builder: &mut FirstRoundBuilder, + _builder: &mut FirstRoundBuilder<'a, S>, _alloc: &'a Bump, _table_map: &IndexMap>, ) -> Table<'a, S> { diff --git a/crates/proof-of-sql/src/sql/proof_plans/filter_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/filter_exec.rs index ed8d1a14b..908a06f9b 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/filter_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/filter_exec.rs @@ -88,7 +88,7 @@ where ); // 3. filtered_columns let filtered_columns_evals = - builder.try_consume_mle_evaluations(self.aliased_results.len())?; + builder.try_consume_final_round_mle_evaluations(self.aliased_results.len())?; assert!(filtered_columns_evals.len() == self.aliased_results.len()); let alpha = builder.try_consume_post_result_challenge()?; @@ -145,7 +145,7 @@ impl ProverEvaluate for FilterExec { #[tracing::instrument(name = "FilterExec::first_round_evaluate", level = "debug", skip_all)] fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { @@ -262,8 +262,8 @@ pub(super) fn verify_filter( ) -> Result<(), ProofError> { let c_fold_eval = alpha * fold_vals(beta, c_evals); let d_fold_eval = alpha * fold_vals(beta, d_evals); - let c_star_eval = builder.try_consume_mle_evaluation()?; - let d_star_eval = builder.try_consume_mle_evaluation()?; + let c_star_eval = builder.try_consume_final_round_mle_evaluation()?; + let d_star_eval = builder.try_consume_final_round_mle_evaluation()?; // sum c_star * s - d_star = 0 builder.try_produce_sumcheck_subpolynomial_evaluation( diff --git a/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test_dishonest_prover.rs b/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test_dishonest_prover.rs index 9ec4f5701..443b28934 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test_dishonest_prover.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/filter_exec_test_dishonest_prover.rs @@ -37,7 +37,7 @@ impl ProverEvaluate for DishonestFilterExec { )] fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { diff --git a/crates/proof-of-sql/src/sql/proof_plans/group_by_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/group_by_exec.rs index 3ca31d42b..90e2bf476 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/group_by_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/group_by_exec.rs @@ -100,9 +100,10 @@ impl ProofPlan for GroupByExec { .collect::, _>>()?; // 3. filtered_columns let group_by_result_columns_evals = - builder.try_consume_mle_evaluations(self.group_by_exprs.len())?; - let sum_result_columns_evals = builder.try_consume_mle_evaluations(self.sum_expr.len())?; - let count_column_eval = builder.try_consume_mle_evaluation()?; + builder.try_consume_final_round_mle_evaluations(self.group_by_exprs.len())?; + let sum_result_columns_evals = + builder.try_consume_final_round_mle_evaluations(self.sum_expr.len())?; + let count_column_eval = builder.try_consume_final_round_mle_evaluation()?; let alpha = builder.try_consume_post_result_challenge()?; let beta = builder.try_consume_post_result_challenge()?; @@ -193,7 +194,7 @@ impl ProverEvaluate for GroupByExec { #[tracing::instrument(name = "GroupByExec::first_round_evaluate", level = "debug", skip_all)] fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { @@ -346,8 +347,8 @@ fn verify_group_by( // sum_out_fold = count_out + sum beta^(j+1) * sum_out[j] let sum_out_fold_eval = count_out_eval + beta * fold_vals(beta, &sum_out_evals); - let g_in_star_eval = builder.try_consume_mle_evaluation()?; - let g_out_star_eval = builder.try_consume_mle_evaluation()?; + let g_in_star_eval = builder.try_consume_final_round_mle_evaluation()?; + let g_out_star_eval = builder.try_consume_final_round_mle_evaluation()?; // sum g_in_star * sel_in * sum_in_fold - g_out_star * sum_out_fold = 0 builder.try_produce_sumcheck_subpolynomial_evaluation( diff --git a/crates/proof-of-sql/src/sql/proof_plans/projection_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/projection_exec.rs index 80e8e85b4..c2de0ca29 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/projection_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/projection_exec.rs @@ -60,7 +60,8 @@ impl ProofPlan for ProjectionExec { .verifier_evaluate(builder, accessor, one_eval) }) .collect::, _>>()?; - let column_evals = builder.try_consume_mle_evaluations(self.aliased_results.len())?; + let column_evals = + builder.try_consume_final_round_mle_evaluations(self.aliased_results.len())?; Ok(TableEvaluation::new(column_evals, one_eval)) } @@ -94,7 +95,7 @@ impl ProverEvaluate for ProjectionExec { )] fn first_round_evaluate<'a, S: Scalar>( &self, - _builder: &mut FirstRoundBuilder, + _builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { diff --git a/crates/proof-of-sql/src/sql/proof_plans/slice_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/slice_exec.rs index aca38aaf1..fec20554c 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/slice_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/slice_exec.rs @@ -75,7 +75,8 @@ where let max_one_eval = builder.try_consume_one_evaluation()?; let selection_eval = max_one_eval - offset_one_eval; // 3. filtered_columns - let filtered_columns_evals = builder.try_consume_mle_evaluations(columns_evals.len())?; + let filtered_columns_evals = + builder.try_consume_final_round_mle_evaluations(columns_evals.len())?; let alpha = builder.try_consume_post_result_challenge()?; let beta = builder.try_consume_post_result_challenge()?; @@ -112,7 +113,7 @@ impl ProverEvaluate for SliceExec { #[tracing::instrument(name = "SliceExec::first_round_evaluate", level = "debug", skip_all)] fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { diff --git a/crates/proof-of-sql/src/sql/proof_plans/table_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/table_exec.rs index 0e4b62fba..f23235a9d 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/table_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/table_exec.rs @@ -76,7 +76,7 @@ impl ProverEvaluate for TableExec { #[tracing::instrument(name = "TableExec::first_round_evaluate", level = "debug", skip_all)] fn first_round_evaluate<'a, S: Scalar>( &self, - _builder: &mut FirstRoundBuilder, + _builder: &mut FirstRoundBuilder<'a, S>, _alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { diff --git a/crates/proof-of-sql/src/sql/proof_plans/union_exec.rs b/crates/proof-of-sql/src/sql/proof_plans/union_exec.rs index 48a273398..b516d403d 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/union_exec.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/union_exec.rs @@ -65,7 +65,8 @@ where .iter() .map(TableEvaluation::column_evals) .collect::>(); - let output_column_evals = builder.try_consume_mle_evaluations(self.schema.len())?; + let output_column_evals = + builder.try_consume_final_round_mle_evaluations(self.schema.len())?; let input_one_evals = input_table_evals .iter() .map(TableEvaluation::one_eval) @@ -108,7 +109,7 @@ impl ProverEvaluate for UnionExec { #[tracing::instrument(name = "UnionExec::first_round_evaluate", level = "debug", skip_all)] fn first_round_evaluate<'a, S: Scalar>( &self, - builder: &mut FirstRoundBuilder, + builder: &mut FirstRoundBuilder<'a, S>, alloc: &'a Bump, table_map: &IndexMap>, ) -> Table<'a, S> { @@ -184,7 +185,7 @@ fn verify_union( .zip(input_one_evals) .map(|(&input_eval, &input_one_eval)| -> Result<_, ProofError> { let c_fold_eval = gamma * fold_vals(beta, input_eval); - let c_star_eval = builder.try_consume_mle_evaluation()?; + let c_star_eval = builder.try_consume_final_round_mle_evaluation()?; // c_star + c_fold * c_star - input_ones = 0 builder.try_produce_sumcheck_subpolynomial_evaluation( SumcheckSubpolynomialType::Identity, @@ -196,7 +197,7 @@ fn verify_union( .collect::, _>>()?; let d_bar_fold_eval = gamma * fold_vals(beta, output_eval); - let d_star_eval = builder.try_consume_mle_evaluation()?; + let d_star_eval = builder.try_consume_final_round_mle_evaluation()?; // d_star + d_bar_fold * d_star - output_ones = 0 builder.try_produce_sumcheck_subpolynomial_evaluation(