Skip to content

fix(zk): source intermediate root interval from on-chain like TEE#2433

Open
mw2000 wants to merge 4 commits intomainfrom
fix/zk-intermediate-root-interval
Open

fix(zk): source intermediate root interval from on-chain like TEE#2433
mw2000 wants to merge 4 commits intomainfrom
fix/zk-intermediate-root-interval

Conversation

@mw2000
Copy link
Copy Markdown
Contributor

@mw2000 mw2000 commented Apr 28, 2026

Summary

The ZK prover hardcoded DEFAULT_INTERMEDIATE_ROOT_INTERVAL = 10, but the on-chain AggregateVerifier may use a different value (e.g. 30 on Sepolia). This mismatch causes ZK challenge proofs to fail verification.

Fix

Collapse to a single source matching the TEE — chain → ProofRequest → BootInfo → executor:

  • Validity binary reads INTERMEDIATE_BLOCK_INTERVAL on startup (DGF → impl → AggregateVerifier) and threads it into ProofRequest.intermediate_block_interval.
  • Host preimage server answers boot key 9 with the on-chain value.
  • Both the SP1 range program and the native WitnessExecutor now read the interval from BootInfo, the same channel the TEE enclave uses.
  • Falls back to DEFAULT_INTERMEDIATE_ROOT_INTERVAL only when DGF is unset or the chain read fails.

Removed (now redundant)

  • INTERMEDIATE_ROOT_INTERVAL env var
  • SP1 stdin scalar (host write + guest read)
  • Interval params on WitnessExecutor::run and WitnessGenerator::get_sp1_stdin

Notes

  • Range ELF source changed → rebuild once and update range_vkey_commitment. The ELF then accepts any on-chain interval without rebuilding (interval is data, not code).
  • Aggregation program is unchanged.

@cb-heimdall
Copy link
Copy Markdown
Collaborator

cb-heimdall commented Apr 28, 2026

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 1
Sum 2

@mw2000 mw2000 changed the title fix(proof): wire intermediate root interval through ZK prover pipeline fix(zk): wire intermediate root interval through ZK prover pipeline Apr 28, 2026
@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from 1a9ed2b to 0c05242 Compare April 28, 2026 22:05
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
base Ignored Ignored Preview Apr 29, 2026 9:57pm

Request Review

Comment thread crates/proof/succinct/utils/ethereum/host/src/host.rs Outdated
Comment thread crates/proof/zk/service/src/worker/prover_worker_pool.rs Outdated
@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from 0c05242 to 979210a Compare April 28, 2026 23:34
Comment thread crates/proof/zk/service/src/backends/network.rs
@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from 979210a to febef35 Compare April 29, 2026 00:47
@mw2000 mw2000 changed the title fix(zk): wire intermediate root interval through ZK prover pipeline fix(zk): source intermediate root interval from on-chain like TEE Apr 29, 2026
Comment thread crates/proof/succinct/validity/bin/validity.rs Outdated
Comment thread crates/proof/succinct/validity/bin/validity.rs Outdated
Comment thread crates/proof/succinct/validity/bin/validity.rs Outdated
@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from febef35 to 90e06c7 Compare April 29, 2026 01:00
Comment thread crates/proof/succinct/validity/Cargo.toml Outdated
@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from 90e06c7 to d3b2f18 Compare April 29, 2026 01:06
@mw2000 mw2000 marked this pull request as ready for review April 29, 2026 01:08
@mw2000 mw2000 marked this pull request as draft April 29, 2026 01:09
Comment thread crates/proof/zk/service/src/backends/op_succinct/provider.rs Outdated
@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from d3b2f18 to 0765742 Compare April 29, 2026 02:03
Comment thread crates/proof/succinct/validity/src/intermediate_interval.rs
@mw2000 mw2000 marked this pull request as ready for review April 29, 2026 02:11
@mw2000 mw2000 enabled auto-merge April 29, 2026 02:12
Comment thread crates/proof/succinct/validity/src/intermediate_interval.rs
@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from 842d0a5 to 800e720 Compare April 29, 2026 02:36
@mw2000
Copy link
Copy Markdown
Contributor Author

