Skip to content

eest: add EIP-8025 execution witness test suite (93 zkevm fixtures)#20938

Closed
awskii wants to merge 37 commits into
mainfrom
awskii/eest-witness-newmain
Closed

eest: add EIP-8025 execution witness test suite (93 zkevm fixtures)#20938
awskii wants to merge 37 commits into
mainfrom
awskii/eest-witness-newmain

Conversation

@awskii
Copy link
Copy Markdown
Member

@awskii awskii commented May 1, 2026

Summary

  • Port the EIP-8025 execution witness suite onto fresh main
  • Add the witness test runner and ExecModuleTester exposure
  • Wire the suite into CI with Linux/macOS only for now

Why

  • The suite is still under investigation for CI pressure in the execution race jobs
  • Windows was removed temporarily so it doesn't mask or amplify the failure signal while we isolate the root cause
  • The zkevm witness test now logs each fixture name before running, which makes it easier to identify the first failing corpus entry

Status

  • Ralphex execution completed successfully
  • Plan moved to docs/plans/completed/20260429-eest-witness-test-suite-port.md
  • Code review findings were addressed in the latest commit

Testing

  • make lint
  • make erigon
  • witness fixture suite: 93 fixtures / 176 subtests

awskii and others added 24 commits April 29, 2026 17:34
Add witness_block_test_util.go with WitnessBlockTest struct that wraps
BlockTest with per-block execution witness expectations (state, codes,
headers). Includes UnmarshalJSON for dual deserialization and accessors
for querying expected witness data per block index.
Add public M field to BlockTest struct and assign it in both Run() and
RunCLI() methods so the witness test runner can access the
ExecModuleTester after block execution.
Create testmain_test.go and witness_test.go in
execution/tests/eest_zkevm_witness/ to validate Erigon's execution
witness generation against 93 EIP-8025 fixtures from
ethereum/execution-spec-tests zkevm@v0.3.3.

