Skip to content

Commit

Permalink
Avocado example (#315)
Browse files Browse the repository at this point in the history
# Rationale for this change

More examples in the repo provide better documentation as well as
provide some regression testing on top of other tests.

# What changes are included in this PR?

A simple example is added.

# Are these changes tested?
Yes
  • Loading branch information
jd-sxt authored Oct 24, 2024
2 parents d455a13 + 97d112d commit b5fed3d
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ jobs:
run: cargo run --example books
- name: Run brands example
run: cargo run --example brands
- name: Run avocado-prices example
run: cargo run --example avocado-prices
- name: Run plastics example
run: cargo run --example plastics
- name: Run posql_db example (With Blitzar)
Expand Down Expand Up @@ -240,4 +242,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
4 changes: 4 additions & 0 deletions crates/proof-of-sql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ required-features = [ "arrow" ]
name = "plastics"
required-features = [ "arrow" ]

[[example]]
name = "avocado-prices"
required-features = [ "arrow" ]

[[bench]]
name = "posql_benches"
harness = false
Expand Down
37 changes: 37 additions & 0 deletions crates/proof-of-sql/examples/avocado-prices/avocado-prices.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Year,Price
1990,96
1991,100
1992,269
1993,149
1994,127
1995,153
1996,232
1997,127
1998,249
1999,240
2000,241
2001,90
2002,91
2003,169
2004,167
2005,56
2006,230
2007,174
2008,124
2009,92
2010,201
2011,167
2012,125
2013,147
2014,285
2015,154
2016,106
2017,223
2018,85
2019,145
2020,147
2021,68
2022,142
2023,281
2024,164

124 changes: 124 additions & 0 deletions crates/proof-of-sql/examples/avocado-prices/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//! Example to use Proof of SQL with datasets
//! To run, use `cargo run --example avocado-prices`.
//!
//! NOTE: If this doesn't work because you do not have the appropriate GPU drivers installed,
//! you can run `cargo run --release --example avocado-prices --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::{OwnedTable, OwnedTableTestAccessor},
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)`.
// For a sampling:
// max_nu = 3 => max table size is 32 rows
// max_nu = 4 => max table size is 128 rows
// max_nu = 8 => max table size is 32768 rows
// max_nu = 10 => max table size is 0.5 million rows
// max_nu = 15 => max table size is 0.5 billion rows
// max_nu = 20 => max table size is 0.5 trillion rows
// Note: we will eventually load these from a file.
const DORY_SETUP_MAX_NU: usize = 8;
// This should be a "nothing-up-my-sleeve" phrase or number.
const DORY_SEED: [u8; 32] = *b"len 32 rng seed - Space and Time";

/// # Panics
/// Will panic if the query does not parse or the proof fails to verify.
fn prove_and_verify_query(
sql: &str,
accessor: &OwnedTableTestAccessor<DynamicDoryEvaluationProof>,
prover_setup: &ProverSetup,
verifier_setup: &VerifierSetup,
) {
// Parse the query:
println!("Parsing the query: {sql}...");
let now = Instant::now();
let query_plan = QueryExpr::<DynamicDoryCommitment>::try_new(
sql.parse().unwrap(),
"avocado".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::<DynamicDoryEvaluationProof>::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/avocado-prices/avocado-prices.csv";
let data_batch = ReaderBuilder::new(SchemaRef::new(
infer_schema_from_files(&[filename.to_string()], b',', None, true).unwrap(),
))
.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 accessor = OwnedTableTestAccessor::<DynamicDoryEvaluationProof>::new_from_table(
"avocado.prices".parse().unwrap(),
OwnedTable::try_from(data_batch).unwrap(),
0,
&prover_setup,
);

prove_and_verify_query(
"SELECT COUNT(*) AS total FROM prices",
&accessor,
&prover_setup,
&verifier_setup,
);
prove_and_verify_query(
"SELECT Price, COUNT(*) AS total FROM prices GROUP BY Price ORDER BY total",
&accessor,
&prover_setup,
&verifier_setup,
);
prove_and_verify_query(
"SELECT Year, COUNT(*) AS total FROM prices WHERE Price > 100 GROUP BY Year ORDER BY total DESC LIMIT 5",
&accessor,
&prover_setup,
&verifier_setup,
);
}

0 comments on commit b5fed3d

Please sign in to comment.