Skip to content

Commit effe773

Browse files
committed
docs(shadow-testing): clarify PostEuclidV2 function vs PostFeynman verifier, add v0.9.0 lessons
1 parent 6445f84 commit effe773

2 files changed

Lines changed: 60 additions & 2 deletions

File tree

tests/shadow-testing/docs/GUIDE.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ For `finalizeBundlePostEuclidV2`, the batch was already committed on mainnet at
573573

574574
## Real Verifier Deployment
575575

576-
### Option 1: Copy the Mainnet Verifier (Fastest)
576+
### Option 1: Copy the Mainnet Verifier (Fastest — Only if Digests Match)
577577

578578
For quick testing, copy the exact mainnet verifier contract code to Anvil using `anvil_setCode`:
579579

@@ -589,7 +589,7 @@ PLONK_CODE=$(cast code $PLONK --rpc-url https://ethereum-rpc.publicnode.com)
589589
cast rpc anvil_setCode $PLONK $PLONK_CODE --rpc-url http://localhost:18545
590590
```
591591

592-
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.
593593

594594
### Option 2: Deploy a Fresh Verifier Using S3 Digests
595595

@@ -616,6 +616,24 @@ For v0.9.0 release assets are under `scroll-zkvm/releases/v0.9.0/`:
616616

617617
> **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.
618618
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:
622+
623+
```text
624+
finalizeBundlePostEuclidV2(bytes,uint256,bytes32,bytes32,bytes)
625+
```
626+
627+
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+
619637
### Verifying Digests Match Your Proofs
620638

621639
If you want to double-check, compare the canonical digests from S3 against the values stored in the deployed wrapper:

tests/shadow-testing/docs/TROUBLESHOOTING.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,46 @@ Before executing a single command:
236236
| Coordinator asset download 403 (`galileov2/verifier/...`) | Wrong S3 prefix; use `v0.8.0/verifier/` | Trap 14 |
237237
| `l2_block` export hangs for minutes | Slow `chunk_hash` JOIN; export by block-number range | Trap 15 |
238238

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.
278+
239279
## Documentation Priority
240280

241281
When debugging, read docs in this order:

0 commit comments

Comments
 (0)