-
Notifications
You must be signed in to change notification settings - Fork 9
feat(circuit_params): tool to report verifier circuit component sizes #398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| [package] | ||
| name = "circuit-params" | ||
| version.workspace = true | ||
| edition.workspace = true | ||
| license.workspace = true | ||
| description = "Compute the leaf-prover verifier circuit's per-component sizes for a range of trace sizes" | ||
|
|
||
| [dependencies] | ||
| clap.workspace = true | ||
| indexmap = { version = "2.10.0", default-features = false, features = ["std"] } | ||
|
|
||
| leaf-prover.workspace = true | ||
|
|
||
| cairo-air.workspace = true | ||
| circuit-cairo-verifier.workspace = true | ||
| circuits-stark-verifier.workspace = true | ||
| circuit-common.workspace = true | ||
| stwo-cairo-common.workspace = true | ||
| stwo-cairo-prover.workspace = true | ||
| stwo-cairo-utils.workspace = true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| //! Computes the leaf-prover verifier circuit's per-component sizes for the CANONICAL preprocessed | ||
| //! trace config, across a range of verified trace sizes, and writes them as text. | ||
|
|
||
| use std::path::PathBuf; | ||
| use std::process::ExitCode; | ||
| use std::sync::Arc; | ||
|
|
||
| use cairo_air::verifier::INTERACTION_POW_BITS; | ||
| use circuit_cairo_verifier::privacy::get_pcs_config; | ||
| use circuit_cairo_verifier::statement::MEMORY_VALUES_LIMBS; | ||
| use circuit_cairo_verifier::verify::{CairoVerifierConfig, build_cairo_verifier_circuit}; | ||
| use circuit_common::finalize::{ComponentSizes, compute_padded_sizes}; | ||
| use circuits_stark_verifier::proof::ProofConfig; | ||
| use clap::Parser; | ||
| use leaf_prover::consts::DISABLED_COMPONENTS_CANONICAL_PREPROCESSED; | ||
| use leaf_prover::prove_leaf::{LeafVerifierComponents, leaf_verifier_components}; | ||
| use stwo_cairo_common::preprocessed_columns::preprocessed_trace::PreProcessedTraceVariant; | ||
| use stwo_cairo_common::prover_types::cpu::M31; | ||
| use stwo_cairo_utils::binary_utils::run_binary; | ||
|
|
||
| #[derive(Parser)] | ||
| struct Args { | ||
| /// Path to write the output to. If omitted, prints to stdout. | ||
| #[clap(long)] | ||
| output_path: Option<PathBuf>, | ||
| /// Smallest verified trace log size to measure (inclusive). A canonical Cairo trace commits | ||
| /// its preprocessed sequence columns at `MAX_SEQUENCE_LOG_SIZE = 25`, so a real canonical | ||
| /// leaf proof has `log_trace_size >= 25`. | ||
| #[clap(long)] | ||
| min_trace_log_size: u32, | ||
| /// Largest verified trace log size to measure (inclusive). | ||
| #[clap(long)] | ||
| max_trace_log_size: u32, | ||
| /// Log blowup factor of the verified Cairo proof (1, 2, or 3), passed to `get_pcs_config`. | ||
| #[clap(long = "log_blowup_factor", default_value_t = 1)] | ||
| log_blowup_factor: u32, | ||
| } | ||
|
|
||
| /// The fraction (as a percentage) of the padded (power-of-two) component that is actually used. | ||
| fn usage_percent(size: usize, padded_size: usize) -> f64 { | ||
| 100.0 * size as f64 / padded_size as f64 | ||
| } | ||
|
|
||
| /// The raw (non-padded) row count of each AIR component. | ||
| struct RawSizes { | ||
| eq: usize, | ||
| qm31_ops: usize, | ||
| m31_to_u32: usize, | ||
| triple_xor: usize, | ||
| blake_g_gate: usize, | ||
| } | ||
|
|
||
| /// One line with each component's padded log size and usage (fraction of the padded power-of-two | ||
| /// that the non-padded rows fill). | ||
| fn format_sizes(raw: &RawSizes, padded: &ComponentSizes) -> String { | ||
| let component = |name: &str, raw_size: usize, padded_size: usize| { | ||
| format!( | ||
| "{name}:(log: {}, usage = {:.0}%)", | ||
| padded_size.ilog2(), | ||
| usage_percent(raw_size, padded_size), | ||
| ) | ||
| }; | ||
| format!( | ||
| "{} {} {} {} {}", | ||
| component("eq", raw.eq, padded.eq), | ||
| component("qm31_ops", raw.qm31_ops, padded.qm31_ops), | ||
| component("m31_to_u32", raw.m31_to_u32, padded.m31_to_u32), | ||
| component("triple_xor", raw.triple_xor, padded.triple_xor), | ||
| component("blake_g_gate", raw.blake_g_gate, padded.blake_g_gate), | ||
| ) | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Output omits raw row countsMedium Severity The binary computes Reviewed by Cursor Bugbot for commit ce5906e. Configure here.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we care about this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I fixed the doc, I think the usage percentage is more useful than the actual number. |
||
|
|
||
| /// Builds the leaf-prover verifier circuit topology (with the CANONICAL preprocessed trace and its | ||
| /// component set) for a verified Cairo proof whose trace has the given log size, and returns the | ||
| /// non-padded row counts and padded sizes of its AIR components. | ||
| fn leaf_verifier_component_sizes( | ||
| trace_log_size: u32, | ||
| log_blowup_factor: u32, | ||
| ) -> (RawSizes, ComponentSizes) { | ||
| let preprocessed_trace_variant = PreProcessedTraceVariant::Canonical; | ||
|
|
||
| // The Cairo-proof PCS config the leaf prover uses (canonical preprocessed). | ||
| let pcs_config = get_pcs_config(trace_log_size, log_blowup_factor); | ||
|
|
||
| let LeafVerifierComponents { components: cairo_components, enabled_bits } = | ||
| leaf_verifier_components(&DISABLED_COMPONENTS_CANONICAL_PREPROCESSED); | ||
|
|
||
| let proof_config = ProofConfig::new( | ||
| &cairo_components, | ||
| preprocessed_trace_variant.n_columns(), | ||
| &pcs_config, | ||
| INTERACTION_POW_BITS, | ||
| ); | ||
|
|
||
| // Program length and output count are held fixed for this measurement; only the trace size | ||
| // varies. The preprocessed root value is irrelevant for the [NoValue] topology. | ||
| let program: Arc<[[M31; MEMORY_VALUES_LIMBS]]> = | ||
| std::iter::repeat_n([M31::from(0u32); MEMORY_VALUES_LIMBS], 128).collect(); | ||
|
|
||
| let verifier_config = CairoVerifierConfig { | ||
| proof_config, | ||
| enabled_bits, | ||
| program, | ||
| n_outputs: 1, | ||
| preprocessed_root: [0u32; 8].into(), | ||
| preprocessed_trace_variant, | ||
| }; | ||
|
|
||
| let context = build_cairo_verifier_circuit(&verifier_config); | ||
| let padded = compute_padded_sizes(&context); | ||
|
|
||
| // Non-padded row counts, mirroring `compute_padded_sizes` before its power-of-two rounding. | ||
| let circuit = context.circuit(); | ||
| // TODO(ilya): Use `qm31_ops_n_rows` instead of counting the operations manually. | ||
| let qm31_ops = circuit.add.len() | ||
| + circuit.sub.len() | ||
| + circuit.mul.len() | ||
| + circuit.pointwise_mul.len() | ||
| + circuit.permutation.iter().map(|p| p.inputs.len() + p.outputs.len()).sum::<usize>(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong qm31_ops usage metricMedium Severity The Reviewed by Cursor Bugbot for commit f546396. Configure here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. both compute |
||
| let raw = RawSizes { | ||
| eq: circuit.eq.len(), | ||
| qm31_ops, | ||
| m31_to_u32: circuit.m31_to_u32.len(), | ||
| triple_xor: circuit.triple_xor.len(), | ||
| blake_g_gate: circuit.blake_g_gate.len(), | ||
| }; | ||
|
|
||
| (raw, padded) | ||
| } | ||
|
|
||
| fn main() -> ExitCode { | ||
| run_binary(run, "circuit_params") | ||
| } | ||
|
|
||
| fn run() -> Result<(), String> { | ||
| let args = Args::parse(); | ||
|
|
||
| let output = (args.min_trace_log_size..=args.max_trace_log_size) | ||
| .map(|trace_log_size| { | ||
| let (raw, padded) = | ||
| leaf_verifier_component_sizes(trace_log_size, args.log_blowup_factor); | ||
| format!("{}: {}", trace_log_size, format_sizes(&raw, &padded)) | ||
| }) | ||
| .collect::<Vec<_>>() | ||
| .join("\n"); | ||
|
|
||
| match args.output_path { | ||
| Some(path) => std::fs::write(&path, format!("{output}\n")) | ||
| .map_err(|err| format!("Cannot write output to {}: {err}", path.display()))?, | ||
| None => println!("{output}"), | ||
| } | ||
| Ok(()) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| use std::process::Command; | ||
|
|
||
| /// Runs the `circuit-params` binary for a single trace log size and checks it prints one info line. | ||
| #[test] | ||
| fn run_circuit_params_binary() { | ||
| let binary = env!("CARGO_BIN_EXE_circuit-params"); | ||
| let output = Command::new(binary) | ||
| .args(["--min-trace-log-size", "25", "--max-trace-log-size", "25"]) | ||
| .output() | ||
| .expect("Cannot run circuit-params"); | ||
|
|
||
| assert!( | ||
| output.status.success(), | ||
| "binary exited with status {}: {}", | ||
| output.status, | ||
| String::from_utf8_lossy(&output.stderr) | ||
| ); | ||
|
|
||
| let stdout = String::from_utf8(output.stdout).expect("stdout is not valid UTF-8"); | ||
| assert!( | ||
| stdout.contains("25: eq:(log:") && stdout.contains("blake_g_gate:(log:"), | ||
| "unexpected output: {stdout}" | ||
| ); | ||
| } |


Uh oh!
There was an error while loading. Please reload this page.