diff --git a/crates/proof-of-sql/Cargo.toml b/crates/proof-of-sql/Cargo.toml index 6f4012201..2f0676307 100644 --- a/crates/proof-of-sql/Cargo.toml +++ b/crates/proof-of-sql/Cargo.toml @@ -59,7 +59,6 @@ zerocopy = { workspace = true } alloy-sol-types = { workspace = true } arrow-csv = { workspace = true } blitzar = { workspace = true } -clap = { workspace = true, features = ["derive"] } criterion = { workspace = true, features = ["html_reports"] } merlin = { workspace = true } opentelemetry = { workspace = true } @@ -94,6 +93,11 @@ name = "generate-parameters" path = "utils/generate-parameters/main.rs" required-features = [ "std", "blitzar"] +[[bin]] +name = "commitment-utility" +path = "utils/commitment-utility/main.rs" +required-features = [ "std", "blitzar"] + [[example]] name = "hello_world" required-features = ["test"] diff --git a/crates/proof-of-sql/utils/commitment-utility/main.rs b/crates/proof-of-sql/utils/commitment-utility/main.rs new file mode 100644 index 000000000..ae44929cb --- /dev/null +++ b/crates/proof-of-sql/utils/commitment-utility/main.rs @@ -0,0 +1,135 @@ +//! Utility to deserialize and print a commitment from a file or stdin. +use clap::{Parser, ValueEnum}; +use curve25519_dalek::ristretto::RistrettoPoint; +use proof_of_sql::{ + base::commitment::TableCommitment, + proof_primitive::dory::{DoryCommitment, DynamicDoryCommitment}, +}; +use snafu::Snafu; +use std::{ + fs::File, + io::{self, Read, Write}, + path::PathBuf, +}; + +#[derive(ValueEnum, Clone, Debug)] +/// Supported commitment schemes. +enum CommitmentScheme { + /// Inner Product Argument (IPA) commitment scheme. + Ipa, + /// Dory commitment scheme. + Dory, + /// Dynamic Dory commitment scheme. + DynamicDory, +} + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { + /// Input file (defaults to None which is stdin) + #[arg(short, long)] + input: Option, + + /// Output file (defaults to None which is stdout) + #[arg(short, long)] + output: Option, + + /// Commitment scheme (e.g. `ipa`, `dynamic_dory`, `dory`) + #[arg(long, value_enum, default_value = "CommitmentScheme::DynamicDory")] + scheme: CommitmentScheme, +} + +#[derive(Debug, Snafu)] +enum CommitUtilityError { + #[snafu(display("Failed to open input file '{:?}'", filename))] + OpenInputFile { filename: PathBuf }, + + #[snafu(display("Failed to read from input file '{:?}'", filename))] + ReadInputFile { filename: PathBuf }, + + #[snafu(display("Failed to read from stdin"))] + ReadStdin, + + #[snafu(display("Failed to create output file '{:?}'", filename))] + CreateOutputFile { filename: PathBuf }, + + #[snafu(display("Failed to write to output file '{:?}'", filename))] + WriteOutputFile { filename: PathBuf }, + + #[snafu(display("Failed to write to stdout"))] + WriteStdout, + + #[snafu(display("Failed to deserialize commitment"))] + DeserializationError, +} + +type CommitUtilityResult = std::result::Result; + +fn main() -> CommitUtilityResult<()> { + let cli = Cli::parse(); + + // Read input data + let input_data = match &cli.input { + Some(input_file) => { + let mut file = + File::open(input_file).map_err(|_| CommitUtilityError::OpenInputFile { + filename: input_file.clone(), + })?; + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer) + .map_err(|_| CommitUtilityError::ReadInputFile { + filename: input_file.clone(), + })?; + buffer + } + None => { + let mut buffer = Vec::new(); + io::stdin() + .read_to_end(&mut buffer) + .map_err(|_| CommitUtilityError::ReadStdin)?; + buffer + } + }; + + // Deserialize commitment based on the scheme + let human_readable = match cli.scheme { + CommitmentScheme::DynamicDory => { + let commitment: TableCommitment = + postcard::from_bytes(&input_data) + .map_err(|_| CommitUtilityError::DeserializationError)?; + format!("{commitment:#?}") + } + CommitmentScheme::Dory => { + let commitment: TableCommitment = postcard::from_bytes(&input_data) + .map_err(|_| CommitUtilityError::DeserializationError)?; + format!("{commitment:#?}") + } + CommitmentScheme::Ipa => { + let commitment: TableCommitment = postcard::from_bytes(&input_data) + .map_err(|_| CommitUtilityError::DeserializationError)?; + format!("{commitment:#?}") + } + }; + + // Write output data + match &cli.output { + Some(output_file) => { + let mut file = + File::create(output_file).map_err(|_| CommitUtilityError::CreateOutputFile { + filename: output_file.clone(), + })?; + file.write_all(human_readable.as_bytes()).map_err(|_| { + CommitUtilityError::WriteOutputFile { + filename: output_file.clone(), + } + })?; + } + None => { + io::stdout() + .write_all(human_readable.as_bytes()) + .map_err(|_| CommitUtilityError::WriteStdout)?; + } + } + + Ok(()) +} diff --git a/crates/proof-of-sql/utils/generate-parameters/round_trip_test.rs b/crates/proof-of-sql/utils/generate-parameters/round_trip_test.rs index 37aeea7dd..b7ce2d429 100644 --- a/crates/proof-of-sql/utils/generate-parameters/round_trip_test.rs +++ b/crates/proof-of-sql/utils/generate-parameters/round_trip_test.rs @@ -19,6 +19,8 @@ fn we_can_generate_save_and_load_public_setups() { // Run the binary with nu = 4, mode = "pv", and target as the temp directory let output = Command::new("cargo") .arg("run") + .arg("--bin") + .arg("generate-parameters") .arg("--release") .arg("--") .arg("--nu")