fix(zk): source intermediate root interval from on-chain like TEE#2433
fix(zk): source intermediate root interval from on-chain like TEE#2433
Conversation
🟡 Heimdall Review Status
|
1a9ed2b to
0c05242
Compare
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
0c05242 to
979210a
Compare
979210a to
febef35
Compare
febef35 to
90e06c7
Compare
90e06c7 to
d3b2f18
Compare
d3b2f18 to
0765742
Compare
842d0a5 to
800e720
Compare
|
Attached to linear issue CHAIN-4080 |
800e720 to
6254939
Compare
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
6254939 to
72d816e
Compare
| session_id: None, | ||
| prover_address: proof_request.prover_address.clone(), | ||
| l1_head: proof_request.l1_head.clone(), | ||
| intermediate_root_interval: None, |
There was a problem hiding this comment.
The proof_request DB model now carries intermediate_root_interval: Option<i64>, but this reconstruction discards it. Should be:
| 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::*; |
There was a problem hiding this comment.
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.
Review SummaryClean, well-designed fix that eliminates the hardcoded Validation is handled well: the gRPC boundary rejects Minor finding
Note on previous inline commentsMost inline comments from earlier review runs appear to be stale — the issues they raised (hardcoded interval in |
|
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? |
Summary
The ZK prover hardcoded
DEFAULT_INTERMEDIATE_ROOT_INTERVAL = 10, but the on-chainAggregateVerifiermay 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:INTERMEDIATE_BLOCK_INTERVALon startup (DGF → impl →AggregateVerifier) and threads it intoProofRequest.intermediate_block_interval.WitnessExecutornow read the interval fromBootInfo, the same channel the TEE enclave uses.DEFAULT_INTERMEDIATE_ROOT_INTERVALonly when DGF is unset or the chain read fails.Removed (now redundant)
INTERMEDIATE_ROOT_INTERVALenv varWitnessExecutor::runandWitnessGenerator::get_sp1_stdinNotes
range_vkey_commitment. The ELF then accepts any on-chain interval without rebuilding (interval is data, not code).