All 93 fixtures are marked as expected failures via bt.Fails for
known State/Codes ordering mismatches (#20442, #20534).
Add execution-eest-zkevm test group to tools/test-groups and append
blockchain_tests_zkevm/**/*.json to the git-lfs pull include pattern
in setup-erigon action.
make lint (0 issues, run twice) and make erigon integration both pass
cleanly with the new witness test files from Tasks 1-4.
- Guard NewWitness against genesis block (number 0) to prevent uint64
  underflow in parent block number calculation
- Simplify headers slice initialization to direct literal
- Add TestNewWitnessRejectsGenesisBlock test
…ewmain

# Conflicts:
#	execution/tests/testutil/block_test_util.go
#	tools/test-groups
…ss Headers format

After merge with main, ExecutionWitnessResult.Headers changed from
[]hexutil.Bytes to []map[string]any in PR #21224 ("align response
debug_executionWitness to GETH"). The EEST zkevm fixture format still
encodes headers as RLP hex bytes, so compareWitness can't pass them to
compareByteSlices anymore.

Add a small jsonHeadersToRLP helper that mirrors marshalWitnessHeader in
reverse: it renames balHash back to blockAccessListHash, drops the
synthetic "hash" and "size" fields that aren't part of types.Header's
JSON schema, and round-trips each map through Header.UnmarshalJSON +
rlp.EncodeToBytes. The resulting []hexutil.Bytes is comparable
element-by-element against the fixture data.
Main's #21092 removed both execution-eest-blockchain and
execution-eest-devnet from tools/test-groups when spec tests were
extracted out of make test-all. The merge resolution mistakenly kept
the PR-side branch with the devnet entry plus a stale "Temporarily
disable the blockchain shard" comment. Drop the devnet entry and the
comment; keep only the PR's own execution-eest-zkevm contribution.
The witness test only consumes BlockTest.M from the Run(t) path, so the
RunCLI() assignment is a dead store with a real cost: cmd/evm's
runBlockTest holds a map[string]*BlockTest across an entire fixture
file, and bt.M kept each iteration's ExecModuleTester reachable past
m.Close(). Close() releases DB/snapshots/engine but doesn't nil the
struct fields, so StateCache and other heavyweights stayed pinned for
the rest of the file's iteration. Under evm.race with --workers 12 in
the EEST blockchain-tests CI matrix that pushed the runners past the
OOM threshold (jobs SIGTERM'd at 9-57 minutes), while main without the
field assignment runs fine.

Removing the RunCLI line restores the prior memory profile. Run(t)
keeps the assignment since the witness test needs it; t.Cleanup handles
the cleanup there.
@awskii awskii marked this pull request as ready for review May 21, 2026 18:18
@yperbasis yperbasis added this pull request to the merge queue May 22, 2026
@yperbasis yperbasis removed this pull request from the merge queue due to a manual request May 22, 2026
Copy link
Copy Markdown
Member

@yperbasis yperbasis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update to use PR #21002 machinery.

Adopts the lazy-download manifest machinery introduced by #21002 instead
of relying on the prior Git LFS path under execution/tests/execution-spec-tests/.

- test-fixtures.json: add eest_zkevm entry pinning zkevm@v0.3.4
  fixtures_zkevm.tar.gz (sha256 b9e3ab70..., 231977945 bytes).
- Makefile: add a focused test-fixtures-zkevm target so workflows can
  pull just the zkevm tarball without forcing eest_stable/devnet/benchmark.
- execution/tests/eest_zkevm_witness/witness_test.go: repoint the fixture
  walk root at test-fixtures-cache/eest_zkevm/fixtures/blockchain_tests,
  matching the tarball's internal layout (the script does not strip
  --strip-components).
- .github/workflows/test-all-erigon-race.yml: when the matrix entry is
  execution-eest-zkevm, restore the cached tarball (keyed on
  hashFiles('test-fixtures.json')) and run make test-fixtures-zkevm
  before make test-group. Other matrix entries are unaffected.
Copy link
Copy Markdown
Member Author

@awskii awskii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migrated to the #21002 manifest in ceb81f9. Summary:

  • test-fixtures.json — added eest_zkevm pinning zkevm@v0.3.4 (fixtures_zkevm.tar.gz, sha256 b9e3ab70…, 231,977,945 bytes).
  • Makefile — added test-fixtures-zkevm (focused; pulls only the zkevm tarball, doesn't piggy-back on test-fixtures-eest since most jobs don't need it).
  • execution/tests/eest_zkevm_witness/witness_test.go — repointed the walk root at test-fixtures-cache/eest_zkevm/fixtures/blockchain_tests, matching the tarball's internal fixtures/blockchain_tests/... layout (the script doesn't strip).
  • .github/workflows/test-all-erigon-race.yml — when the matrix entry is execution-eest-zkevm, restore the cached tarball (keyed on hashFiles('test-fixtures.json')) and run make test-fixtures-zkevm before make test-group. Other matrix entries are untouched.

Verified locally: tools/test-fixtures.sh downloads, sha256-verifies, and extracts; the whitelisted fixture (for_amsterdam/.../validation_state_unsorted_but_complete.json) is reachable at the new path and the test walks the corpus correctly.

PR #21224 added a DB-level precondition to debug_executionWitness: the
RPC now reads the commitment-history flag via rawdb.ReadDBCommitmentHistoryEnabled
and returns an error if it's unset. statecfg.EnableHistoricalCommitment
sets the schema but not the DB flag (in production the flag is written
by node/eth/backend on startup).

The test framework builds its DB from scratch, so write the flag
explicitly right after setting up the API. Confirmed locally that the
whitelisted fixture now reaches the comparator instead of failing on
the precondition.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an EIP-8025 execution witness validation suite (zkevm fixtures) to Erigon’s execution tests, including fixture download wiring and small witness-generation/test harness adjustments.

Changes:

  • Add eest_zkevm fixture manifest entry plus make test-fixtures-zkevm target and CI cache/download steps.
  • Introduce a witness-aware BlockTest wrapper and a new execution/tests/eest_zkevm_witness runner that compares debug_executionWitness output to fixture expectations.
  • Harden witness creation by explicitly rejecting genesis block witnesses and add a unit test for it.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tools/test-groups Adds a dedicated CI test group for the zkevm witness suite.
