Skip to content

Commit

Permalink
feat: brands example (#305)
Browse files Browse the repository at this point in the history
# Rationale for this change

Add an additional brands example to help improve documentation.

# What changes are included in this PR?

brands example is added.

# Are these changes tested?
Yes.

```
Parsing the query: SELECT COUNT(*) AS total_brands FROM global_brands...
Done in 0.324239 ms.
Generating proof...Done in 42.034217999999996 ms.
Verifying proof...Verified in 11.154853 ms.
Query Result:
Ok(OwnedTable { table: {Identifier { name: "total_brands" }: BigInt([25])} })
Parsing the query: SELECT Name FROM global_brands WHERE Founded < 1950...
Done in 0.410224 ms.
Generating proof...Done in 90.15787999999999 ms.
Verifying proof...Verified in 34.490026 ms.
Query Result:
Ok(OwnedTable { table: {Identifier { name: "name" }: VarChar(["Samsung", "Toyota", "Coca-Cola", "Mercedes-Benz", "Louis Vuitton", "BMW", "Disney", "Honda", "Pepsi", "Adidas", "Nestle", "Unilever", "Sony", "Volkswagen", "IKEA", "H&M", "Gucci"])} })
Parsing the query: SELECT Country, SUM(Revenue) AS total_revenue FROM global_brands GROUP BY Country ORDER BY total_revenue DESC LIMIT 5...
Done in 0.887756 ms.
Generating proof...Done in 54.226909 ms.
Verifying proof...Verified in 17.774898 ms.
Query Result:
Ok(OwnedTable { table: {Identifier { name: "country" }: VarChar(["United States", "Germany", "Japan", "South Korea", "Switzerland"]), Identifier { name: "total_revenue" }: Decimal75(Precision(20), 10, [MontScalar(BigInt([16337200000000, 0, 0, 0])), MontScalar(BigInt([5476100000000, 0, 0, 0])), MontScalar(BigInt([4926200000000, 0, 0, 0])), MontScalar(BigInt([2007300000000, 0, 0, 0])), MontScalar(BigInt([944200000000, 0, 0, 0]))])} })
```
  • Loading branch information
henrymai authored Oct 23, 2024
2 parents 946c4e2 + 41b09dc commit 3538016
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ jobs:
run: cargo run --example dinosaurs
- name: Run books example
run: cargo run --example books
- name: Run brands example
run: cargo run --example brands
- 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)
Expand Down
4 changes: 4 additions & 0 deletions crates/proof-of-sql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ required-features = [ "arrow" ]
name = "books"
required-features = [ "arrow" ]

[[example]]
name = "brands"
required-features = [ "arrow" ]

[[bench]]
name = "posql_benches"
harness = false
Expand Down
26 changes: 26 additions & 0 deletions crates/proof-of-sql/examples/brands/brands.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Name,Country,Founded,Revenue
Apple,United States,1976,365.82
Samsung,South Korea,1938,200.73
Microsoft,United States,1975,198.27
Amazon,United States,1994,513.98
Google,United States,1998,282.84
Toyota,Japan,1937,278.52
Coca-Cola,United States,1886,38.66
Mercedes-Benz,Germany,1926,154.31
McDonald's,United States,1955,19.2
Nike,United States,1964,44.54
Louis Vuitton,France,1854,75.98
BMW,Germany,1916,121.87
Disney,United States,1923,67.42
Honda,Japan,1948,129.21
Pepsi,United States,1893,79.47
Adidas,Germany,1949,21.23
Nestle,Switzerland,1866,94.42
Unilever,Netherlands,1929,58.26
Sony,Japan,1946,84.89
Volkswagen,Germany,1937,250.2
IKEA,Sweden,1943,44.6
Starbucks,United States,1971,23.52
Zara,Spain,1974,27.72
H&M,Sweden,1947,21.73
Gucci,Italy,1921,10.34
128 changes: 128 additions & 0 deletions crates/proof-of-sql/examples/brands/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//! This is a non-interactive example of using Proof of SQL with a brands dataset.
//! To run this, use `cargo run --release --example brands`.
//!
//! NOTE: If this doesn't work because you do not have the appropriate GPU drivers installed,
//! you can run `cargo run --release --example brands --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"8f3a2e1c5b9d7f0a6e4d2c8b7a9f1e3d";

/// # 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(),
"brands".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/brands/brands.csv";
let inferred_schema =
SchemaRef::new(infer_schema_from_files(&[filename.to_string()], b',', None, true).unwrap());
let posql_compatible_schema = get_posql_compatible_schema(&inferred_schema);

let brands_batch = ReaderBuilder::new(posql_compatible_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::<DynamicDoryEvaluationProof>::new_empty_with_setup(&prover_setup);
accessor.add_table(
"brands.global_brands".parse().unwrap(),
OwnedTable::try_from(brands_batch).unwrap(),
0,
);

// Query 1: Count the total number of brands
prove_and_verify_query(
"SELECT COUNT(*) AS total_brands FROM global_brands",
&accessor,
&prover_setup,
&verifier_setup,
);

// Query 2: List the names of brands founded before 1950
prove_and_verify_query(
"SELECT Name FROM global_brands WHERE Founded < 1950",
&accessor,
&prover_setup,
&verifier_setup,
);

// Query 3: List the top 5 countries with the highest total revenue, ordered by total revenue
prove_and_verify_query(
"SELECT Country, SUM(Revenue) AS total_revenue FROM global_brands GROUP BY Country ORDER BY total_revenue DESC LIMIT 5",
&accessor,
&prover_setup,
&verifier_setup,
);
}

0 comments on commit 3538016

Please sign in to comment.