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 ef9a52e3c..dd1693a54 100644 --- a/crates/proof-of-sql/src/base/polynomial/multilinear_extension.rs +++ b/crates/proof-of-sql/src/base/polynomial/multilinear_extension.rs @@ -1,12 +1,12 @@ use crate::base::{database::Column, if_rayon, scalar::Scalar, slice_ops}; use alloc::vec::Vec; -use core::ffi::c_void; +use core::{ffi::c_void, fmt::Debug}; use num_traits::Zero; #[cfg(feature = "rayon")] use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; /// Interface for operating on multilinear extension's in-place -pub trait MultilinearExtension { +pub trait MultilinearExtension: Debug { /// Given an evaluation vector, compute the evaluation of the multilinear /// extension fn inner_product(&self, evaluation_vec: &[S]) -> S; @@ -20,6 +20,9 @@ pub trait MultilinearExtension { /// pointer to identify the slice forming the MLE fn id(&self) -> *const c_void; + #[cfg(test)] + fn to_scalar_vec(&self) -> Vec; + #[cfg(test)] /// Given an evaluation point, compute the evaluation of the multilinear /// extension. This is inefficient and should only be used for testing. @@ -30,7 +33,7 @@ pub trait MultilinearExtension { } } -impl<'a, T: Sync, S: Scalar> MultilinearExtension for &'a [T] +impl<'a, T: Sync + Debug, S: Scalar> MultilinearExtension for &'a [T] where &'a T: Into, { @@ -58,6 +61,11 @@ where fn id(&self) -> *const c_void { self.as_ptr().cast::() } + + #[cfg(test)] + fn to_scalar_vec(&self) -> Vec { + slice_ops::slice_cast(self) + } } /// TODO: add docs @@ -78,17 +86,22 @@ macro_rules! slice_like_mle_impl { fn id(&self) -> *const c_void { (&self[..]).id() } + + #[cfg(test)] + fn to_scalar_vec(&self) -> Vec { + (&self[..]).to_scalar_vec() + } }; } -impl<'a, T: Sync, S: Scalar> MultilinearExtension for &'a Vec +impl<'a, T: Sync + Debug, S: Scalar> MultilinearExtension for &'a Vec where &'a T: Into, { slice_like_mle_impl!(); } -impl<'a, T: Sync, const N: usize, S: Scalar> MultilinearExtension for &'a [T; N] +impl<'a, T: Sync + Debug, const N: usize, S: Scalar> MultilinearExtension for &'a [T; N] where &'a T: Into, { @@ -151,6 +164,11 @@ impl MultilinearExtension for &Column<'_, S> { Column::Int128(c) => MultilinearExtension::::id(c), } } + + #[cfg(test)] + fn to_scalar_vec(&self) -> Vec { + self.to_scalar_with_scaling(0) + } } impl MultilinearExtension for Column<'_, S> { @@ -169,4 +187,9 @@ impl MultilinearExtension for Column<'_, S> { fn id(&self) -> *const c_void { (&self).id() } + + #[cfg(test)] + fn to_scalar_vec(&self) -> Vec { + (&self).to_scalar_vec() + } } diff --git a/crates/proof-of-sql/src/proof_primitive/sumcheck/proof.rs b/crates/proof-of-sql/src/proof_primitive/sumcheck/proof.rs index 7a28f17b1..f4c091946 100644 --- a/crates/proof-of-sql/src/proof_primitive/sumcheck/proof.rs +++ b/crates/proof-of-sql/src/proof_primitive/sumcheck/proof.rs @@ -61,6 +61,7 @@ impl SumcheckProof { polynomial_info: CompositePolynomialInfo, claimed_sum: &S, ) -> Result, ProofError> { + dbg!(&polynomial_info); transcript.extend_as_be([ polynomial_info.max_multiplicands as u64, polynomial_info.num_variables as u64, @@ -95,6 +96,11 @@ impl SumcheckProof { actual_sum += self.coefficients[coefficient_index]; } if actual_sum != expected_evaluation { + dbg!(round_index); + dbg!(actual_sum, expected_evaluation); + dbg!(&self.coefficients); + dbg!("Verifier error"); + dbg!(&evaluation_point); return Err(ProofError::VerificationError { error: "round evaluation does not match claimed sum", }); diff --git a/crates/proof-of-sql/src/proof_primitive/sumcheck/prover_state.rs b/crates/proof-of-sql/src/proof_primitive/sumcheck/prover_state.rs index 27f24a82a..748a88ee0 100644 --- a/crates/proof-of-sql/src/proof_primitive/sumcheck/prover_state.rs +++ b/crates/proof-of-sql/src/proof_primitive/sumcheck/prover_state.rs @@ -46,6 +46,9 @@ impl ProverState { flattened_ml_extensions: Vec>, num_vars: usize, ) -> Self { + dbg!(&list_of_products); + dbg!(&flattened_ml_extensions); + dbg!(num_vars); let max_multiplicands = list_of_products .iter() .map(|(_, product)| product.len()) 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 111592436..e12925f25 100644 --- a/crates/proof-of-sql/src/sql/proof/query_proof.rs +++ b/crates/proof-of-sql/src/sql/proof/query_proof.rs @@ -161,7 +161,8 @@ impl QueryProof { let mut evaluation_point = vec![Zero::zero(); num_sumcheck_variables]; let sumcheck_proof = SumcheckProof::create(&mut transcript, &mut evaluation_point, sumcheck_state); - + dbg!("Prover"); + dbg!(&evaluation_point); // 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); @@ -306,6 +307,8 @@ impl QueryProof { .chain(self.one_evaluation_lengths.iter()) .copied(); + dbg!("Verifier"); + dbg!(&subclaim.evaluation_point); // pass over the provable AST to fill in the verification builder let sumcheck_evaluations = SumcheckMleEvaluations::new( self.range_length, diff --git a/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs b/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs index 1d50286e8..fad4fcd03 100644 --- a/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs +++ b/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs @@ -1,8 +1,9 @@ use crate::base::{polynomial::MultilinearExtension, scalar::Scalar}; use alloc::{boxed::Box, vec::Vec}; +use core::fmt::Debug; /// The type of a sumcheck subpolynomial -#[derive(Copy, Clone, Hash, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum SumcheckSubpolynomialType { /// The subpolynomial should be zero at every entry/row Identity, @@ -22,6 +23,7 @@ pub type SumcheckSubpolynomialTerm<'a, S> = (S, Vec { terms: Vec>, subpolynomial_type: SumcheckSubpolynomialType, @@ -33,6 +35,62 @@ impl<'a, S: Scalar> SumcheckSubpolynomial<'a, S> { subpolynomial_type: SumcheckSubpolynomialType, terms: Vec>, ) -> Self { + dbg!(&subpolynomial_type); + dbg!(terms.len()); + #[cfg(test)] + let concrete_terms = terms + .iter() + .map(|(mul, mles)| { + ( + mul, + mles.iter() + .map(|mle| mle.to_scalar_vec()) + .collect::>(), + ) + }) + .collect::>(); + #[cfg(test)] + let len = concrete_terms + .iter() + .flat_map(|(_, mles)| mles.iter().map(|mle| mle.len())) + .max() + .unwrap_or(0); + #[cfg(test)] + match subpolynomial_type { + SumcheckSubpolynomialType::Identity => { + (0..len).for_each(|i| { + let sum = concrete_terms + .iter() + .map(|(mul, mles)| { + **mul + * mles + .iter() + .map(|mle| *mle.get(i).unwrap_or(&S::zero())) + .product::() + }) + .sum::(); + assert_eq!(sum, S::zero()); + }); + } + SumcheckSubpolynomialType::ZeroSum => { + dbg!(&terms); + let sum = (0..len) + .map(|i| { + concrete_terms + .iter() + .map(|(mul, mles)| { + **mul + * mles + .iter() + .map(|mle| *mle.get(i).unwrap_or(&S::zero())) + .product::() + }) + .sum::() + }) + .sum::(); + assert_eq!(sum, S::zero()); + } + } Self { terms, subpolynomial_type, diff --git a/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs.rej b/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs.rej new file mode 100644 index 000000000..2e721a4b5 --- /dev/null +++ b/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs.rej @@ -0,0 +1,61 @@ +diff a/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs b/crates/proof-of-sql/src/sql/proof/sumcheck_subpolynomial.rs (rejected hunks) +@@ -33,6 +33,59 @@ impl<'a, S: Scalar> SumcheckSubpolynomial<'a, S> { + subpolynomial_type: SumcheckSubpolynomialType, + terms: Vec>, + ) -> Self { ++ #[cfg(test)] ++ let concrete_terms = terms ++ .iter() ++ .map(|(mul, mles)| { ++ ( ++ mul, ++ mles.iter() ++ .map(|mle| mle.to_scalar_vec()) ++ .collect::>(), ++ ) ++ }) ++ .collect::>(); ++ #[cfg(test)] ++ let len = concrete_terms ++ .iter() ++ .flat_map(|(_, mles)| mles.iter().map(|mle| mle.len())) ++ .max() ++ .unwrap_or(0); ++ #[cfg(test)] ++ match subpolynomial_type { ++ SumcheckSubpolynomialType::Identity => { ++ (0..len).for_each(|i| { ++ let sum = concrete_terms ++ .iter() ++ .map(|(mul, mles)| { ++ **mul ++ * mles ++ .iter() ++ .map(|mle| *mle.get(i).unwrap_or(&S::zero())) ++ .product::() ++ }) ++ .sum::(); ++ assert_eq!(sum, S::zero()); ++ }); ++ } ++ SumcheckSubpolynomialType::ZeroSum => { ++ let sum = (0..len) ++ .map(|i| { ++ concrete_terms ++ .iter() ++ .map(|(mul, mles)| { ++ **mul ++ * mles ++ .iter() ++ .map(|mle| *mle.get(i).unwrap_or(&S::zero())) ++ .product::() ++ }) ++ .sum::() ++ }) ++ .sum::(); ++ assert_eq!(sum, S::zero()); ++ } ++ } + Self { + terms, + subpolynomial_type, 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 b622f48c0..dc04e83d2 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 @@ -124,6 +124,8 @@ impl ProverEvaluate for SliceExec { ) -> (Table<'a, S>, Vec) { // 1. columns let (input, input_one_eval_lengths) = self.input.result_evaluate(alloc, table_map); + dbg!(&input_one_eval_lengths); + dbg!(&input); let columns = input.columns().copied().collect::>(); // 2. select let select = get_slice_select(input.num_rows(), self.skip, self.fetch); @@ -140,6 +142,8 @@ impl ProverEvaluate for SliceExec { .expect("Failed to create table from iterator"); let mut one_eval_lengths = input_one_eval_lengths; one_eval_lengths.push(output_length); + dbg!(&res); + dbg!(&one_eval_lengths); (res, one_eval_lengths) } @@ -158,6 +162,7 @@ impl ProverEvaluate for SliceExec { ) -> Table<'a, S> { // 1. columns let input = self.input.final_round_evaluate(builder, alloc, table_map); + dbg!(&input); let columns = input.columns().copied().collect::>(); // 2. select let select = get_slice_select(input.num_rows(), self.skip, self.fetch); @@ -185,13 +190,15 @@ impl ProverEvaluate for SliceExec { input.num_rows(), result_len, ); - Table::<'a, S>::try_from_iter_with_options( + let res = Table::<'a, S>::try_from_iter_with_options( self.get_column_result_fields() .into_iter() .map(|expr| expr.name()) .zip(filtered_columns), TableOptions::new(Some(output_length)), ) - .expect("Failed to create table from iterator") + .expect("Failed to create table from iterator"); + dbg!(&res); + res } } diff --git a/crates/proof-of-sql/src/sql/proof_plans/slice_exec_test.rs b/crates/proof-of-sql/src/sql/proof_plans/slice_exec_test.rs index 84a80c523..29307a705 100644 --- a/crates/proof-of-sql/src/sql/proof_plans/slice_exec_test.rs +++ b/crates/proof-of-sql/src/sql/proof_plans/slice_exec_test.rs @@ -39,6 +39,56 @@ fn we_can_prove_and_get_the_correct_result_from_a_slice_exec() { assert_eq!(res, expected_res); } +#[test] +fn we_can_prove_and_get_the_correct_result_from_a_slice_exec2() { + let alloc = Bump::new(); + let t = "namespace.table_name".parse().unwrap(); + let plan = slice_exec( + table_exec( + t, + vec![ + ColumnField::new("language_rank".parse().unwrap(), ColumnType::BigInt), + ColumnField::new("language_name".parse().unwrap(), ColumnType::VarChar), + ColumnField::new("space_and_time".parse().unwrap(), ColumnType::VarChar), + ], + ), + 1, + Some(2), + ); + let accessor = TableTestAccessor::::new_from_table( + t, + table([ + borrowed_bigint("language_rank", [0_i64, 1, 2, 3], &alloc), + borrowed_varchar( + "language_name", + ["English", "Español", "Português", "Français"], + &alloc, + ), + borrowed_varchar( + "space_and_time", + [ + "space and time", + "espacio y tiempo", + "espaço e tempo", + "espace et temps", + ], + &alloc, + ), + ]), + 0_usize, + (), + ); + let verifiable_res = VerifiableQueryResult::new(&plan, &accessor, &()); + exercise_verification(&verifiable_res, &plan, &accessor, t); + let res = verifiable_res.verify(&plan, &accessor, &()).unwrap().table; + let expected_res = owned_table([ + bigint("language_rank", [1, 2]), + varchar("language_name", ["Español", "Português"]), + varchar("space_and_time", ["espacio y tiempo", "espaço e tempo"]), + ]); + assert_eq!(res, expected_res); +} + #[test] fn we_can_prove_and_get_the_correct_empty_result_from_a_slice_exec() { let data = owned_table([ @@ -244,13 +294,13 @@ fn we_can_get_the_correct_result_from_a_slice_using_result_evaluate() { } #[test] -fn we_can_prove_a_slice_exec() { +fn we_can_prove_a_slice_exec_cat() { let data = owned_table([ - bigint("a", [101, 105, 105, 105, 105]), - bigint("b", [1, 2, 3, 4, 7]), - int128("c", [1, 3, 3, 4, 5]), - varchar("d", ["1", "2", "3", "4", "5"]), - scalar("e", [1, 2, 3, 4, 5]), + bigint("a", [17, 18]), + // bigint("b", [1, 2, 3, 4, 7]), + // int128("c", [1, 3, 3, 4, 5]), + // varchar("d", ["1", "2", "3", "4", "5"]), + // scalar("e", [1, 2, 3, 4, 5]), ]); let t = "sxt.t".parse().unwrap(); let mut accessor = OwnedTableTestAccessor::::new_empty_with_setup(()); @@ -258,32 +308,33 @@ fn we_can_prove_a_slice_exec() { let expr = slice_exec( filter( vec![ - col_expr_plan(t, "b", &accessor), - col_expr_plan(t, "c", &accessor), - col_expr_plan(t, "d", &accessor), - col_expr_plan(t, "e", &accessor), - aliased_plan(const_int128(105), "const"), - aliased_plan( - equal(column(t, "b", &accessor), column(t, "c", &accessor)), - "bool", - ), + col_expr_plan(t, "a", &accessor), + // col_expr_plan(t, "c", &accessor), + // col_expr_plan(t, "d", &accessor), + // col_expr_plan(t, "e", &accessor), + // aliased_plan(const_int128(105), "const"), + // aliased_plan( + // equal(column(t, "b", &accessor), column(t, "c", &accessor)), + // "bool", + // ), ], tab(t), - equal(column(t, "a", &accessor), const_int128(105)), + equal(column(t, "a", &accessor), const_int128(18)), ), - 2, + 0, Some(1), ); + dbg!(&expr); let res = VerifiableQueryResult::new(&expr, &accessor, &()); exercise_verification(&res, &expr, &accessor, t); let res = res.verify(&expr, &accessor, &()).unwrap().table; let expected = owned_table([ - bigint("b", [4]), - int128("c", [4]), - varchar("d", ["4"]), - scalar("e", [4]), - int128("const", [105]), - boolean("bool", [true]), + bigint("a", [18]), + // int128("c", [4]), + // varchar("d", ["4"]), + // scalar("e", [4]), + // int128("const", [105]), + // boolean("bool", [true]), ]); assert_eq!(res, expected); }