test-fixtures.json Pins the eest_zkevm fixture tarball (url/sha/size).
Makefile Adds test-fixtures-zkevm target to fetch/extract the zkevm witness fixtures.
execution/types/stateless/witness.go Rejects genesis witness creation; minor slice init cleanup.
execution/types/stateless/witness_test.go Adds a unit test asserting genesis witness creation is rejected.
execution/tests/testutil/witness_block_test_util.go Adds WitnessBlockTest to parse per-block executionWitness expectations.
execution/tests/testutil/block_test_util.go Exposes the underlying ExecModuleTester from BlockTest.Run().
execution/tests/eest_zkevm_witness/witness_test.go Adds the witness fixture runner and comparison helpers.
execution/tests/eest_zkevm_witness/testmain_test.go Adds TestMain hook for the suite.
docs/plans/completed/20260429-eest-witness-test-suite-port.md Documents the port plan and completion notes for the suite.
.github/workflows/test-all-erigon-race.yml Caches the zkevm fixture tarball and runs make test-fixtures-zkevm for the new group.
Comments suppressed due to low confidence (2)

execution/tests/eest_zkevm_witness/witness_test.go:97

  • execmoduletester.New(t, ...) already registers t.Cleanup(mock.Close), so the additional defer test.M.Close() will close the tester twice. ExecModuleTester.Close() is not idempotent (it closes Engine/DB/snapshots), so this can cause panics or flaky failures.
		if test.M == nil {
			t.Fatal("ExecModuleTester not set after BlockTest.Run")
		}
		defer test.M.Close()

docs/plans/completed/20260429-eest-witness-test-suite-port.md:101

  • The verification steps here still instruct initializing the execution-spec-tests submodule and mention LFS checkout, but the suite in this PR is wired to make test-fixtures-zkevm / test-fixtures-cache/eest_zkevm. Consider updating the recorded steps so someone following the plan doesn't fetch the wrong fixture source.
### Task 6: Run witness test suite

- [x] Initialize submodule: `git submodule update --init execution/tests/execution-spec-tests`
- [x] Fetch LFS fixtures: fixtures already checked out as real JSON (git-lfs not needed)
- [x] Run test suite: `go test -count=1 -v -run TestExecutionSpecWitness ./execution/tests/eest_zkevm_witness/...`
- [x] Verify all 93 fixtures run and pass (via expected-failure annotations) — 176 subtests, 0 failures
- [x] No deviations from expected results

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread execution/tests/eest_zkevm_witness/witness_test.go
Comment thread execution/tests/eest_zkevm_witness/witness_test.go Outdated
Comment thread execution/tests/testutil/block_test_util.go
Comment thread execution/types/stateless/witness.go
Comment thread docs/plans/completed/20260429-eest-witness-test-suite-port.md Outdated
awskii added 4 commits May 22, 2026 16:49
The M field added by this PR was a data-race hazard (Copilot also
flagged a related double-close: execmoduletester.New already registers
t.Cleanup(m.Close), so the test's defer test.M.Close() ran Close
twice on the same instance — Close is not idempotent and closes
Engine/DB/snapshots).

Replace the field with an explicit RunWithTester(t) (*ExecModuleTester,
error) method that returns the tester from Run's existing setup path.
Run(t) error becomes a thin wrapper. The witness test grabs the
tester from the return value, drops the field access, and removes the
double-close defer (auto-cleanup via t.Cleanup is sufficient).

