Skip to content

feat(circuit-verifier): mix circuit hash into the channel. - #648

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

ilyalesokhin-starkware merged 1 commit into
mainfrom
ilya/mix-circuit-hash

Conversation

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor

Mix blake2s(config_words || preprocessed_root) into the channel before the
output values, on both the prover (mix_public_inputs) and the in-circuit
verifier (CircuitStatement::claims_to_mix), so the transcript commits to the
circuit's identity. Add the host twin compute_circuit_hash_host and replace the
CircuitClaim::mix_into method with a free mix_public_inputs function shared by
the prover and out-of-circuit verifier.

Regenerate the affected multiverifier and privacy proof fixtures.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

@cursor

cursor Bot commented Jul 13, 2026 •

Copy link
Copy Markdown

PR Summary

High Risk
Changes Fiat-Shamir public-input ordering and transcript binding for all circuit proofs; any prover/verifier mismatch or stale fixtures would break verification, including recursive multiverifier setups.

Overview
Transcript now binds to circuit identity by hashing FRI blowup, per-component log sizes, and the preprocessed Merkle root, then mixing that digest into the Fiat-Shamir channel before output values.

The prover adds a host compute_circuit_hash (mirrored by in-circuit logic) and calls mix_circuit_hash right after the preprocessed trace is committed. In-circuit verification recomputes the same hash in CircuitStatement and feeds it through claims_to_mix ahead of the output words so host and recursive verifier stay aligned. A regression test asserts host vs in-circuit digests match.

Multiverifier MULTIVERIFIER_PREPROCESSED_ROOT and related proof fixtures are updated for the new transcript; backward-compatibility test comments no longer pin a specific commit hash.

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

@reviewable-StarkWare

Copy link
Copy Markdown
Collaborator

This change is Reviewable

ilyalesokhin-starkware commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor Author

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

test_data/circuit_multiverifier/proof.bin at r2 (raw file):
@yuvalsw the proof chaned because I've mixex the circuit-hash into the channel.

I think that it is a good practice.

@yuvalsw yuvalsw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@yuvalsw reviewed all commit messages and made 1 comment.
Reviewable status: 0 of 10 files reviewed, 2 unresolved discussions (waiting on Gali-StarkWare and ilyalesokhin-starkware).


-- commits line 13 at r3:
what is out-of-circuit verifier?
"Regenerate the affected multiverifier and privacy proof fixtures" - redundant.

Add the host twin compute_circuit_hash_host and replace the
CircuitClaim::mix_into method with a free mix_public_inputs function shared by
the prover and out-of-circuit verifier.
Aren't these refactors that should be split into an earlier commit?

Code quote:

- 5f36cf9: feat(circuit-verifier): mix circuit hash into the channel.

  Mix blake2s(config_words || preprocessed_root) into the channel before the
  output values, on both the prover (mix_public_inputs) and the in-circuit
  verifier (CircuitStatement::claims_to_mix), so the transcript commits to the
  circuit's identity. Add the host twin compute_circuit_hash_host and replace the
  CircuitClaim::mix_into method with a free mix_public_inputs function shared by
  the prover and out-of-circuit verifier.

  Regenerate the affected multiverifier and privacy proof fixtures.

  Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

-- commits line 13 at r3:

Previously, yuvalsw wrote…

what is out-of-circuit verifier?
"Regenerate the affected multiverifier and privacy proof fixtures" - redundant.

Add the host twin compute_circuit_hash_host and replace the
CircuitClaim::mix_into method with a free mix_public_inputs function shared by
the prover and out-of-circuit verifier.
Aren't these refactors that should be split into an earlier commit?

out-of-circuit is the non-circuit rust verifier.

@Gali-StarkWare Gali-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.

@Gali-StarkWare reviewed 7 files and all commit messages, and made 2 comments.
Reviewable status: 7 of 12 files reviewed, 4 unresolved discussions (waiting on ilyalesokhin-starkware and yuvalsw).


crates/circuit_multiverifier/src/backward_compatibility_test.rs line 29 at r5 (raw file):

/// An older Cairo verifier proof, produced at commit f5cd0f7a (that version's `proof_cairo.bin`).
const BACKWARD_COMPATIBILITY_CAIRO_PROOF_PATH: &str = concat!(
    env!("CARGO_MANIFEST_DIR"),

Commit id?

Code quote:

/// The preprocessed root of the Cairo verifier circuit as it was at commit f5cd0f7a.
const BACKWARD_COMPATIBILITY_CAIRO_VERIFIER_PREPROCESSED_ROOT: [u32; 8] =
    [695775592, 831947430, 3864682957, 1778749033, 1073148880, 3248306553, 1968525874, 3767461582];
/// The output values of the Cairo verifier circuit as it was at commit f5cd0f7a.
/// TODO(ilya): consider removing this and using the output values from the current Cairo verifier
/// proof when breaking backwards compatibility.
const BACKWARD_COMPATIBILITY_CAIRO_VERIFIER_OUTPUT_VALUES: [u32; 8] =
    [3035180123, 3555538090, 587798257, 1881776298, 3385462846, 2102605012, 3369268656, 403460632];
/// An older Cairo verifier proof, produced at commit f5cd0f7a (that version's `proof_cairo.bin`).
const BACKWARD_COMPATIBILITY_CAIRO_PROOF_PATH: &str = concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/../../test_data/circuit_multiverifier/backward_compatibility_cairo_proof.bin"
);

crates/circuit_multiverifier/src/backward_compatibility_test.rs line 34 at r5 (raw file):

///
/// Checks that the multiverifier can verify, in the same circuit, both a Cairo verifier proof in
/// slot 0 and a multiverifier proof in slot 1.

Why the doc change?

Code quote:

