diff --git a/air/src/options.rs b/air/src/options.rs index 5811b44..a1709ec 100644 --- a/air/src/options.rs +++ b/air/src/options.rs @@ -26,17 +26,21 @@ impl ProofOptions { )) } - // TODO: Use parameters appropriate for 252-bit field (see ethSTARK paper, - // sections 5.10.1 and 5.10.2) - pub fn with_96_bit_security() -> Self { + pub fn with_proof_options( + num_queries: Option, + blowup_factor: Option, + grinding_factor: Option, + fri_folding_factor: Option, + fri_max_remainder_size: Option, + ) -> Self { Self(WinterProofOptions::new( - 54, // 27 - 4, //8, - 16, + num_queries.unwrap_or(54), // 27 + blowup_factor.unwrap_or(4), //8, + grinding_factor.unwrap_or(16), HashFunction::Blake3_192, FieldExtension::None, - 8, - 256, + fri_folding_factor.unwrap_or(8), + fri_max_remainder_size.unwrap_or(256), )) } @@ -47,7 +51,7 @@ impl ProofOptions { impl Default for ProofOptions { fn default() -> Self { - Self::with_96_bit_security() + Self::with_proof_options(None, None, None, None, None) } } diff --git a/cli/src/cmd/prove.rs b/cli/src/cmd/prove.rs deleted file mode 100644 index e46330c..0000000 --- a/cli/src/cmd/prove.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; - -use super::ProofData; -use crate::utils::Cmd; -use air::ProofOptions; -use clap::{Parser, ValueHint}; -use runner::ExecutionTrace; -use winter_utils::Serializable; - -pub struct ProveOutput {} - -#[derive(Parser, Debug)] -#[clap(author, version, about, long_about = None)] -pub struct ProveArgs { - #[clap( - help = "Path to the compiled Cairo program JSON file", - long, - value_hint = ValueHint::FilePath - )] - pub program: PathBuf, - - #[clap( - help = "Path to the execution trace output file", - long, - value_hint = ValueHint::FilePath - )] - pub trace: PathBuf, - - #[clap( - help = "Path to the memory output file", - long, - value_hint = ValueHint::FilePath - )] - pub memory: PathBuf, - - #[clap( - help = "Path to write the STARK proof", - long, - value_hint = ValueHint::FilePath - )] - pub output: PathBuf, - - #[clap( - help = "Number of serialized outputs", - long, - value_hint = ValueHint::FilePath - )] - pub num_outputs: Option, -} - -#[derive(Debug)] -pub enum Error {} - -impl Cmd for ProveArgs { - type Output = Result; - - fn run(self) -> Self::Output { - // Load trace from file - let trace = - ExecutionTrace::from_file(self.program, self.trace, self.memory, self.num_outputs); - - // Generate proof - let proof_options = ProofOptions::with_96_bit_security(); - let (proof, pub_inputs) = prover::prove_trace(trace, &proof_options).unwrap(); - let input_bytes = pub_inputs.to_bytes(); - let proof_bytes = proof.to_bytes(); - println!("Proof size: {:.1} KB", proof_bytes.len() as f64 / 1024f64); - - // Write proof to disk - let data = ProofData { - input_bytes, - proof_bytes, - }; - let b = bincode::serialize(&data).unwrap(); - let mut f = File::create(self.output).unwrap(); - f.write_all(&b).unwrap(); - - Ok(ProveOutput {}) - } -} diff --git a/cli/src/cmd/prove/args.rs b/cli/src/cmd/prove/args.rs new file mode 100644 index 0000000..1c83c28 --- /dev/null +++ b/cli/src/cmd/prove/args.rs @@ -0,0 +1,149 @@ +use clap::{Error, ErrorKind, Parser, ValueHint}; +use std::path::PathBuf; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +pub struct ProveArgs { + #[clap( + help = "Path to the compiled Cairo program JSON file", + long, + value_hint = ValueHint::FilePath + )] + pub program: PathBuf, + + #[clap( + help = "Path to the execution trace output file", + long, + value_hint = ValueHint::FilePath + )] + pub trace: PathBuf, + + #[clap( + help = "Path to the memory output file", + long, + value_hint = ValueHint::FilePath + )] + pub memory: PathBuf, + + #[clap( + help = "Path to write the STARK proof", + long, + value_hint = ValueHint::FilePath + )] + pub output: PathBuf, + + #[clap(help = "Number of serialized outputs", long)] + pub num_outputs: Option, + + #[clap( + help = "Number of queries for a STARK proof", + long, + value_parser(clap::builder::ValueParser::new(parse_num_queries)) + )] + pub num_queries: Option, + + #[clap( + help = "Blowup factor for a STARK proof", + long, + value_parser(clap::builder::ValueParser::new(parse_blowup_factor)) + )] + pub blowup_factor: Option, + + #[clap( + help = "Query seed grinding factor for a STARK proof", + long, + value_parser(clap::value_parser!(u32).range(..33)) + )] + pub grinding_factor: Option, + + #[clap( + help = "Factor by which the degree of a polynomial is reduced with each FRI layer", + long, + value_parser(clap::builder::ValueParser::new(parse_fri_folding_factor)) + )] + pub fri_folding_factor: Option, + + #[clap( + help = "Maximum allowed remainder (last FRI layer) size", + long, + value_parser(clap::builder::ValueParser::new(parse_fri_max_remainder_size)) + )] + pub fri_max_remainder_size: Option, +} + +fn parse_num_queries(value: &str) -> Result { + let value = value + .parse::() + .map_err(|e| Error::raw(ErrorKind::InvalidValue, format!("{}", e)))?; + + match value { + 0 => Err(Error::raw(ErrorKind::ValueValidation, "cannot be 0")), + 129.. => Err(Error::raw( + ErrorKind::ValueValidation, + "cannot be more than 128", + )), + _ => Ok(value), + } +} + +fn parse_blowup_factor(value: &str) -> Result { + let value = value + .parse::() + .map_err(|e| Error::raw(ErrorKind::InvalidValue, format!("{}", e)))?; + + if !value.is_power_of_two() { + return Err(Error::raw( + ErrorKind::ValueValidation, + "must be a power of two", + )); + } + + match value { + 0..=3 => Err(Error::raw( + ErrorKind::ValueValidation, + "cannot be smaller than 4", + )), + 257.. => Err(Error::raw( + ErrorKind::ValueValidation, + "cannot be more than 256", + )), + _ => Ok(value), + } +} + +fn parse_fri_folding_factor(value: &str) -> Result { + let value = value + .parse::() + .map_err(|e| Error::raw(ErrorKind::InvalidValue, format!("{}", e)))?; + + if value != 4 && value != 8 && value != 16 { + Err(Error::raw(ErrorKind::ValueValidation, "must be 4, 8 or 16")) + } else { + Ok(value) + } +} + +fn parse_fri_max_remainder_size(value: &str) -> Result { + let value = value + .parse::() + .map_err(|e| Error::raw(ErrorKind::InvalidValue, format!("{}", e)))?; + + if !value.is_power_of_two() { + return Err(Error::raw( + ErrorKind::ValueValidation, + "must be a power of two", + )); + } + + match value { + 0..=31 => Err(Error::raw( + ErrorKind::ValueValidation, + "cannot be smaller than 32", + )), + 1025.. => Err(Error::raw( + ErrorKind::ValueValidation, + "cannot be more than 1024", + )), + _ => Ok(value), + } +} diff --git a/cli/src/cmd/prove/mod.rs b/cli/src/cmd/prove/mod.rs new file mode 100644 index 0000000..8f56ac7 --- /dev/null +++ b/cli/src/cmd/prove/mod.rs @@ -0,0 +1,4 @@ +mod args; +mod prove; + +pub use args::ProveArgs; diff --git a/cli/src/cmd/prove/prove.rs b/cli/src/cmd/prove/prove.rs new file mode 100644 index 0000000..51e6e85 --- /dev/null +++ b/cli/src/cmd/prove/prove.rs @@ -0,0 +1,47 @@ +use std::fs::File; +use std::io::Write; + +use super::ProveArgs; +use crate::{cmd::ProofData, utils::Cmd}; +use air::ProofOptions; +use runner::ExecutionTrace; +use winter_utils::Serializable; + +pub struct ProveOutput {} + +#[derive(Debug)] +pub enum Error {} + +impl Cmd for ProveArgs { + type Output = Result; + + fn run(self) -> Self::Output { + // Load trace from file + let trace = + ExecutionTrace::from_file(self.program, self.trace, self.memory, self.num_outputs); + + // Generate proof + let proof_options = ProofOptions::with_proof_options( + self.num_queries, + self.blowup_factor, + self.grinding_factor, + self.fri_folding_factor, + self.fri_max_remainder_size, + ); + let (proof, pub_inputs) = prover::prove_trace(trace, &proof_options).unwrap(); + let input_bytes = pub_inputs.to_bytes(); + let proof_bytes = proof.to_bytes(); + println!("Proof size: {:.1} KB", proof_bytes.len() as f64 / 1024f64); + + // Write proof to disk + let data = ProofData { + input_bytes, + proof_bytes, + }; + let b = bincode::serialize(&data).unwrap(); + let mut f = File::create(self.output).unwrap(); + f.write_all(&b).unwrap(); + + Ok(ProveOutput {}) + } +} diff --git a/cli/src/giza.rs b/cli/src/giza.rs index 44ab52e..79dd80e 100644 --- a/cli/src/giza.rs +++ b/cli/src/giza.rs @@ -3,8 +3,7 @@ mod utils; use crate::utils::Cmd; use clap::{Parser, Subcommand}; -use cmd::prove::ProveArgs; -use cmd::verify::VerifyArgs; +use cmd::{prove::ProveArgs, verify::VerifyArgs}; #[derive(Debug, Parser)] #[clap(name = "giza")] diff --git a/examples/src/main.rs b/examples/src/main.rs index a23291f..1c69389 100644 --- a/examples/src/main.rs +++ b/examples/src/main.rs @@ -48,7 +48,7 @@ fn main() { let trace = program.execute().unwrap(); // generate the proof of execution - let proof_options = ProofOptions::with_96_bit_security(); + let proof_options = ProofOptions::with_proof_options(None, None, None, None, None); let (proof, pub_inputs) = prover::prove_trace(trace, &proof_options).unwrap(); let proof_bytes = proof.to_bytes(); println!("Proof size: {:.1} KB", proof_bytes.len() as f64 / 1024f64); diff --git a/memory.bin b/memory.bin deleted file mode 100644 index e69de29..0000000 diff --git a/runner/src/cairo_interop.rs b/runner/src/cairo_interop.rs index c9de654..264e2d5 100644 --- a/runner/src/cairo_interop.rs +++ b/runner/src/cairo_interop.rs @@ -121,15 +121,15 @@ mod tests { #[test] fn test_trace_bin() { - let trace = read_trace_bin(PathBuf::from("../tmp/trace.bin")); + let trace = read_trace_bin(&PathBuf::from("../tmp/trace.bin")); println!("{:?}", trace); } #[test] fn test_memory_bin() { let mem = read_memory_bin( - PathBuf::from("../tmp/memory.bin"), - PathBuf::from("../tmp/program.json"), + &PathBuf::from("../tmp/memory.bin"), + &PathBuf::from("../tmp/program.json"), ); println!("{:?}", mem.data); }