Also drop the zkevm fixture version (zkevm@v0.3.3) from the package
doc comment — the pin lives in test-fixtures.json now, so the comment
would just drift with every bump.
- witness_test.go: drop bt.Whitelist so the full corpus runs. All
  mismatches are still absorbed by bt.Fails(".") for the documented
  state/codes ordering issues (#20442, #20534), so the CI signal stays
  green; CI logs now reflect the whole 93-fixture surface.
- stateless/witness.go: fix "wtness" → "witness" in a comment touched by
  this PR's surrounding refactor.
- docs/plans/completed/20260429-eest-witness-test-suite-port.md: replace
  the v0.3.3 + submodule/LFS references with the manifest-driven flow
  (test-fixtures.json + make test-fixtures-zkevm) so the completed-plan
  record matches what shipped.
…ilure

After dropping the whitelist (bd01f8d) many fixtures fail at block
execution rather than at witness comparison, because Erigon doesn't yet
implement every EIP in zkevm v0.3.4 (EIP-7708 burn logs, EIP-7954,
EIP-8037, etc.). The previous t.Fatalf bypassed the suite-wide
bt.Fails(".") absorption mechanism, so each gap surfaced as a hard
failure.

Route the error through bt.CheckFailure (mirroring the witness-comparison
branch) so it's absorbed as a documented gap. Return early after
absorption since there's no tester to drive the subsequent debug RPC
calls. Unexpected failures (no matching Fails pattern) still raise via
t.Error.
…s too

Same shape as the block-execution-failure fix (9c70e4d): with the
whitelist gone, many fixtures reach the RPC path but the RPC returns
"block not found: 1" for fixtures whose state shape differs from the
single fixture the test was originally tuned against. The previous
t.Fatalf bypassed bt.Fails absorption, leaving each gap as a hard
failure.

Collect RPC errors (and nil results) into witnessErrs alongside
comparison mismatches, then let the bt.CheckFailure call at the end of
the closure absorb them uniformly. Unexpected failures (no matching
Fails pattern) still raise via t.Error.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Comment thread execution/tests/eest_zkevm_witness/witness_test.go
Comment thread execution/tests/eest_zkevm_witness/witness_test.go Outdated
Comment thread execution/tests/eest_zkevm_witness/witness_test.go
Comment thread docs/plans/completed/20260429-eest-witness-test-suite-port.md Outdated
Comment thread docs/plans/completed/20260429-eest-witness-test-suite-port.md Outdated
awskii added 4 commits May 25, 2026 13:42
… Walk guard

The os.Stat pre-check only branched on os.IsNotExist, so a dir that exists
as a non-directory (or a non-IsNotExist stat error) fell through to the shared
Walk, re-surfacing the misleading 'clone the tests submodule' message the
pre-check was meant to replace (and hitting Walk's nil-deref on the error
case). Mirror Walk's full 'missing OR not-a-directory' guard.
…gain

The widen-corpus suite contains Amsterdam EIPs (eip7708/7778/7843/7928) that
Erigon does not yet fully implement, so their blocks fail to execute (gas
mismatches). Hard-failing on block execution (prior commit) turned ~12.8k
known-failing subtests red in CI. Route block-execution errors back through
bt.CheckFailure so the suite-wide bt.Fails(".") absorbs them, matching the
witness-comparison gaps. The whole corpus is a known-failing tracker today.
Copy link
Copy Markdown
Member

@yperbasis yperbasis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Infra changes look good (RunWithTester, manifest migration, genesis guard). One blocking concern on the test itself:

bt.Fails(".", ...) + bt.CheckFailure on both error classes makes this a no-op regression detector.

. matches every fixture; routing block-execution errors and witness mismatches through bt.CheckFailure means the only signal the suite produces is "did anything pass unexpectedly." The commit message on 8c38b22ab7 confirms the two failure modes are genuinely different (Amsterdam EIPs unimplemented vs. State/Codes ordering #20442/#20534), and the prior hard-fail commit c488b1ca43 was reverted specifically because they got conflated.

Minimum fix: split bt.Fails by category (Amsterdam EIPs by name pattern → "not yet implemented"; the rest → "ordering #20442/#20534"), and let block-execution errors outside the Amsterdam set fall through to t.Errorf. That way a regression that turns one category into the other surfaces as unexpected.

Smaller items:

  • TestNewWitnessRejectsGenesisBlock compares err.Error() verbatim — use a sentinel or errors.Is.
  • RunWithTester's no-close contract is docstring-only; consider hiding Close on the returned type so the double-close footgun can't recur.
  • Branch needs rebase against 7827ec7268 (new exec_mode matrix in test-all-erigon-race.yml).
  • Re-request review — @AskAlexSharov's approval is on cd9d157e58, 11 substantive commits ago.

awskii added 3 commits May 27, 2026 09:55
…ewmain

# Conflicts:
#	.github/workflows/test-all-erigon-race.yml
Copy link
Copy Markdown
Member

@yperbasis yperbasis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is red

@awskii
Copy link
Copy Markdown
Member Author

awskii commented May 29, 2026

ZKevm corpus is geth compatible, we need to make it RETH compatible since Zilk is using it.

We are not looking for 100% compatibility - its unbearable, and im closing this in favor of newer zkevm corpus v0.4.0 at #21487

@awskii awskii closed this May 29, 2026
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.

4 participants