mw2000 commented Apr 29, 2026

Attached to linear issue CHAIN-4080

@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from 800e720 to 6254939 Compare April 29, 2026 21:25
mw2000 added 2 commits April 29, 2026 14:27
The ZK proving pipeline carried the intermediate root interval through
three parallel channels (env var, SP1 stdin scalar, ProofRequest), each
defaulting to DEFAULT_INTERMEDIATE_ROOT_INTERVAL=10 and drifting from the
on-chain AggregateVerifier.INTERMEDIATE_BLOCK_INTERVAL.

Collapse to a single source matching the TEE: the validity binary reads
INTERMEDIATE_BLOCK_INTERVAL from chain (DGF -> impl -> AggregateVerifier)
and threads it into ProofRequest, so the host preimage server answers
boot key 9 with the on-chain value and both the zkVM range program and
the native witness executor read it from BootInfo. Falls back to
DEFAULT_INTERMEDIATE_ROOT_INTERVAL when DGF is unset or the chain read
fails. Removes INTERMEDIATE_ROOT_INTERVAL env var, the stdin scalar
read in the guest, and the now-redundant interval params on
WitnessExecutor::run and WitnessGenerator::get_sp1_stdin.

Made-with: Cursor
@mw2000 mw2000 force-pushed the fix/zk-intermediate-root-interval branch from 6254939 to 72d816e Compare April 29, 2026 21:27
session_id: None,
prover_address: proof_request.prover_address.clone(),
l1_head: proof_request.l1_head.clone(),
intermediate_root_interval: None,
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.

The proof_request DB model now carries intermediate_root_interval: Option<i64>, but this reconstruction discards it. Should be:

Suggested change
intermediate_root_interval: None,
intermediate_root_interval: proof_request.intermediate_root_interval.map(|v| v as u64),

Low severity since this only affects mock backend, but it's inconsistent with the goal of preserving the interval end-to-end. The mock build_mock_public_values doesn't use the interval today, but if it ever does (or if mock proof verification checks the field), this None would silently use the default.

pub use contract::*;
pub use db::*;
pub use env::*;
pub use intermediate_interval::*;
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.

Pre-existing, but since you're touching this file: per workspace conventions (CLAUDE.md), each mod declaration should be grouped with its pub use re-export:

mod intermediate_interval;
pub use intermediate_interval::*;

rather than listing all mods then all pub uses. This applies to the entire file but is a pre-existing issue — flagging only because you're adding a new module here.

@github-actions
Copy link
Copy Markdown
Contributor

Review Summary

Clean, well-designed fix that eliminates the hardcoded DEFAULT_INTERMEDIATE_ROOT_INTERVAL by reading the canonical value from the on-chain AggregateVerifier. The approach is sound — single source of truth mirrors the TEE path, and the data flows correctly through both the validity proposer path (on-chain → RequesterConfigOPSuccinctProofRequesterhost.fetch()BootInfo) and the ZK service path (gRPC → DB → ProveBlockRequest → backends → WitnessParamsBootInfo).

Validation is handled well: the gRPC boundary rejects interval == 0, the on-chain resolver bails on zero, and the executor has a .max(1) defense-in-depth. The migration is backwards-compatible (nullable column, NULL falls back to default). The protobuf field addition at position 8 is wire-compatible.

Minor finding

Cargo.toml dependency ordering (crates/proof/succinct/validity/Cargo.toml:42): base-proof-contracts.workspace = true is placed between anyhow and dotenv, breaking the waterfall (sort-by-line-length) convention. It should be placed after longer lines in this block.

Note on previous inline comments

Most inline comments from earlier review runs appear to be stale — the issues they raised (hardcoded interval in fetch, missing ProveBlockRequestParams field, missing zero validation, etc.) have all been addressed in the current revision.

@jackchuma
Copy link
Copy Markdown
Contributor

Generally looks good to me. Can we add enforcement somewhere that the range proof block intervals are always a multiple of the intermediate block interval?

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