/// Multi-input regression test.
///
/// Checks that the multiverifier can verify, in the same circuit, both a Cairo verifier proof in
/// slot 0 and a multiverifier proof in slot 1.

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_multiverifier/src/backward_compatibility_test.rs line 29 at r5 (raw file):

Previously, Gali-StarkWare wrote…

Commit id?

I fixed the proof to be the one from this commit, so I can't put it in the comment.
I'm not sure how to update the proof in the case that we fix it.

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_multiverifier/src/backward_compatibility_test.rs line 34 at r5 (raw file):

Previously, Gali-StarkWare wrote…

Why the doc change?

fixed.

@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 and resolved 1 discussion.
Reviewable status: 7 of 12 files reviewed, 4 unresolved discussions (waiting on Gali-StarkWare and yuvalsw).


test_data/circuit_multiverifier/backward_compatibility_cairo_proof.bin at r4 (raw file):
Proof has been

@Gali-StarkWare Gali-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.

@Gali-StarkWare partially reviewed 5 files and made 4 comments.
Reviewable status: 11 of 12 files reviewed, 8 unresolved discussions (waiting on ilyalesokhin-starkware and yuvalsw).


crates/circuit_prover/src/prover.rs line 149 at r5 (raw file):

    // Preprocessed trace.
    commitment_scheme.commit_tree(preprocessed_tree, channel);

Suggestion:

    // Preprocessed trace.
    let preprocessed_root: HashValue<QM31> = preprocessed_tree.commitment.root().into();
    commitment_scheme.commit_tree(preprocessed_tree, channel);

crates/circuit_prover/src/prover.rs line 167 at r5 (raw file):

        &preprocessed_root,
    );
    mix_public_inputs(channel, &claim, &circuit_hash);

I think that's a bit weird, no?

Code quote:

    let circuit_hash = compute_circuit_hash_host(
        &component_log_sizes,
        pcs_config.fri_config.log_blowup_factor,
        &preprocessed_root,
    );
    mix_public_inputs(channel, &claim, &circuit_hash);

crates/circuit_verifier/src/circuit_claim.rs line 31 at r5 (raw file):

    claim: &CircuitClaim,
    circuit_hash: &Blake2sHash,
) {

why not just add a params to the mix_into func?

Suggestion:

/// Mixes the circuit's public inputs into the channel.
pub fn mix_into(
    &self
    channel: &mut impl Channel,
    circuit_hash: &Blake2sHash,
) {

crates/circuit_verifier/src/statement.rs line 110 at r5 (raw file):

        let circuit_hash_words = self.circuit_hash.iter().copied().collect_vec();
        let output_words = unpack_qm31s_to_u32_words(context, self.output_values.iter().copied());
        vec![circuit_hash_words, output_words]

Keep the comments

Code quote:

        let circuit_hash_words = self.circuit_hash.iter().copied().collect_vec();
        let output_words = unpack_qm31s_to_u32_words(context, self.output_values.iter().copied());
        vec![circuit_hash_words, output_words]

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_prover/src/prover.rs line 167 at r5 (raw file):

Previously, Gali-StarkWare wrote…

I think that's a bit weird, no?

What is weird about it?

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_verifier/src/circuit_claim.rs line 31 at r5 (raw file):

Previously, Gali-StarkWare wrote…

why not just add a params to the mix_into func?

I think that making it a member function of the claim is weird.

@ilyalesokhin-starkware

Copy link
Copy Markdown
Contributor Author

crates/circuit_verifier/src/statement.rs line 110 at r5 (raw file):

Previously, Gali-StarkWare wrote…

Keep the comments

What information does it add?

@ilyalesokhin-starkware
ilyalesokhin-starkware changed the base branch from graphite-base/648 to ilya/compute-circuit-hash July 21, 2026 09:26

@Gali-StarkWare Gali-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.

@Gali-StarkWare reviewed 5 files and all commit messages.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on yuvalsw).

@ilyalesokhin-starkware
ilyalesokhin-starkware changed the base branch from ilya/compute-circuit-hash to graphite-base/648 July 21, 2026 09:58
@ilyalesokhin-starkware
ilyalesokhin-starkware changed the base branch from graphite-base/648 to ilya/compute-circuit-hash July 21, 2026 09:59

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

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 13d60e4. Configure here.

Comment thread crates/circuit_prover/src/circuit_hash.rs Outdated

@Gali-StarkWare Gali-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.

@Gali-StarkWare reviewed 1 file and all commit messages.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on yuvalsw).

@ilyalesokhin-starkware
ilyalesokhin-starkware changed the base branch from ilya/compute-circuit-hash to graphite-base/648 July 21, 2026 11:53
@graphite-app
graphite-app Bot changed the base branch from graphite-base/648 to main July 21, 2026 11:53

@yuvalsw yuvalsw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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


-- commits line 13 at r3:

Previously, ilyalesokhin-starkware wrote…

I don't consider adding an unused function as a refactor.

discussed f2f. it's not a refactor. resolving.

@Gali-StarkWare Gali-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.

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

Mix blake2s(config_words || preprocessed_root) into the channel before the
output values.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@OmriEshhar1 OmriEshhar1 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.

@OmriEshhar1 reviewed 14 files and all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on yuvalsw).

@OmriEshhar1 OmriEshhar1 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.

Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on yuvalsw).

@OmriEshhar1 OmriEshhar1 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.

Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on yuvalsw).

@yuvalsw yuvalsw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

.

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

@yuvalsw yuvalsw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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

@yuvalsw yuvalsw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

.

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

@yuvalsw yuvalsw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

.

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

@ilyalesokhin-starkware
ilyalesokhin-starkware merged commit c42b562 into main Jul 21, 2026
13 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.

5 participants