cmd/evm: add enginetest command for direct engine fixture execution#34650
cmd/evm: add enginetest command for direct engine fixture execution#34650spencer-tb wants to merge 9 commits intoethereum:masterfrom
Conversation
29e3f4c to
00957ea
Compare
00957ea to
d46370a
Compare
| return engine.PayloadStatusV1{Status: engine.INVALID}, engineParamsErr("nil versionedHashes post-cancun") | ||
| case p.BeaconRoot == nil: | ||
| return engine.PayloadStatusV1{Status: engine.INVALID}, engineParamsErr("nil beaconRoot post-cancun") | ||
| case !h.checkFork(params.Timestamp, forks.Cancun, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5): |
There was a problem hiding this comment.
Will need to double check this for my own sanity -- for some reason I was expecting it to just say forks.Cancun
There was a problem hiding this comment.
This matches the real ConsensusAPI.NewPayloadV3 at api.go:204 which allows V3 for Cancun through BPO5. So maybe can be changed there too but not 100% certain :)
There was a problem hiding this comment.
Ah I see, seems I was remembering this:
go-ethereum/eth/catalyst/api.go
Line 708 in d8cb8a9
| if postCheck != nil { | ||
| defer postCheck(result, chain) | ||
| } |
There was a problem hiding this comment.
Minor nit: I think we may want to use a closure here becauseresult here would be evaluated at the callsite and not when the defer is triggered.
There was a problem hiding this comment.
Small self-contained example to elaborate:
package main
import "fmt"
func runBuggy(postCheck func(error, string)) (result error) {
chain := "some-chain"
// `result` is evaluated at the callsite, so its nil and not when the defer fires.
if postCheck != nil {
defer postCheck(result, chain)
}
result = fmt.Errorf("payload 3: expected VALID, got INVALID")
return result
}
func runFixed(postCheck func(error, string)) (result error) {
chain := "some-chain"
// closure captures `result` by reference, so it reads the final value when the defer fires.
if postCheck != nil {
defer func() { postCheck(result, chain) }()
}
result = fmt.Errorf("payload 3: expected VALID, got INVALID")
return result
}
func main() {
check := func(res error, chain string) {
fmt.Println(" postCheck got error:", res)
}
fmt.Println("buggy:")
runBuggy(check)
fmt.Println("fixed:")
runFixed(check)
}| var tests map[string]*tests.BlockTest | ||
| if err = json.Unmarshal(src, &tests); err != nil { | ||
| return nil, err | ||
| return nil, nil // Skip non-fixture JSON files |
There was a problem hiding this comment.
Just want to confirm that this also skips errors from malformed fixture files?
- Add lastBlockHash to blocktest/enginetest, lastPayloadStatus to enginetest - Remove stateRoot from blocktest/enginetest (only statetest has it) - Report validation/rejection error in `error` even when test passes, for negative tests (expected exceptions) - Enables EELS consume direct to map errors through ExceptionMapper and verify correct exception for every invalid test
|
I like the idea. I don't know if we need --worker though, we could just default to runtime.NumCPU() |
Summary
Add
evm enginetestcommand that runsblockchain_test_enginefixtures directly against a lightweight Engine API handler, without requiring Hive or full client startup. Also add--workersflag to all three test runners (enginetest,blocktest,statetest) for parallel fixture file processing.evm enginetestA new direct runner for Engine API test fixtures. Implements a lightweight engine handler that mirrors the core logic of
eth/catalyst.ConsensusAPI:NewPayloadV1-V5parameter validationExecutableDataToBlockpayload conversion and block insertion viaInsertBlockWithoutSetHeadForkchoiceUpdatedwithSetCanonicalhead management (including initial FCU to genesis)PayloadStatusV1responsesEngineAPIErrorcode validation against fixture expectations (errorCode,validationError)This exercises the actual engine code path (two-phase insert-then-canonicalize via forkchoice), not just
InsertChainlikeblocktest.Benchmarks
Tested against EEST v5.3.0 stable fixtures on Apple M-series.
For reference, Hive runs of the same test suite on the same geth version:
consume engine: 2h 48mconsume rlp: 4h 29mevm enginetest— exercises the same engine code paths asconsume engine(40,523 tests):evm blocktest— exercises the same execution paths asconsume rlp(43,924 tests):evm statetest(40,553 tests):Hive parity
Tested against v5.3.0 stable release — exact same 4 failures as Hive
consume engineon geth master:eip7002/test_system_contract_deployment[CancunToPragueAtTime15k-deploy_after_fork-nonzero_balance]eip7002/test_system_contract_deployment[CancunToPragueAtTime15k-deploy_after_fork-zero_balance]eip7251/test_system_contract_deployment[CancunToPragueAtTime15k-deploy_after_fork-nonzero_balance]eip7251/test_system_contract_deployment[CancunToPragueAtTime15k-deploy_after_fork-zero_balance]Usage