From 43a174e44569bd3c150bf3edd2f6a22fee989d2e Mon Sep 17 00:00:00 2001 From: Henry Mai Date: Wed, 23 Oct 2024 11:24:53 -0400 Subject: [PATCH] feat: plastics example --- .github/workflows/lint-and-test.yml | 4 +- crates/proof-of-sql/Cargo.toml | 6 +- crates/proof-of-sql/examples/plastics/main.rs | 135 ++++++++++++++++++ .../examples/plastics/plastics.csv | 19 +++ 4 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 crates/proof-of-sql/examples/plastics/main.rs create mode 100644 crates/proof-of-sql/examples/plastics/plastics.csv diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index dfebc0ea6..85014b80a 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -124,6 +124,8 @@ jobs: run: cargo run --example books - name: Run brands example run: cargo run --example brands + - name: Run plastics example + run: cargo run --example plastics - name: Run posql_db example (With Blitzar) run: bash crates/proof-of-sql/examples/posql_db/run_example.sh - name: Run posql_db example (Without Blitzar) @@ -238,4 +240,4 @@ jobs: - name: Install solhint run: npm install -g solhint - name: Run tests - run: solhint -c 'crates/proof-of-sql/.solhint.json' 'crates/proof-of-sql/**/*.sol' -w 0 + run: solhint -c 'crates/proof-of-sql/.solhint.json' 'crates/proof-of-sql/**/*.sol' -w 0 \ No newline at end of file diff --git a/crates/proof-of-sql/Cargo.toml b/crates/proof-of-sql/Cargo.toml index d4fe9f69d..853e2e31f 100644 --- a/crates/proof-of-sql/Cargo.toml +++ b/crates/proof-of-sql/Cargo.toml @@ -115,6 +115,10 @@ required-features = [ "arrow" ] name = "brands" required-features = [ "arrow" ] +[[example]] +name = "plastics" +required-features = [ "arrow" ] + [[bench]] name = "posql_benches" harness = false @@ -128,4 +132,4 @@ required-features = [ "test" ] [[bench]] name = "jaeger_benches" harness = false -required-features = [ "blitzar" ] +required-features = [ "blitzar" ] \ No newline at end of file diff --git a/crates/proof-of-sql/examples/plastics/main.rs b/crates/proof-of-sql/examples/plastics/main.rs new file mode 100644 index 000000000..7263e7538 --- /dev/null +++ b/crates/proof-of-sql/examples/plastics/main.rs @@ -0,0 +1,135 @@ +//! This is a non-interactive example of using Proof of SQL with a plastics dataset. +//! To run this, use `cargo run --release --example plastics`. +//! +//! NOTE: If this doesn't work because you do not have the appropriate GPU drivers installed, +//! you can run `cargo run --release --example plastics --no-default-features --features="arrow cpu-perf"` instead. It will be slower for proof generation. + +use arrow::datatypes::SchemaRef; +use arrow_csv::{infer_schema_from_files, ReaderBuilder}; +use proof_of_sql::{ + base::database::{ + arrow_schema_utility::get_posql_compatible_schema, OwnedTable, OwnedTableTestAccessor, + TestAccessor, + }, + proof_primitive::dory::{ + DynamicDoryCommitment, DynamicDoryEvaluationProof, ProverSetup, PublicParameters, + VerifierSetup, + }, + sql::{parse::QueryExpr, postprocessing::apply_postprocessing_steps, proof::QueryProof}, +}; +use rand::{rngs::StdRng, SeedableRng}; +use std::{fs::File, time::Instant}; + +// We generate the public parameters and the setups used by the prover and verifier for the Dory PCS. +// The `max_nu` should be set such that the maximum table size is less than `2^(2*max_nu-1)`. +const DORY_SETUP_MAX_NU: usize = 8; +// This should be a "nothing-up-my-sleeve" phrase or number. +const DORY_SEED: [u8; 32] = *b"32f7f321c4ab1234d5e6f7a8b9c0d1e2"; + +/// # Panics +/// Will panic if the query does not parse or the proof fails to verify. +fn prove_and_verify_query( + sql: &str, + accessor: &OwnedTableTestAccessor, + prover_setup: &ProverSetup, + verifier_setup: &VerifierSetup, +) { + // Parse the query: + println!("Parsing the query: {sql}..."); + let now = Instant::now(); + let query_plan = QueryExpr::::try_new( + sql.parse().unwrap(), + "plastics".parse().unwrap(), + accessor, + ) + .unwrap(); + println!("Done in {} ms.", now.elapsed().as_secs_f64() * 1000.); + + // Generate the proof and result: + print!("Generating proof..."); + let now = Instant::now(); + let (proof, provable_result) = QueryProof::::new( + query_plan.proof_expr(), + accessor, + &prover_setup, + ); + println!("Done in {} ms.", now.elapsed().as_secs_f64() * 1000.); + + // Verify the result with the proof: + print!("Verifying proof..."); + let now = Instant::now(); + let result = proof + .verify( + query_plan.proof_expr(), + accessor, + &provable_result, + &verifier_setup, + ) + .unwrap(); + let result = apply_postprocessing_steps(result.table, query_plan.postprocessing()); + println!("Verified in {} ms.", now.elapsed().as_secs_f64() * 1000.); + + // Display the result + println!("Query Result:"); + println!("{result:?}"); +} + +fn main() { + let mut rng = StdRng::from_seed(DORY_SEED); + let public_parameters = PublicParameters::rand(DORY_SETUP_MAX_NU, &mut rng); + let prover_setup = ProverSetup::from(&public_parameters); + let verifier_setup = VerifierSetup::from(&public_parameters); + + let filename = "./crates/proof-of-sql/examples/plastics/plastics.csv"; + let schema = get_posql_compatible_schema(&SchemaRef::new( + infer_schema_from_files(&[filename.to_string()], b',', None, true).unwrap(), + )); + let plastics_batch = ReaderBuilder::new(schema) + .with_header(true) + .build(File::open(filename).unwrap()) + .unwrap() + .next() + .unwrap() + .unwrap(); + + // Load the table into an "Accessor" so that the prover and verifier can access the data/commitments. + let mut accessor = + OwnedTableTestAccessor::::new_empty_with_setup(&prover_setup); + accessor.add_table( + "plastics.types".parse().unwrap(), + OwnedTable::try_from(plastics_batch).unwrap(), + 0, + ); + + // Query 1: Count total number of plastic types + prove_and_verify_query( + "SELECT COUNT(*) AS total_types FROM types", + &accessor, + &prover_setup, + &verifier_setup, + ); + + // Query 2: List names of biodegradable plastics + prove_and_verify_query( + "SELECT Name FROM types WHERE Biodegradable = TRUE ORDER BY Name", + &accessor, + &prover_setup, + &verifier_setup, + ); + + // Query 3: Show average density of plastics by recycling code + prove_and_verify_query( + "SELECT Code, SUM(Density)/COUNT(*) as avg_density FROM types GROUP BY Code ORDER BY Code", + &accessor, + &prover_setup, + &verifier_setup, + ); + + // Query 4: List plastics with density greater than 1.0 g/cm³ + prove_and_verify_query( + "SELECT Name, Density FROM types WHERE Density > 1.0 ORDER BY Density DESC", + &accessor, + &prover_setup, + &verifier_setup, + ); +} diff --git a/crates/proof-of-sql/examples/plastics/plastics.csv b/crates/proof-of-sql/examples/plastics/plastics.csv new file mode 100644 index 000000000..9b793da0a --- /dev/null +++ b/crates/proof-of-sql/examples/plastics/plastics.csv @@ -0,0 +1,19 @@ +Name,Code,Density,Biodegradable +Polyethylene Terephthalate (PET),1,1.38,FALSE +High-Density Polyethylene (HDPE),2,0.97,FALSE +Polyvinyl Chloride (PVC),3,1.40,FALSE +Low-Density Polyethylene (LDPE),4,0.92,FALSE +Polypropylene (PP),5,0.90,FALSE +Polystyrene (PS),6,1.05,FALSE +Polylactic Acid (PLA),7,1.25,TRUE +Polybutylene Adipate Terephthalate (PBAT),7,1.26,TRUE +Polyhydroxyalkanoates (PHA),7,1.24,TRUE +Polybutylene Succinate (PBS),7,1.26,TRUE +Acrylic (PMMA),7,1.18,FALSE +Polycarbonate (PC),7,1.20,FALSE +Polyurethane (PU),7,1.05,FALSE +Acrylonitrile Butadiene Styrene (ABS),7,1.04,FALSE +Polyamide (Nylon),7,1.15,FALSE +Polyethylene Furanoate (PEF),7,1.43,TRUE +Thermoplastic Starch (TPS),7,1.35,TRUE +Cellulose Acetate,7,1.30,TRUE \ No newline at end of file