diff --git a/crates/proof-of-sql/src/base/commitment/commitment_evaluation_proof_test.rs b/crates/proof-of-sql/src/base/commitment/commitment_evaluation_proof_test.rs index d1579f975..89e4c2a15 100644 --- a/crates/proof-of-sql/src/base/commitment/commitment_evaluation_proof_test.rs +++ b/crates/proof-of-sql/src/base/commitment/commitment_evaluation_proof_test.rs @@ -20,7 +20,7 @@ pub fn test_simple_commitment_evaluation_proof( ); let commits = Vec::from_columns_with_offset( - &[Column::Scalar(&[ + [Column::Scalar(&[ CP::Scalar::one(), CP::Scalar::one() + CP::Scalar::one(), ])], @@ -50,7 +50,7 @@ pub fn test_commitment_evaluation_proof_with_length_1( let mut transcript = Transcript::new(b"evaluation_proof"); let proof = CP::new(&mut transcript, &a, &b_point, offset as u64, prover_setup); - let commits = Vec::from_columns_with_offset(&[Column::Scalar(&a)], offset, prover_setup); + let commits = Vec::from_columns_with_offset([Column::Scalar(&a)], offset, prover_setup); let mut b = vec![CP::Scalar::zero(); a.len()]; crate::base::polynomial::compute_evaluation_vector(&mut b, &b_point); diff --git a/crates/proof-of-sql/src/base/commitment/committable_column.rs b/crates/proof-of-sql/src/base/commitment/committable_column.rs index 0a5257d3d..23616a3ce 100644 --- a/crates/proof-of-sql/src/base/commitment/committable_column.rs +++ b/crates/proof-of-sql/src/base/commitment/committable_column.rs @@ -120,6 +120,12 @@ impl<'a, S: Scalar> From<&Column<'a, S>> for CommittableColumn<'a> { } } +impl<'a, S: Scalar> From> for CommittableColumn<'a> { + fn from(value: Column<'a, S>) -> Self { + (&value).into() + } +} + impl<'a, S: Scalar> From<&'a OwnedColumn> for CommittableColumn<'a> { fn from(value: &'a OwnedColumn) -> Self { match value { diff --git a/crates/proof-of-sql/src/base/commitment/vec_commitment_ext.rs b/crates/proof-of-sql/src/base/commitment/vec_commitment_ext.rs index 2080ab074..d058b3d66 100644 --- a/crates/proof-of-sql/src/base/commitment/vec_commitment_ext.rs +++ b/crates/proof-of-sql/src/base/commitment/vec_commitment_ext.rs @@ -185,7 +185,7 @@ mod tests { fn we_can_convert_from_columns() { // empty case let commitments = Vec::::from_columns_with_offset( - &Vec::>::new(), + Vec::>::new(), 0, &(), ); diff --git a/crates/proof-of-sql/src/base/database/column.rs b/crates/proof-of-sql/src/base/database/column.rs index 3cbb2d858..c2877788c 100644 --- a/crates/proof-of-sql/src/base/database/column.rs +++ b/crates/proof-of-sql/src/base/database/column.rs @@ -169,6 +169,23 @@ impl<'a, S: Scalar> Column<'a, S> { } } + /// Returns the column as a slice of scalars + pub(crate) fn as_scalar(&self, alloc: &'a Bump) -> &'a [S] { + match self { + Self::Boolean(col) => alloc.alloc_slice_fill_with(col.len(), |i| S::from(col[i])), + Self::SmallInt(col) => alloc.alloc_slice_fill_with(col.len(), |i| S::from(col[i])), + Self::Int(col) => alloc.alloc_slice_fill_with(col.len(), |i| S::from(col[i])), + Self::BigInt(col) => alloc.alloc_slice_fill_with(col.len(), |i| S::from(col[i])), + Self::Int128(col) => alloc.alloc_slice_fill_with(col.len(), |i| S::from(col[i])), + Self::Scalar(col) => col, + Self::Decimal75(_, _, col) => col, + Self::VarChar((_, scals)) => scals, + Self::TimestampTZ(_, _, col) => { + alloc.alloc_slice_fill_with(col.len(), |i| S::from(col[i])) + } + } + } + /// Returns element at index as scalar /// /// Note that if index is out of bounds, this function will return None diff --git a/crates/proof-of-sql/src/base/polynomial/multilinear_extension.rs b/crates/proof-of-sql/src/base/polynomial/multilinear_extension.rs index 6d1085cf5..e7bbdf1af 100644 --- a/crates/proof-of-sql/src/base/polynomial/multilinear_extension.rs +++ b/crates/proof-of-sql/src/base/polynomial/multilinear_extension.rs @@ -96,7 +96,7 @@ where slice_like_mle_impl!(); } -impl MultilinearExtension for Column<'_, S> { +impl MultilinearExtension for &Column<'_, S> { fn inner_product(&self, evaluation_vec: &[S]) -> S { match self { Column::Boolean(c) => c.inner_product(evaluation_vec), @@ -153,3 +153,21 @@ impl MultilinearExtension for Column<'_, S> { } } } + +impl MultilinearExtension for Column<'_, S> { + fn inner_product(&self, evaluation_vec: &[S]) -> S { + (&self).inner_product(evaluation_vec) + } + + fn mul_add(&self, res: &mut [S], multiplier: &S) { + (&self).mul_add(res, multiplier) + } + + fn to_sumcheck_term(&self, num_vars: usize) -> Rc> { + (&self).to_sumcheck_term(num_vars) + } + + fn id(&self) -> *const c_void { + (&self).id() + } +} diff --git a/crates/proof-of-sql/src/proof_primitive/dory/dory_commitment.rs b/crates/proof-of-sql/src/proof_primitive/dory/dory_commitment.rs index 4a705dc20..6921dedb9 100644 --- a/crates/proof-of-sql/src/proof_primitive/dory/dory_commitment.rs +++ b/crates/proof-of-sql/src/proof_primitive/dory/dory_commitment.rs @@ -119,7 +119,7 @@ mod tests { // empty case let commitments = Vec::::from_columns_with_offset( - &Vec::>::new(), + Vec::>::new(), 0, &setup, ); diff --git a/crates/proof-of-sql/src/sql/proof/indexes.rs b/crates/proof-of-sql/src/sql/proof/indexes.rs index 252c3fca0..728e48707 100644 --- a/crates/proof-of-sql/src/sql/proof/indexes.rs +++ b/crates/proof-of-sql/src/sql/proof/indexes.rs @@ -4,7 +4,7 @@ use core::{ops::Range, slice}; use num_traits::Zero; use serde::{Deserialize, Serialize}; -#[derive(Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] /// Indexes of a table for use in the ProvableQueryResult pub enum Indexes { /// Sparse indexes. (i.e. explicitly specified indexes) @@ -93,6 +93,9 @@ impl Indexes { Indexes::Dense(range) => { if range.is_empty() { Some(Zero::zero()) + } else if range.end as usize > 2usize.pow(evaluation_point.len() as u32) { + // This only happens when the indexes are tampered with. + None } else { Some( compute_truncated_lagrange_basis_sum(range.end as usize, evaluation_point) diff --git a/crates/proof-of-sql/src/sql/proof/provable_query_result.rs b/crates/proof-of-sql/src/sql/proof/provable_query_result.rs index 79c779ab7..2a132da19 100644 --- a/crates/proof-of-sql/src/sql/proof/provable_query_result.rs +++ b/crates/proof-of-sql/src/sql/proof/provable_query_result.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; /// An intermediate form of a query result that can be transformed /// to either the finalized query result form or a query error -#[derive(Default, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct ProvableQueryResult { num_columns: u64, indexes: Indexes, @@ -85,7 +85,9 @@ impl ProvableQueryResult { table_length: usize, column_result_fields: &[ColumnField], ) -> Result, QueryError> { - assert_eq!(self.num_columns as usize, column_result_fields.len()); + if self.num_columns as usize != column_result_fields.len() { + return Err(QueryError::InvalidColumnCount); + } if !self.indexes.valid(table_length) { return Err(QueryError::InvalidIndexes); @@ -140,7 +142,9 @@ impl ProvableQueryResult { &self, column_result_fields: &[ColumnField], ) -> Result, QueryError> { - assert_eq!(column_result_fields.len(), self.num_columns()); + if column_result_fields.len() != self.num_columns() { + return Err(QueryError::InvalidColumnCount); + } let n = self.indexes.len(); let mut offset: usize = 0; 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 38ad00fe1..dae0cd566 100644 --- a/crates/proof-of-sql/src/sql/proof/query_proof.rs +++ b/crates/proof-of-sql/src/sql/proof/query_proof.rs @@ -167,7 +167,7 @@ impl QueryProof { }?; // verify sizes - if !self.validate_sizes(&counts, result) { + if !self.validate_sizes(&counts) { Err(ProofError::VerificationError { error: "invalid proof size", })?; @@ -224,20 +224,12 @@ impl QueryProof { let column_result_fields = expr.get_column_result_fields(); - // compute the evaluation of the result MLEs - let result_evaluations = result.evaluate( - &subclaim.evaluation_point, - table_length, - &column_result_fields[..], - )?; - // pass over the provable AST to fill in the verification builder let sumcheck_evaluations = SumcheckMleEvaluations::new( table_length, &subclaim.evaluation_point, &sumcheck_random_scalars, &self.pcs_proof_evaluations, - &result_evaluations, result.indexes(), ); let mut builder = VerificationBuilder::new( @@ -250,7 +242,20 @@ impl QueryProof { post_result_challenges, ); let owned_table_result = result.to_owned_table(&column_result_fields[..])?; - expr.verifier_evaluate(&mut builder, accessor, Some(&owned_table_result))?; + let verifier_evaluations = + expr.verifier_evaluate(&mut builder, accessor, Some(&owned_table_result))?; + // compute the evaluation of the result MLEs + let result_evaluations = result.evaluate( + &subclaim.evaluation_point, + table_length, + &column_result_fields[..], + )?; + // check the evaluation of the result MLEs + if verifier_evaluations != result_evaluations { + Err(ProofError::VerificationError { + error: "result evaluation check failed", + })?; + } // perform the evaluation check of the sumcheck polynomial if builder.sumcheck_evaluation() != subclaim.expected_evaluation { @@ -283,9 +288,8 @@ impl QueryProof { }) } - fn validate_sizes(&self, counts: &ProofCounts, result: &ProvableQueryResult) -> bool { - result.num_columns() == counts.result_columns - && self.commitments.len() == counts.intermediate_mles + fn validate_sizes(&self, counts: &ProofCounts) -> bool { + self.commitments.len() == counts.intermediate_mles && self.pcs_proof_evaluations.len() == counts.intermediate_mles + counts.anchored_mles } } 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 e584c15bf..293f4b1ec 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 @@ -60,6 +60,7 @@ impl ProverEvaluate for TrivialTestProofPlan { _accessor: &'a dyn DataAccessor, ) -> Vec> { let col = alloc.alloc_slice_fill_copy(builder.table_length(), self.column_fill_value); + builder.produce_intermediate_mle(col as &[_]); builder.produce_sumcheck_subpolynomial( SumcheckSubpolynomialType::Identity, vec![(S::ONE, vec![Box::new(col as &[_])])], @@ -74,7 +75,7 @@ impl ProofPlan for TrivialTestProofPlan { _accessor: &dyn MetadataAccessor, ) -> Result<(), ProofError> { builder.count_degree(2); - builder.count_result_columns(1); + builder.count_intermediate_mles(1); builder.count_subpolynomials(1); builder.count_anchored_mles(self.anchored_mle_count); Ok(()) @@ -91,7 +92,7 @@ impl ProofPlan for TrivialTestProofPlan { _accessor: &dyn CommitmentAccessor, _result: Option<&OwnedTable>, ) -> Result, ProofError> { - assert_eq!(builder.consume_result_mle(), C::Scalar::ZERO); + assert_eq!(builder.consume_intermediate_mle(), C::Scalar::ZERO); builder.produce_sumcheck_subpolynomial_evaluation( SumcheckSubpolynomialType::ZeroSum, C::Scalar::from(self.evaluation), @@ -162,24 +163,6 @@ fn verify_fails_if_the_sumcheck_evaluation_isnt_correct() { assert!(proof.verify(&expr, &accessor, &result, &()).is_err()); } -#[test] -fn veriy_fails_if_result_mle_evaluation_fails() { - // prove and try to verify an artificial polynomial where we prove - // that every entry in the result is zero - let expr = TrivialTestProofPlan { - ..Default::default() - }; - let accessor = UnimplementedTestAccessor::new_empty(); - let (proof, mut result) = QueryProof::::new(&expr, &accessor, &()); - match result.indexes_mut() { - Indexes::Sparse(ref mut indexes) => { - indexes.pop(); - } - _ => panic!("unexpected indexes type"), - } - assert!(proof.verify(&expr, &accessor, &result, &()).is_err()); -} - #[test] fn verify_fails_if_counts_dont_match() { // prove and verify an artificial polynomial where we try to prove @@ -234,6 +217,7 @@ impl ProverEvaluate for SquareTestProofPlan { )); let res: &[_] = alloc.alloc_slice_copy(&self.res); builder.produce_anchored_mle(x); + builder.produce_intermediate_mle(res); builder.produce_sumcheck_subpolynomial( SumcheckSubpolynomialType::Identity, vec![ @@ -251,7 +235,7 @@ impl ProofPlan for SquareTestProofPlan { _accessor: &dyn MetadataAccessor, ) -> Result<(), ProofError> { builder.count_degree(3); - builder.count_result_columns(1); + builder.count_intermediate_mles(1); builder.count_subpolynomials(1); builder.count_anchored_mles(1); Ok(()) @@ -268,7 +252,6 @@ impl ProofPlan for SquareTestProofPlan { accessor: &dyn CommitmentAccessor, _result: Option<&OwnedTable>, ) -> Result, ProofError> { - let res_eval = builder.consume_result_mle(); let x_commit = C::Scalar::from(self.anchored_commit_multiplier) * accessor.get_commitment(ColumnRef::new( "sxt.test".parse().unwrap(), @@ -276,6 +259,7 @@ impl ProofPlan for SquareTestProofPlan { ColumnType::BigInt, )); let x_eval = builder.consume_anchored_mle(x_commit); + let res_eval = builder.consume_intermediate_mle(); builder.produce_sumcheck_subpolynomial_evaluation( SumcheckSubpolynomialType::Identity, res_eval - x_eval * x_eval, @@ -434,6 +418,7 @@ impl ProverEvaluate for DoubleSquareTestProofPlan { (-S::ONE, vec![Box::new(z), Box::new(z)]), ], ); + builder.produce_intermediate_mle(res); vec![Column::BigInt(res)] } } @@ -444,10 +429,9 @@ impl ProofPlan for DoubleSquareTestProofPlan { _accessor: &dyn MetadataAccessor, ) -> Result<(), ProofError> { builder.count_degree(3); - builder.count_result_columns(1); + builder.count_intermediate_mles(2); builder.count_subpolynomials(2); builder.count_anchored_mles(1); - builder.count_intermediate_mles(1); Ok(()) } fn get_length(&self, _accessor: &dyn MetadataAccessor) -> usize { @@ -467,9 +451,9 @@ impl ProofPlan for DoubleSquareTestProofPlan { "x".parse().unwrap(), ColumnType::BigInt, )); - let res_eval = builder.consume_result_mle(); let x_eval = builder.consume_anchored_mle(x_commit); let z_eval = builder.consume_intermediate_mle(); + let res_eval = builder.consume_intermediate_mle(); // poly1 builder.produce_sumcheck_subpolynomial_evaluation( @@ -627,6 +611,7 @@ impl ProverEvaluate for ChallengeTestProofPlan { let alpha = builder.consume_post_result_challenge(); let _beta = builder.consume_post_result_challenge(); builder.produce_anchored_mle(x); + builder.produce_intermediate_mle(res); builder.produce_sumcheck_subpolynomial( SumcheckSubpolynomialType::Identity, vec![ @@ -644,7 +629,7 @@ impl ProofPlan for ChallengeTestProofPlan { _accessor: &dyn MetadataAccessor, ) -> Result<(), ProofError> { builder.count_degree(3); - builder.count_result_columns(1); + builder.count_intermediate_mles(1); builder.count_subpolynomials(1); builder.count_anchored_mles(1); builder.count_post_result_challenges(2); @@ -664,13 +649,13 @@ impl ProofPlan for ChallengeTestProofPlan { ) -> Result, ProofError> { let alpha = builder.consume_post_result_challenge(); let _beta = builder.consume_post_result_challenge(); - let res_eval = builder.consume_result_mle(); let x_commit = accessor.get_commitment(ColumnRef::new( "sxt.test".parse().unwrap(), "x".parse().unwrap(), ColumnType::BigInt, )); let x_eval = builder.consume_anchored_mle(x_commit); + let res_eval = builder.consume_intermediate_mle(); builder.produce_sumcheck_subpolynomial_evaluation( SumcheckSubpolynomialType::Identity, alpha * res_eval - alpha * x_eval * x_eval, diff --git a/crates/proof-of-sql/src/sql/proof/query_result.rs b/crates/proof-of-sql/src/sql/proof/query_result.rs index a0087839c..e65f383ee 100644 --- a/crates/proof-of-sql/src/sql/proof/query_result.rs +++ b/crates/proof-of-sql/src/sql/proof/query_result.rs @@ -39,6 +39,9 @@ pub enum QueryError { /// The underlying source error source: OwnedTableError, }, + /// The number of columns in the table was invalid. + #[snafu(display("Invalid number of columns"))] + InvalidColumnCount, } /// The verified results of a query along with metadata produced by verification 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 d7e133a98..d8305f118 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 @@ -29,8 +29,6 @@ pub struct SumcheckMleEvaluations<'a, S: Scalar> { 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 final result table columns. - pub result_evaluations: &'a [S], } impl<'a, S: Scalar> SumcheckMleEvaluations<'a, S> { @@ -40,14 +38,12 @@ impl<'a, S: Scalar> SumcheckMleEvaluations<'a, S> { /// - `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 - /// - `result_evaluations` - the evaluations of the final result table columns /// - `result_indexes` - the indexes of the entries in the result columns. This can be sparse or dense pub fn new( table_length: usize, evaluation_point: &[S], sumcheck_random_scalars: &SumcheckRandomScalars, pcs_proof_evaluations: &'a [S], - result_evaluations: &'a [S], result_indexes: &Indexes, ) -> Self { assert_eq!( @@ -70,7 +66,6 @@ impl<'a, S: Scalar> SumcheckMleEvaluations<'a, S> { one_evaluation, random_evaluation, pcs_proof_evaluations, - result_evaluations, result_indexes_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 aec1b7d1d..9a603722d 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 @@ -13,13 +13,11 @@ fn we_can_track_the_evaluation_of_mles_used_within_sumcheck() { let sumcheck_random_scalars = SumcheckRandomScalars::new(&random_scalars, 3, 2); let pcs_proof_evaluations = [Curve25519Scalar::from(42u64)]; - let result_evaluations = [Curve25519Scalar::from(51u64)]; let evals = SumcheckMleEvaluations::new( 3, &evaluation_point, &sumcheck_random_scalars, &pcs_proof_evaluations, - &result_evaluations, &Indexes::Sparse(vec![]), ); let expected_eval = (Curve25519Scalar::one() - evaluation_point[0]) @@ -55,13 +53,11 @@ fn we_can_track_the_evaluation_of_dense_indexes() { let sumcheck_random_scalars = SumcheckRandomScalars::new(&random_scalars, 3, 2); let pcs_proof_evaluations = [Curve25519Scalar::from(42u64)]; - let result_evaluations = [Curve25519Scalar::from(51u64)]; let evals = SumcheckMleEvaluations::new( 3, &evaluation_point, &sumcheck_random_scalars, &pcs_proof_evaluations, - &result_evaluations, &Indexes::Dense(0..3), ); // Because the range is the entire table, these should be the same. 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 ca2357d68..c02496504 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 @@ -37,12 +37,15 @@ impl ProverEvaluate for EmptyTestQueryExpr { } fn prover_evaluate<'a>( &self, - _builder: &mut ProofBuilder<'a, S>, + builder: &mut ProofBuilder<'a, S>, alloc: &'a Bump, _accessor: &'a dyn DataAccessor, ) -> Vec> { let zeros = vec![0; self.length]; let res: &[_] = alloc.alloc_slice_copy(&zeros); + let _ = std::iter::repeat_with(|| builder.produce_intermediate_mle(res)) + .take(self.columns) + .collect::>(); vec![Column::BigInt(res); self.columns] } } @@ -52,7 +55,7 @@ impl ProofPlan for EmptyTestQueryExpr { builder: &mut CountBuilder, _accessor: &dyn MetadataAccessor, ) -> Result<(), ProofError> { - builder.count_result_columns(1); + builder.count_intermediate_mles(self.columns); Ok(()) } fn get_length(&self, _accessor: &dyn MetadataAccessor) -> usize { @@ -63,10 +66,15 @@ impl ProofPlan for EmptyTestQueryExpr { } fn verifier_evaluate( &self, - _builder: &mut VerificationBuilder, + builder: &mut VerificationBuilder, _accessor: &dyn CommitmentAccessor, _result: Option<&OwnedTable<::Scalar>>, ) -> Result, ProofError> { + let _ = std::iter::repeat_with(|| { + assert_eq!(builder.consume_intermediate_mle(), C::Scalar::ZERO) + }) + .take(self.columns) + .collect::>(); Ok(vec![C::Scalar::ZERO]) } 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 ea3b0e6e6..d32d484de 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 @@ -25,7 +25,10 @@ pub fn exercise_verification( accessor: &impl TestAccessor, table_ref: TableRef, ) { - assert!(res.verify(expr, accessor, &()).is_ok()); + let verification_result = res.verify(expr, accessor, &()); + if verification_result.is_err() { + panic!("Verification failed: {:?}", verification_result.err()); + } // try changing the result tamper_result(res, expr, accessor); 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 7000251dc..12bd27d17 100644 --- a/crates/proof-of-sql/src/sql/proof/verification_builder.rs +++ b/crates/proof-of-sql/src/sql/proof/verification_builder.rs @@ -14,7 +14,6 @@ pub struct VerificationBuilder<'a, C: Commitment> { bit_distributions: &'a [BitDistribution], pcs_proof_commitments: Vec, folded_pcs_proof_evaluation: C::Scalar, - consumed_result_mles: usize, consumed_pcs_proof_mles: usize, consumed_intermediate_mles: usize, produced_subpolynomials: usize, @@ -52,7 +51,6 @@ impl<'a, C: Commitment> VerificationBuilder<'a, C> { sumcheck_evaluation: C::Scalar::zero(), pcs_proof_commitments: Vec::with_capacity(inner_product_multipliers.len()), folded_pcs_proof_evaluation: C::Scalar::zero(), - consumed_result_mles: 0, consumed_pcs_proof_mles: 0, consumed_intermediate_mles: 0, produced_subpolynomials: 0, @@ -98,13 +96,6 @@ impl<'a, C: Commitment> VerificationBuilder<'a, C> { self.consume_anchored_mle(commitment) } - /// Consume the evaluation of the MLE for a result column used in sumcheck - pub fn consume_result_mle(&mut self) -> C::Scalar { - let index = self.consumed_result_mles; - self.consumed_result_mles += 1; - self.mle_evaluations.result_evaluations[index] - } - /// Produce the evaluation of a subpolynomial used in sumcheck pub fn produce_sumcheck_subpolynomial_evaluation( &mut self, @@ -152,7 +143,6 @@ impl<'a, C: Commitment> VerificationBuilder<'a, C> { && self.produced_subpolynomials == self.subpolynomial_multipliers.len() && self.consumed_intermediate_mles == self.intermediate_commitments.len() && self.consumed_pcs_proof_mles == self.mle_evaluations.pcs_proof_evaluations.len() - && self.consumed_result_mles == self.mle_evaluations.result_evaluations.len() && self.post_result_challenges.is_empty() } diff --git a/crates/proof-of-sql/src/sql/proof/verification_builder_test.rs b/crates/proof-of-sql/src/sql/proof/verification_builder_test.rs index 8ecfbab7d..acc1782d5 100644 --- a/crates/proof-of-sql/src/sql/proof/verification_builder_test.rs +++ b/crates/proof-of-sql/src/sql/proof/verification_builder_test.rs @@ -105,31 +105,6 @@ fn we_build_up_the_folded_pcs_proof_commitment() { ); } -#[test] -fn we_can_consume_result_evaluations() { - let result_evaluations = [ - Curve25519Scalar::from(123u64), - Curve25519Scalar::from(456u64), - ]; - let mle_evaluations = SumcheckMleEvaluations { - table_length: 1, - num_sumcheck_variables: 1, - result_evaluations: &result_evaluations, - ..Default::default() - }; - let mut builder = VerificationBuilder::::new( - 0, - mle_evaluations, - &[][..], - &[][..], - &[][..], - &[][..], - Vec::new(), - ); - assert_eq!(builder.consume_result_mle(), Curve25519Scalar::from(123u64)); - assert_eq!(builder.consume_result_mle(), Curve25519Scalar::from(456u64)); -} - #[test] fn we_can_consume_post_result_challenges_in_proof_builder() { let mut builder = VerificationBuilder::::new( diff --git a/crates/proof-of-sql/src/sql/proof_exprs/sign_expr_test.rs b/crates/proof-of-sql/src/sql/proof_exprs/sign_expr_test.rs index 7fc1a4112..ca6a89cfd 100644 --- a/crates/proof-of-sql/src/sql/proof_exprs/sign_expr_test.rs +++ b/crates/proof-of-sql/src/sql/proof_exprs/sign_expr_test.rs @@ -62,7 +62,6 @@ fn we_can_verify_a_constant_decomposition() { &evaluation_point, &sumcheck_random_scalars, &[], - &[], &Default::default(), ); let one_eval = sumcheck_evaluations.one_evaluation; @@ -87,7 +86,6 @@ fn verification_of_constant_data_fails_if_the_commitment_doesnt_match_the_bit_di &evaluation_point, &sumcheck_random_scalars, &[], - &[], &Default::default(), ); let one_eval = sumcheck_evaluations.one_evaluation; 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 dcdd5c394..f865f9f69 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 @@ -68,7 +68,7 @@ where self.where_clause.count(builder)?; for aliased_expr in &self.aliased_results { aliased_expr.expr.count(builder)?; - builder.count_result_columns(1); + builder.count_intermediate_mles(1); } builder.count_intermediate_mles(2); builder.count_subpolynomials(3); @@ -109,8 +109,9 @@ where )?; // 4. filtered_columns let filtered_columns_evals = Vec::from_iter( - repeat_with(|| builder.consume_result_mle()).take(self.aliased_results.len()), + repeat_with(|| builder.consume_intermediate_mle()).take(self.aliased_results.len()), ); + assert!(filtered_columns_evals.len() == self.aliased_results.len()); let alpha = builder.consume_post_result_challenge(); let beta = builder.consume_post_result_challenge(); @@ -119,10 +120,11 @@ where builder, alpha, beta, - columns_evals, + &columns_evals, selection_eval, - filtered_columns_evals, - ) + &filtered_columns_evals, + )?; + Ok(filtered_columns_evals) } fn get_column_result_fields(&self) -> Vec { @@ -201,6 +203,10 @@ impl ProverEvaluate for FilterExec { ); // Compute filtered_columns and indexes let (filtered_columns, result_len) = filter_columns(alloc, &columns, selection); + // 3. Produce MLEs + filtered_columns.iter().cloned().for_each(|column| { + builder.produce_intermediate_mle(column); + }); let alpha = builder.consume_post_result_challenge(); let beta = builder.consume_post_result_challenge(); @@ -223,10 +229,10 @@ fn verify_filter( builder: &mut VerificationBuilder, alpha: C::Scalar, beta: C::Scalar, - c_evals: Vec, + c_evals: &[C::Scalar], s_eval: C::Scalar, - d_evals: Vec, -) -> Result, ProofError> { + d_evals: &[C::Scalar], +) -> Result<(), ProofError> { let one_eval = builder.mle_evaluations.one_evaluation; let chi_eval = match builder.mle_evaluations.result_indexes_evaluation { @@ -238,8 +244,8 @@ fn verify_filter( } }; - let c_fold_eval = alpha * one_eval + fold_vals(beta, &c_evals); - let d_bar_fold_eval = alpha * one_eval + fold_vals(beta, &d_evals); + let c_fold_eval = alpha * one_eval + fold_vals(beta, c_evals); + let d_bar_fold_eval = alpha * one_eval + fold_vals(beta, d_evals); let c_star_eval = builder.consume_intermediate_mle(); let d_star_eval = builder.consume_intermediate_mle(); @@ -261,7 +267,7 @@ fn verify_filter( d_bar_fold_eval * d_star_eval - chi_eval, ); - Ok(c_evals) + Ok(()) } #[allow(clippy::too_many_arguments)] 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 1141296eb..2c496545e 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 @@ -90,6 +90,10 @@ impl ProverEvaluate for DishonestFilterExec { // Compute filtered_columns and indexes let (filtered_columns, result_len) = filter_columns(alloc, &columns, selection); let filtered_columns = tamper_column(alloc, filtered_columns); + // 3. Produce MLEs + filtered_columns.iter().cloned().for_each(|column| { + builder.produce_intermediate_mle(column); + }); let alpha = builder.consume_post_result_challenge(); let beta = builder.consume_post_result_challenge(); 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 5a4d37dc4..0ca9814c5 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 @@ -77,13 +77,14 @@ impl ProofPlan for GroupByExec { self.where_clause.count(builder)?; for expr in &self.group_by_exprs { expr.count(builder)?; - builder.count_result_columns(1); + builder.count_intermediate_mles(1); } for aliased_expr in &self.sum_expr { aliased_expr.expr.count(builder)?; - builder.count_result_columns(1); + builder.count_intermediate_mles(1); } - builder.count_result_columns(1); + // For the count col + builder.count_intermediate_mles(1); builder.count_intermediate_mles(2); builder.count_subpolynomials(3); builder.count_degree(3); @@ -128,11 +129,12 @@ impl ProofPlan for GroupByExec { // 4. filtered_columns let group_by_result_columns_evals = Vec::from_iter( - repeat_with(|| builder.consume_result_mle()).take(self.group_by_exprs.len()), + repeat_with(|| builder.consume_intermediate_mle()).take(self.group_by_exprs.len()), ); - let sum_result_columns_evals = - Vec::from_iter(repeat_with(|| builder.consume_result_mle()).take(self.sum_expr.len())); - let count_column_eval = builder.consume_result_mle(); + let sum_result_columns_evals = Vec::from_iter( + repeat_with(|| builder.consume_intermediate_mle()).take(self.sum_expr.len()), + ); + let count_column_eval = builder.consume_intermediate_mle(); let alpha = builder.consume_post_result_challenge(); let beta = builder.consume_post_result_challenge(); @@ -281,7 +283,7 @@ impl ProverEvaluate for GroupByExec { .iter() .map(|aliased_expr| aliased_expr.expr.prover_evaluate(builder, alloc, accessor)), ); - // Compute filtered_columns and indexes + // 3. Compute filtered_columns and indexes let AggregatedColumns { group_by_columns: group_by_result_columns, sum_columns: sum_result_columns, @@ -293,6 +295,20 @@ impl ProverEvaluate for GroupByExec { let alpha = builder.consume_post_result_challenge(); let beta = builder.consume_post_result_challenge(); + // 4. Tally results + let sum_result_columns_iter = sum_result_columns.iter().map(|col| Column::Scalar(col)); + let res = Vec::from_iter( + group_by_result_columns + .clone() + .into_iter() + .chain(sum_result_columns_iter) + .chain(core::iter::once(Column::BigInt(count_column))), + ); + // 5. Produce MLEs + res.iter().cloned().for_each(|column| { + builder.produce_intermediate_mle(column); + }); + // 6. Prove group by prove_group_by( builder, alloc, @@ -301,13 +317,7 @@ impl ProverEvaluate for GroupByExec { (&group_by_columns, &sum_columns, selection), (&group_by_result_columns, &sum_result_columns, count_column), ); - let sum_result_columns_iter = sum_result_columns.iter().map(|col| Column::Scalar(col)); - Vec::from_iter( - group_by_result_columns - .into_iter() - .chain(sum_result_columns_iter) - .chain(iter::once(Column::BigInt(count_column))), - ) + res } } 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 bfe21addc..47a52d9e6 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 @@ -49,7 +49,7 @@ impl ProofPlan for ProjectionExec { ) -> Result<(), ProofError> { for aliased_expr in &self.aliased_results { aliased_expr.expr.count(builder)?; - builder.count_result_columns(1); + builder.count_intermediate_mles(1); } Ok(()) } @@ -74,7 +74,7 @@ impl ProofPlan for ProjectionExec { .map(|aliased_expr| aliased_expr.expr.verifier_evaluate(builder, accessor)) .collect::, _>>()?; Ok(Vec::from_iter( - repeat_with(|| builder.consume_result_mle()).take(self.aliased_results.len()), + repeat_with(|| builder.consume_intermediate_mle()).take(self.aliased_results.len()), )) } @@ -119,10 +119,16 @@ impl ProverEvaluate for ProjectionExec { alloc: &'a Bump, accessor: &'a dyn DataAccessor, ) -> Vec> { - Vec::from_iter( + // 1. Evaluate result expressions + let res = Vec::from_iter( self.aliased_results .iter() .map(|aliased_expr| aliased_expr.expr.prover_evaluate(builder, alloc, accessor)), - ) + ); + // 2. Produce MLEs + res.clone().into_iter().for_each(|column| { + builder.produce_intermediate_mle(column.as_scalar(alloc)); + }); + res } }