Skip to content

feat(circuit_params): tool to report verifier circuit component sizes#398

Merged
ilyalesokhin-starkware merged 1 commit into
mainfrom
ilya/circuit-params-sizes
Jul 21, 2026
Merged

feat(circuit_params): tool to report verifier circuit component sizes#398
ilyalesokhin-starkware merged 1 commit into
mainfrom
ilya/circuit-params-sizes

Conversation

@ilyalesokhin-starkware

@ilyalesokhin-starkware ilyalesokhin-starkware commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

What

Adds a new circuit-params crate with a circuit-params binary that computes the leaf-prover verifier circuit's per-component sizes for the CANONICAL preprocessed trace config, across a range of verified Cairo trace sizes.

For each trace log size it prints, per AIR component (eq, qm31_ops, m31_to_u32, triple_xor, blake_g_gate):

  • the padded log size (log), and
  • the usage percentage (usage = non-padded rows / next_power_of_two, rounded to a whole percent).

It builds the verifier circuit topology only (NoValue, via build_cairo_verifier_circuit) — no proving — reusing get_pcs_config and the leaf prover's DISABLED_COMPONENTS_CANONICAL_PREPROCESSED component set.

Usage

cargo run -p circuit-params -- \
  --min-trace-log-size 25 \
  --max-trace-log-size 28 \
  --log_blowup_factor 1 \
  --output-path sizes.txt

Omit --output-path to print to stdout. --log_blowup_factor must be 1, 2, or 3 (passed to get_pcs_config).

Example output:

25: eq:(log: 20, usage = 60%) qm31_ops:(log: 23, usage = 72%) m31_to_u32:(log: 20, usage = 82%) triple_xor:(log: 19, usage = 84%) blake_g_gate:(log: 23, usage = 53%)
26: eq:(log: 20, usage = 60%) qm31_ops:(log: 23, usage = 72%) m31_to_u32:(log: 20, usage = 83%) triple_xor:(log: 19, usage = 85%) blake_g_gate:(log: 23, usage = 53%)
27: eq:(log: 20, usage = 60%) qm31_ops:(log: 23, usage = 73%) m31_to_u32:(log: 20, usage = 84%) triple_xor:(log: 19, usage = 86%) blake_g_gate:(log: 23, usage = 54%)
28: eq:(log: 20, usage = 60%) qm31_ops:(log: 23, usage = 73%) m31_to_u32:(log: 20, usage = 85%) triple_xor:(log: 19, usage = 88%) blake_g_gate:(log: 23, usage = 55%)

Each line is prefixed with the verified trace log size.

Notes

  • circuit-params depends on leaf-prover only to reuse the canonical disabled-components list; happy to move that constant instead if the dependency direction is undesirable.

🤖 Generated with Claude Code


This change is Reviewable

@cursor

cursor Bot commented Jul 20, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Developer tooling and a small refactor of verifier component construction; no change to proving or verification behavior on the hot path beyond using the shared helper.

Overview
Adds a circuit-params workspace crate and binary that measures how large the leaf-prover’s Cairo verifier circuit is for the canonical preprocessed trace, without proving anything. For each trace log size in a CLI range it builds the verifier topology via build_cairo_verifier_circuit, runs compute_padded_sizes, and prints per-AIR-component padded log size and usage % (raw rows vs padded power-of-two). Output can go to stdout or --output-path; --log_blowup_factor is forwarded to get_pcs_config.

leaf_prover now exposes LeafVerifierComponents and leaf_verifier_components(disabled_components) so the leaf prover and this tool share the same enabled/disabled Cairo component set (canonical list from DISABLED_COMPONENTS_CANONICAL_PREPROCESSED). A small integration test runs the binary for trace log size 25 and checks the expected line format.

Reviewed by Cursor Bugbot for commit 8e54217. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread crates/circuit_params/src/main.rs
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.72727% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.58%. Comparing base (53a5df7) to head (8e54217).

Files with missing lines Patch % Lines
crates/circuit_params/src/main.rs 97.29% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #398      +/-   ##
==========================================
+ Coverage   67.14%   67.58%   +0.44%     
==========================================
  Files          41       42       +1     
  Lines        5332     5411      +79     
==========================================
+ Hits         3580     3657      +77     
- Misses       1752     1754       +2     
Files with missing lines Coverage Δ
crates/leaf_prover/src/prove_leaf.rs 97.05% <100.00%> (+0.15%) ⬆️
crates/circuit_params/src/main.rs 97.29% <97.29%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

component("triple_xor", raw.triple_xor, padded.triple_xor),
component("blake_g_gate", raw.blake_g_gate, padded.blake_g_gate),
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output omits raw row counts

Medium Severity

The binary computes RawSizes for each AIR component but format_sizes only prints padded log and usage. The PR and crate docs describe emitting non-padded row counts per component, so stdout/file output is missing a primary reported field.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ce5906e. Configure here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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.

@YairVaknin-starkware YairVaknin-starkware left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@YairVaknin-starkware reviewed 5 files and all commit messages, and made 7 comments.
Reviewable status: all files reviewed, 7 unresolved discussions (waiting on ilyalesokhin-starkware).


crates/circuit_params/src/main.rs line 43 at r3 (raw file):

