diff --git a/crates/proof-of-sql/src/base/commitment/test_evaluation_proof.rs b/crates/proof-of-sql/src/base/commitment/test_evaluation_proof.rs index e9422783f..61bb2af48 100644 --- a/crates/proof-of-sql/src/base/commitment/test_evaluation_proof.rs +++ b/crates/proof-of-sql/src/base/commitment/test_evaluation_proof.rs @@ -1,13 +1,15 @@ use super::{naive_commitment::NaiveCommitment, CommitmentEvaluationProof}; -use crate::base::{proof::Transcript, scalar::test_scalar::TestScalar}; +use crate::base::{ + polynomial::compute_evaluation_vector, proof::Transcript, scalar::test_scalar::TestScalar, +}; /// This should only be used for the purpose of unit testing. -pub struct TestEvaluationProof {} +pub struct TestEvaluationProof; /// This should only be used for the purpose of unit testing. /// For now it is only being created for the purpose of implementing /// CommitmentEvaluationProof for TestEvaluationProof. -pub enum TestErrorType {} +pub struct TestErrorType; impl CommitmentEvaluationProof for TestEvaluationProof { type Scalar = TestScalar; @@ -27,20 +29,31 @@ impl CommitmentEvaluationProof for TestEvaluationProof { _generators_offset: u64, _setup: &Self::ProverPublicSetup<'_>, ) -> Self { - unimplemented!("The `CommitmentEvaluationProof` methods are unimplemented for `TestEvaluationProof`. There is nothing preventing a naive implementation here. If this gets done, this type should likely be renamed as `NaiveEvaluationProof` to reflect this.") + Self } fn verify_batched_proof( &self, _transcript: &mut impl Transcript, - _commit_batch: &[Self::Commitment], - _batching_factors: &[Self::Scalar], - _product: &Self::Scalar, - _b_point: &[Self::Scalar], + commit_batch: &[Self::Commitment], + batching_factors: &[Self::Scalar], + product: &Self::Scalar, + b_point: &[Self::Scalar], _generators_offset: u64, _table_length: usize, _setup: &Self::VerifierPublicSetup<'_>, ) -> Result<(), Self::Error> { - unimplemented!() + let mut v = vec![TestScalar::default(); 1 << b_point.len()]; + compute_evaluation_vector(&mut v, b_point); + (batching_factors.len() == commit_batch.len() + && commit_batch.iter().all(|c| c.0.len() <= 1 << b_point.len()) + && batching_factors + .iter() + .zip(commit_batch) + .map(|(f, c)| v.iter().zip(&c.0).map(|(a, b)| *a * *b).sum::() * *f) + .sum::() + == *product) + .then_some(()) + .ok_or(TestErrorType) } } diff --git a/crates/proof-of-sql/src/sql/proof_exprs/and_expr_test.rs b/crates/proof-of-sql/src/sql/proof_exprs/and_expr_test.rs index fa896fb69..8753ea42d 100644 --- a/crates/proof-of-sql/src/sql/proof_exprs/and_expr_test.rs +++ b/crates/proof-of-sql/src/sql/proof_exprs/and_expr_test.rs @@ -1,11 +1,13 @@ use crate::{ base::{ - commitment::InnerProductProof, + commitment::{test_evaluation_proof::TestEvaluationProof, InnerProductProof}, database::{owned_table_utility::*, Column, OwnedTableTestAccessor}, }, sql::{ proof::{exercise_verification, VerifiableQueryResult}, - proof_exprs::{test_utility::*, DynProofExpr, ProofExpr}, + proof_exprs::{ + proof_expr_test_plan::ProofExprTestPlan, test_utility::*, DynProofExpr, ProofExpr, + }, proof_plans::test_utility::*, }, }; @@ -18,6 +20,27 @@ use rand::{ }; use rand_core::SeedableRng; +#[test] +fn we_can_prove_a_simple_and_expr() { + let data = owned_table([ + boolean("a", [false, true, false, true]), + boolean("b", [false, false, true, true]), + ]); + let t = "sxt.t".parse().unwrap(); + let accessor = OwnedTableTestAccessor::::new_from_table(t, data, 0, ()); + let ast = ProofExprTestPlan { + expr: and(column(t, "a", &accessor), column(t, "b", &accessor)), + table: t, + result_name: "c".parse().unwrap(), + }; + let verifiable_res = VerifiableQueryResult::::new(&ast, &accessor, &()); + let res = verifiable_res.verify(&ast, &accessor, &()).unwrap().table; + assert_eq!( + res, + owned_table([boolean("c", [false, false, false, true])]) + ); +} + #[test] fn we_can_prove_a_simple_and_query() { let data = owned_table([ diff --git a/crates/proof-of-sql/src/sql/proof_exprs/mod.rs b/crates/proof-of-sql/src/sql/proof_exprs/mod.rs index d6e16f969..8549b28d6 100644 --- a/crates/proof-of-sql/src/sql/proof_exprs/mod.rs +++ b/crates/proof-of-sql/src/sql/proof_exprs/mod.rs @@ -84,3 +84,6 @@ mod column_expr_test; #[allow(dead_code, unused_variables)] mod range_check; + +#[cfg(test)] +mod proof_expr_test_plan; diff --git a/crates/proof-of-sql/src/sql/proof_exprs/proof_expr_test_plan.rs b/crates/proof-of-sql/src/sql/proof_exprs/proof_expr_test_plan.rs new file mode 100644 index 000000000..0d24f8fa6 --- /dev/null +++ b/crates/proof-of-sql/src/sql/proof_exprs/proof_expr_test_plan.rs @@ -0,0 +1,85 @@ +use super::{DynProofExpr, ProofExpr}; +use crate::{ + base::{ + commitment::Commitment, + database::{ + Column, ColumnField, ColumnRef, CommitmentAccessor, DataAccessor, MetadataAccessor, + OwnedTable, TableRef, + }, + map::IndexSet, + proof::ProofError, + }, + sql::proof::{ + CountBuilder, Indexes, ProofBuilder, ProofPlan, ProverEvaluate, ResultBuilder, + VerificationBuilder, + }, +}; +use bumpalo::Bump; +use proof_of_sql_parser::Identifier; +use serde::Serialize; + +#[derive(Debug, Serialize)] +pub(super) struct ProofExprTestPlan { + pub expr: DynProofExpr, + pub table: TableRef, + pub result_name: Identifier, +} +impl ProverEvaluate for ProofExprTestPlan { + fn result_evaluate<'a>( + &self, + builder: &mut ResultBuilder, + alloc: &'a Bump, + accessor: &'a dyn DataAccessor, + ) -> Vec> { + let table_length = accessor.get_length(self.table); + builder.set_result_indexes(Indexes::Dense(0..table_length as u64)); + vec![self.expr.result_evaluate(table_length, alloc, accessor)] + } + fn prover_evaluate<'a>( + &self, + builder: &mut ProofBuilder<'a, C::Scalar>, + alloc: &'a Bump, + accessor: &'a dyn DataAccessor, + ) -> Vec> { + vec![self.expr.prover_evaluate(builder, alloc, accessor)] + } +} +impl ProofPlan for ProofExprTestPlan { + fn count( + &self, + builder: &mut CountBuilder, + _accessor: &dyn MetadataAccessor, + ) -> Result<(), ProofError> { + builder.count_result_columns(1); + self.expr.count(builder) + } + fn get_length(&self, accessor: &dyn MetadataAccessor) -> usize { + accessor.get_length(self.table) + } + fn get_offset(&self, accessor: &dyn MetadataAccessor) -> usize { + accessor.get_offset(self.table) + } + fn verifier_evaluate( + &self, + builder: &mut VerificationBuilder, + accessor: &dyn CommitmentAccessor, + _result: Option<&OwnedTable>, + ) -> Result, ProofError> { + let expected_result_eval = self.expr.verifier_evaluate(builder, accessor)?; + let actual_result_eval = builder.consume_result_mle(); + if expected_result_eval != actual_result_eval { + Err(ProofError::VerificationError { + error: "expected_result_eval not same as actual_result_eval", + })? + } + Ok(vec![actual_result_eval]) + } + fn get_column_result_fields(&self) -> Vec { + vec![ColumnField::new(self.result_name, self.expr.data_type())] + } + fn get_column_references(&self) -> IndexSet { + let mut result = IndexSet::default(); + self.expr.get_column_references(&mut result); + result + } +}