You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This preserves the exact immutables (plonkVerifier address, digests, protocolVersion) from mainnet and works as long as your proofs use the same digests as mainnet.
592
+
This preserves the exact immutables (plonkVerifier address, digests, protocolVersion) from mainnet and works **only** if your proofs use the same digests as mainnet. When testing a new guest / circuit version (e.g., v0.9.0) whose digests differ from mainnet, this will produce `VerificationFailed`; use Option 2 instead.
593
593
594
594
### Option 2: Deploy a Fresh Verifier Using S3 Digests
595
595
@@ -616,6 +616,24 @@ For v0.9.0 release assets are under `scroll-zkvm/releases/v0.9.0/`:
616
616
617
617
> ✅ **Use the S3 digest files directly.** For guest v0.9.0, `digest_1.hex` / `digest_2.hex` are published in the canonical form expected by the Plonk verifier. You no longer need to extract digests from a proof's `instances` array.
618
618
619
+
### Important: `finalizeBundlePostEuclidV2` uses a `ZkEvmVerifierPostFeynman` verifier
620
+
621
+
Do not be misled by the contract function name. `ScrollChain` only has one bundle-finalize entry point:
There is **no**`finalizeBundlePostFeynman` function. The actual verifier used by this function is selected by `MultipleVersionRollupVerifier.getVerifier(version, batchIndex)`. For the current mainnet GalileoV2 range, that verifier is a `ZkEvmVerifierPostFeynman`-style wrapper whose `protocolVersion` immutable equals `10`.
628
+
629
+
-`ZkEvmVerifierPostEuclid` computes `keccak256(publicInput)`. This is old code and is **not** used for current GalileoV2 / v0.9.0 proofs.
630
+
-`ZkEvmVerifierPostFeynman` computes `keccak256(abi.encodePacked(protocolVersion, publicInput))` with `protocolVersion = 10`. This matches the `bundle_pi_hash` produced by v0.9.0 guest provers.
631
+
632
+
So on a shadow fork you must either:
633
+
634
+
1. Copy the exact mainnet `ZkEvmVerifierPostFeynman` wrapper (only works if your local proofs use the **same digests** as mainnet), or
635
+
2. Deploy a fresh `ZkEvmVerifierPostFeynman` with the digests from the v0.9.0 S3 release and register it on the MVRV.
636
+
619
637
### Verifying Digests Match Your Proofs
620
638
621
639
If you want to double-check, compare the canonical digests from S3 against the values stored in the deployed wrapper:
|`l2_block` export hangs for minutes | Slow `chunk_hash` JOIN; export by block-number range | Trap 15 |
238
238
239
+
## Lessons from the v0.9.0 Multi-Bundle Shadow Test
240
+
241
+
The following issues were hit while finalizing bundles 17297–17301 (batches 517761–517765) on an Anvil mainnet fork with zkvm guest prover v0.9.0. Keep them in mind for future upgrades.
242
+
243
+
### 1. Do not `git checkout --` uncommitted source changes blindly
244
+
245
+
When cleaning up the branch, the v0.9.0 source adaptations (`libzkp`, `prover-bin`, Go `message` types, `rust-toolchain`, `Cargo.lock`) were accidentally reverted because they were not committed. They had to be reconstructed from compiler errors. Always check `git diff --stat` before a bulk revert, and stage or stash anything you intend to keep.
246
+
247
+
### 2. `finalizeBundlePostEuclidV2` is the only finalize function, but the verifier must be Post-Feynman
248
+
249
+
`ScrollChain` exposes only one bundle-finalize selector (`0xc1aa4e19`). The name says `PostEuclidV2`, but the verifier it actually calls is chosen by `MultipleVersionRollupVerifier.getVerifier(10, batchIndex)`. For GalileoV2 / v0.9.0 this must be a `ZkEvmVerifierPostFeynman`-style wrapper whose `protocolVersion` immutable is `10`.
250
+
251
+
-`ZkEvmVerifierPostEuclid` computes `keccak256(publicInput)` — this is old code and will reject current proofs.
252
+
-`ZkEvmVerifierPostFeynman` computes `keccak256(protocolVersion || publicInput)` — this matches v0.9.0 `bundle_pi_hash`.
253
+
254
+
### 3. Copying the mainnet verifier via `anvil_setCode` fails for new guest versions
255
+
256
+
`anvil_setCode` copies runtime bytecode but **preserves the original immutables** (`plonkVerifier`, `verifierDigest1/2`, `protocolVersion`). If your local v0.9.0 proofs use different digests than mainnet, the wrapper will return `VerificationFailed`. For a new guest version, deploy a fresh `ZkEvmVerifierPostFeynman` using the S3 release digests.
257
+
258
+
### 4. MVRV routing must be verified per target batch
259
+
260
+
After deploying a new verifier, confirm that `MVRV.getVerifier(10, batchIndex)` returns your wrapper for every batch you intend to finalize. If the fork block already contains a later mainnet verifier registration, a plain `updateVerifier` may be rejected; force the storage slot or impersonate the owner as needed for the shadow fork.
261
+
262
+
### 5. v0.9.0 dependency graph needs a fresh `Cargo.lock`
263
+
264
+
Pointing `Cargo.toml` to v0.9.0 is not enough. The first `cargo check` hit a revm version conflict because the old `Cargo.lock` pinned incompatible crate versions. Regenerating `Cargo.lock` resolved it.
265
+
266
+
### 6. Prover aggregation circuits need deferral enabled
267
+
268
+
OpenVM v2+ requires `Prover::enable_deferral(child_prover)` before proving aggregation tasks:
269
+
270
+
- Batch proving needs a chunk child prover.
271
+
- Bundle proving needs a batch child prover.
272
+
273
+
The prover config therefore needs `child_circuit_vks` so the prover can load the correct child circuit assets.
274
+
275
+
### 7. S3 digest files are canonical — no proof extraction needed
276
+
277
+
For v0.9.0, `.../releases/v0.9.0/bundle/digest_1.hex` and `digest_2.hex` are published in the canonical form expected by the Plonk verifier. Do not apply Montgomery→canonical conversion and do not extract digests from proof `instances` unless you are double-checking a specific artifact.
0 commit comments