fn log_size(size: usize) -> u32 {
    size.next_power_of_two().ilog2()

doesn't the padding do this already?

Code quote:

next_power_of_two()

crates/circuit_params/src/main.rs line 48 at r3 (raw file):

/// The fraction (as a percentage) of the padded (power-of-two) component that is actually used.
fn usage_percent(size: usize) -> f64 {
    100.0 * size as f64 / size.next_power_of_two() as f64

isn't this basically the padded size (or do u not want to assume N_LANES isn't the max)?

Code quote:

size.next_power_of_two()

crates/circuit_params/src/main.rs line 100 at r3 (raw file):

            enabled_bits.push(true);
        }
    }

This logic too repeats a few times in our various crates. So centralize or add a TODO too.

Code quote:

    let mut cairo_components: IndexMap<&'static str, Box<dyn CircuitEval<QM31>>> =
        IndexMap::default();
    let mut enabled_bits = vec![];
    for (name, component) in all_components::<QM31>() {
        if DISABLED_COMPONENTS_CANONICAL_PREPROCESSED.contains(&name) {
            enabled_bits.push(false);
        } else {
            cairo_components.insert(name, component);
            enabled_bits.push(true);
        }
    }

crates/circuit_params/src/main.rs line 132 at r3 (raw file):

        + circuit.mul.len()
        + circuit.pointwise_mul.len()
        + circuit.permutation.iter().map(|p| p.inputs.len() + p.outputs.len()).sum::<usize>();

Can you make the func calcing that from stwo-circuits pub or add a TODO for doing it in the mono repo?

Code quote:

    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>();

crates/circuit_params/src/main.rs line 154 at r3 (raw file):

        .map(|trace_log_size| {
            let (raw, padded) =
                leaf_verifier_component_sizes(trace_log_size, args.log_blowup_factor);

let's also allow a range for blowup factors (min_bu..=max_bu)

Code quote:

args.log_blowup_factor

crates/circuit_params/tests/cli_test.rs line 5 at r3 (raw file):

/// Runs the `circuit-params` binary for a single trace log size and checks it prints one info line.
#[test]
fn run_circuit_params_binary() {

Can this test write to a flie with a FIX logic?

Code quote:

fn run_circuit_params_binary() {

component("triple_xor", raw.triple_xor, padded.triple_xor),
component("blake_g_gate", raw.blake_g_gate, padded.blake_g_gate),
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about this?

component("triple_xor", raw.triple_xor, padded.triple_xor),
component("blake_g_gate", raw.blake_g_gate, padded.blake_g_gate),
)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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.

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_params/tests/cli_test.rs line 5 at r3 (raw file):

Previously, YairVaknin-starkware wrote…

Can this test write to a flie with a FIX logic?

I don't want yet another file that changes on every PR.

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_params/src/main.rs line 154 at r3 (raw file):

Previously, YairVaknin-starkware wrote…

let's also allow a range for blowup factors (min_bu..=max_bu)

What is the use case?

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_params/src/main.rs line 43 at r3 (raw file):

Previously, YairVaknin-starkware wrote…

doesn't the padding do this already?

removed.

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_params/src/main.rs line 132 at r3 (raw file):

Previously, YairVaknin-starkware wrote…

Can you make the func calcing that from stwo-circuits pub or add a TODO for doing it in the mono repo?

It is currently not public.

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_params/src/main.rs line 48 at r3 (raw file):

Previously, YairVaknin-starkware wrote…

isn't this basically the padded size (or do u not want to assume N_LANES isn't the max)?

done.

@ilyalesokhin-starkware ilyalesokhin-starkware left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ilyalesokhin-starkware made 1 comment.
Reviewable status: 4 of 6 files reviewed, 6 unresolved discussions (waiting on YairVaknin-starkware).


crates/circuit_params/src/main.rs line 100 at r3 (raw file):

Previously, YairVaknin-starkware wrote…

This logic too repeats a few times in our various crates. So centralize or add a TODO too.

Done.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f546396. Configure here.

+ circuit.sub.len()
+ circuit.mul.len()
+ circuit.pointwise_mul.len()
+ circuit.permutation.iter().map(|p| p.inputs.len() + p.outputs.len()).sum::<usize>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong qm31_ops usage metric

Medium Severity

The qm31_ops usage percentage pairs a hand-rolled raw count (sums of add/sub/mul/pointwise_mul lengths plus permutation input/output counts) with padded.qm31_ops from compute_padded_sizes, which uses the library’s row model (see the nearby TODO for qm31_ops_n_rows). That mismatch makes reported qm31_ops usage and log lines unreliable for sizing decisions.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f546396. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both compute qm31_ops_n_rows in the same way

@YairVaknin-starkware YairVaknin-starkware left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@YairVaknin-starkware reviewed 2 files and all commit messages, made 2 comments, and resolved 6 discussions.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on ilyalesokhin-starkware).


crates/circuit_params/src/main.rs line 154 at r3 (raw file):

Previously, ilyalesokhin-starkware wrote…

What is the use case?

To print them all at once, but up to you if unnecessary.

+ circuit.sub.len()
+ circuit.mul.len()
+ circuit.pointwise_mul.len()
+ circuit.permutation.iter().map(|p| p.inputs.len() + p.outputs.len()).sum::<usize>();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both compute qm31_ops_n_rows in the same way

…izes

Add a `circuit-params` crate with a binary that builds the leaf-prover
verifier circuit (CANONICAL preprocessed trace + its component set) for a
range of verified trace sizes and prints each AIR component's non-padded
row count, padded log size, and usage percentage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@ilyalesokhin-starkware ilyalesokhin-starkware left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ilyalesokhin-starkware resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on ilyalesokhin-starkware).

ilyalesokhin-starkware commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

@ilyalesokhin-starkware
ilyalesokhin-starkware merged commit 764b6fb into main Jul 21, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants