Skip to content

feat: EVM verify optionally verifies app commit + CLI vk paths#2884

Merged
stephenh-axiom-xyz merged 3 commits into
develop-v2.0.0-rc.2from
feat/cli-vk-paths-optional-commit
Jun 15, 2026
Merged

feat: EVM verify optionally verifies app commit + CLI vk paths#2884
stephenh-axiom-xyz merged 3 commits into
develop-v2.0.0-rc.2from
feat/cli-vk-paths-optional-commit

Conversation

@stephenh-axiom-xyz

Copy link
Copy Markdown
Contributor

Resolves INT-5100 and INT-4826.

Overview

This PR adds two related capabilities:

  1. Optional app-commit checking during EVM verification. Sdk::verify_evm_halo2_proof now takes an optional expected AppExecutionCommit. When provided, it asserts the commit embedded in the proof matches the expected app/exe commits before running the on-chain verifier. The CLI's verify evm subcommand exposes this via a new --app-commit flag.

  2. Decoupling CLI verification from proving keys. cargo openvm setup now also writes the standalone internal-recursive verifying key, and verify stark reads that vk directly (via a new --agg-vk flag) instead of loading the much larger proving key just to derive the vk. The verify evm subcommand also gains an --evm-verifier flag to point at a custom verifier directory.

The change is split across the SDK (openvm-sdk) and the CLI (cargo-openvm), plus mechanical call-site updates in benchmarks/examples/tests for the new verify_evm_halo2_proof signature.


SDK changes (crates/sdk)

New Sdk::app_commit helper — src/lib.rs

Adds a public method that produces the AppExecutionCommit (the app_exe_commit + app_vm_commit pair) for a given executable, generating the app proving key if needed. This gives callers a convenient way to obtain the expected commit to pass into verification.

verify_evm_halo2_proof signature — src/lib.rs

Adds an expected_app_commit: Option<AppExecutionCommit> parameter. When Some, it compares against evm_proof.app_commit and returns an error ("mismatching app commits") on mismatch before delegating to the existing solidity verifier path. None preserves the old behavior.

AppExecutionCommit now comparable — src/types.rs

Derives PartialEq, Eq so the equality check above is possible.

Error message cleanup — src/solidity.rs

Renames the internal verification error prefix from "Sdk::verify_openvm_evm_proof" to the user-facing "EVM proof verification failed".

Updated call sites (signature change)

  • src/examples/sdk_evm.rs — passes None, with a comment showing how to pass Some(sdk.app_commit(elf)?).
  • src/tests.rstest_sdk_fibonacci now computes sdk.app_commit(...) and passes Some(app_commit), exercising the new path.

CLI changes (crates/cli)

New default vk path — src/default.rs

Adds default_internal_recursive_vk_path()~/.openvm/internal_recursive.vk.

setup also writes the vk — src/commands/setup.rs

After writing the internal-recursive proving key, setup now also extracts its verifying key and writes it to the new .vk path. This is what lets verify stark avoid loading the full proving key.

verify starksrc/commands/verify.rs

  • New --agg-vk <PATH> flag. Defaults to the default_internal_recursive_vk_path() written by setup.
  • Reads the aggregation verifying key directly from that path, replacing the previous logic that loaded the internal-recursive proving key and called .get_vk() on it. (Removes the MultiStarkProvingKey / SC imports that were only needed for that.)

verify evmsrc/commands/verify.rs

  • New --evm-verifier <PATH> flag to override the default ~/.openvm/halo2/ verifier directory.
  • New --app-commit [<PATH>] flag (0-or-1 value):
    • omitted → no commit check (None);
    • present with no value → resolves the default .commit.json path for the cargo target;
    • present with a path → reads that explicit .commit.json.
    • The resolved AppExecutionCommit is passed into Sdk::verify_evm_halo2_proof.
  • Adds #[command(flatten)] cargo_args: SingleTargetCargoArgs so the target can be located for the default commit-path resolution.
  • Minor: corrects the "verifier not found" hint to mention cargo openvm setup --evm.

@github-actions

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@shuklaayush

Copy link
Copy Markdown
Collaborator

@claude can you check if any docs need to be updated

@claude

claude Bot commented Jun 12, 2026

Copy link
Copy Markdown

Claude finished @shuklaayush's task in 2m 21s —— View job


Checking if docs need updating

  • Search for documentation files referencing affected CLI commands and SDK APIs
  • Review doc content for outdated information
  • Report findings

Findings

I found two doc files with text that should be updated to reflect the changes in this PR:


1. docs/vocs/docs/pages/book/writing-apps/verifying-proofs.mdx (lines 40-42)

Current (outdated):

The `cargo openvm verify stark` command implicitly reads `~/.openvm/internal_recursive.pk` from
`cargo openvm setup` and derives the aggregation verification key from it.

Issue: verify stark now reads the verifying key directly (~/.openvm/internal_recursive.vk via the new --agg-vk flag) instead of loading the proving key and deriving the vk. This info box should be updated.

Also, the verify evm section (lines 57-64) doesn't mention the new --evm-verifier or --app-commit flags. Not strictly wrong (it still works as documented), but the new flags could be worth documenting.


2. docs/vocs/docs/pages/book/writing-apps/generating-proofs.mdx (lines 62-97)

The "STARK and EVM Key Generation" section describes what cargo openvm setup writes:

  • Line 68: Says it "writes the internal-recursive aggregation proving key" — should also mention it now writes the verifying key too.
  • Line 82: File list only shows internal_recursive.pk — should add internal_recursive.vk.
  • Line 95: Only describes internal_recursive.pk — should add a line for internal_recursive.vk.

Not affected (no changes needed)

  • docs/vocs/docs/pages/book/advanced-usage/sdk.mdx: The EVM verification code block is included via // [!include ~/snippets/examples_sdk/sdk_evm.rs:evm_verification], which symlinks to crates/sdk/examples/sdk_evm.rs. That file is already updated in this PR (passes None with a comment about Some(app_commit)), so the docs will auto-update.
  • CHANGELOG.md: Already mentions the agg.vk / agg.pk change (line 105) — but note this is under v1.4.0, not under Unreleased. You may want to add a changelog entry under ## Unreleased for the new CLI flags (--agg-vk, --evm-verifier, --app-commit) and the verify_evm_halo2_proof signature change.
  • crates/verify/README.md, crates/continuations/README.md: Reference internal_recursive only in the context of aggregation layer naming, not the CLI file paths — no changes needed.
  • docs/crates/benchmarks.md, docs/crates/metrics.md: Not affected.

Comment thread crates/cli/src/default.rs
}

pub fn default_internal_recursive_vk_path() -> String {
env::var("HOME").unwrap() + "/.openvm/internal_recursive.vk"

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.

will this change, if say we do openvm 2.1 release? how will we know if we need to regenerate 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.

Should probably always re-keygen on any major release, ex. 2.0 -> 2.1 (but probably not 2.0.0 -> 2.0.1, as this wouldn't require a circuit change)

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.

ok so setup is actually per machine / per openvm minor version right

#[arg(
long,
num_args = 0..=1,
help = "Check the commit embedded in the proof against an expected app commit. With no value, uses the default commit path for the target; or pass an explicit path to a .commit.json",

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.

can you explain the difference in meaning between Some(None) v.s. None

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.

None doesn't do the check, Some(None) does the check using the default app_commit path, Some(Some(path_to_app_commit)) does the check using path_to_app_commit

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.

yea, i meant updating the help text there

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.

Ah shoot, somehow these responses didn't buffer on my browser and I merged… will add this in a future PR

@github-actions

Copy link
Copy Markdown
group app.proof_time_ms app.cycles leaf.proof_time_ms
fibonacci 3,926 12,000,265 1,134
keccak 21,792 18,655,329 4,619
sha2_bench 9,595 14,793,960 1,852
regex 1,496 4,137,067 429
ecrecover 610 123,583 288
pairing 939 1,745,757 306
kitchen_sink 4,175 2,579,903 888

Note: cells_used metrics omitted because CUDA tracegen does not expose unpadded trace heights.

Commit: a8a5a80

Benchmark Workflow

@stephenh-axiom-xyz stephenh-axiom-xyz merged commit 2009dbc into develop-v2.0.0-rc.2 Jun 15, 2026
40 checks passed
@stephenh-axiom-xyz stephenh-axiom-xyz deleted the feat/cli-vk-paths-optional-commit branch June 15, 2026 15:04
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.

3 participants