fix(specs): BPO3 inherits BPO2, not Amsterdam; run BPO transition pyspec fixtures#12312
fix(specs): BPO3 inherits BPO2, not Amsterdam; run BPO transition pyspec fixtures#12312Marchhill wants to merge 22 commits into
Conversation
Per review agreement on #12118, the intrinsic must not read world state: replace the draft's tiered recipient/value costs (dead-account, code, access-list probes) with the spec's flat model, and drop the worldState parameter from IntrinsicGasCalculator and IGasPolicy. Also compress comments across the branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…evm-stateless-v050-v2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…evm-stateless-v050-v2
* test: update pyspec fixtures to glamsterdam-devnet v6.0.0 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: ignore ZkEVM stateless suite (fixtures target bal-devnet-7) The ZkEvmBlockchainTests stateless suite runs Nethermind.Stateless.Executor against the pinned tests-zkevm@v0.4.1 archive, which is generated against bal-devnet-7 (tests-bal@v7.2.0). Its EIP-7928 block-access-list semantics differ from the devnet-6 (tests-glamsterdam-devnet@v6.0.0) rules this stack implements, so stateless execution rejects every fixture block on a BAL mismatch (StatelessValidationResult.IsSuccess=0) — the full Pyspec [Sequential]/engine shards each failed only on the *_stateless_block_N cases. Mark the suite [Ignore] until the client tracks bal-devnet-7 (or the archive is repinned to devnet-6). No production code is affected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: bump Glamsterdam devnet Pyspec fixtures to v6.1.0 Run the Ethereum.Blockchain.Pyspec.Test suite against the tests-glamsterdam-devnet@v6.1.0 fixture release. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: re-enable zkEVM stateless fixtures on tests-zkevm@v0.5.0 The zkVM stateless suite was disabled because the pinned archive (tests-zkevm@v0.4.1) was generated against bal-devnet-7, whose EIP-7928 BAL semantics differ from the devnet-6 rules this stack implements. tests-zkevm@v0.5.0 is generated against tests-glamsterdam-devnet@v6.1.0 (the devnet-6 fixtures this stack tracks), so the mismatch is resolved. Bump the archive version and drop the [Ignore]. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: update Pyspec fixtures to Glamsterdam devnet-6 (v6.1.0) and zkEVM v0.5.0 Point the default Pyspec fixture archive at tests-glamsterdam-devnet@v6.1.0 and the zkEVM stateless preview suite at tests-zkevm@v0.5.0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: implement EIP-8246 (Remove SELFDESTRUCT Burn) Removes the residual ETH-burn cases left by EIP-6780: - A self-targeting SELFDESTRUCT now moves no ETH and emits no log, regardless of whether the account was created in the same transaction. - At transaction finalization, accounts marked for destruction keep their balance: storage and code are cleared and the nonce is reset to 0. A resulting zero-balance account is still removed as empty per EIP-161, matching the spec and keeping CREATE2 redeployment unblocked. Wires a new IsEip8246Enabled flag through IReleaseSpec / ReleaseSpec / decorators / chainspec (Eip8246TransitionTimestamp) and enables it in the Amsterdam fork. Adds Eip8246Tests covering same-transaction self-destruct to self/other, post-destruct funding, the zero-balance empty-account case, and the unchanged not-in-same-tx no-op, each pinned with EIP on and off. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: cover deferred finalization path; address review feedback - Add an EIP-8037 + EIP-7708 fixture dimension so every EIP-8246 scenario also runs through the deferred FinalizeDestroyedAccount path (as in Amsterdam), covering the balance-preservation logic there. - Add a CREATE2 redeployment test: a factory re-creates a self-destructed child at the same address across transactions, verifying the nonce reset keeps redeployment unblocked and the preserved balance accumulates. - Report the destroy refund to the tracer in the deferred path, matching the inline path. - Document the pre-existing Burn-vs-SelfDestruct log distinction between the post-fee and pre-fee finalization paths. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: do not enable EIP-8246 in Amsterdam fork EIP-8246 is a Draft and is not part of the EEST `for_amsterdam` conformance fixtures. Enabling it in the Amsterdam fork changed SELFDESTRUCT behaviour for that fork, diverging from the reference post-states and failing the Pyspec tests across all shards. Keep the full implementation and spec/chainspec plumbing so the EIP can be activated via the Eip8246Transition chainspec parameter once it is scheduled, but leave it disabled in the named forks. Unit tests toggle the flag directly via OverridableReleaseSpec, so coverage is unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: assert storage clearing in EIP-8246 self-destruct tests Address PR review comments: - The self-destruct-to-self contract now writes storage slot 0 before SELFDESTRUCT so AssertBalanceOnly can verify storage is wiped on the surviving balance-only account. - Clarify the self-targeting SELFDESTRUCT short-circuit comment to distinguish the EIP-6780 pure no-op case from the EIP-8246 burn-removal case (account in destroy list, finalization still clears code/storage). Note: the deferred finalization path also gained a tracer.ReportRefund call to match the inline path; that is an incidental tracer fix unrelated to EIP-8246 semantics. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: tidy EIP-8246 self-destruct test per review - Rename the self-destruct-to-self fixtures to _sstoreThenSelfDestructToSelf so the name reflects the SSTORE-then-SELFDESTRUCT bytecode. - Wrap AssertBalanceOnly in Assert.EnterMultipleScope so every mismatch is surfaced in one run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(test-build): cast ulong DestroyRefund for tracer refund (master #11937) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: port EIP-8246 test BlockNumber override to ulong (master #11937) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: bump EF fixtures to tests-glamsterdam-devnet@v6.1.1 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: map InvalidTxSignature to INVALID_SIGNATURE_VRS for v6.1.1 test_bad_v_r_s Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: map InvalidTxChainId/EIP-155 sig failure to INVALID_CHAINID (v6.1.1) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: decode invalid-tx state tests from txbytes (v6.1.1 expectException) v6.1.1 state tests carry expectException plus the actual signed tx in txbytes. The template tx is re-signed pre-EIP-155, which cannot reproduce signature-level invalidity (test_invalid_chain_id executes as a valid tx and diverges from the expected post state). Decode the fixture's raw tx for such entries so validation rejects it; undecodable txbytes fall back to the template. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: key opcode dispatch tables by spec instance, not on the spec object The per-spec opcode tables were cached in IReleaseSpec.EvmInstructionsNoTrace/ Traced slots. OverridableReleaseSpec's getter fell back to the wrapped spec and ReleaseSpecDecorator's setter wrote through to it, so wrappers with different EVM flags (7708/8037/8246 test variants) shared one table with fork singletons — first writer won, giving wrong opcode handlers (missing transfer logs, wrong state-gas charges) depending on test order. Port master's fix (#12146): cache tables in a ConcurrentDictionary keyed by spec instance (plain statics for the single-fork zkEVM guest) and drop the IReleaseSpec slots. Full Evm.Test suite: 10/10 clean (was ~5 of 6 runs failing). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: tighten EIP-8246 comments Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test: move the v6.1.1 pyspec fixes off the EIP-8246 branch The fixture bump and its harness fixes (INVALID_SIGNATURE_VRS/INVALID_CHAINID mappings, txbytes decode for expectException state tests) are unrelated to EIP-8246; they move to fix/zkevm-stateless-v050-v2 where the fixture/format alignment lives. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: move the opcode-table cache fix to the stateless branch; group 8246 with Amsterdam EIPs The spec-instance opcode-table keying is test-infrastructure hardening unrelated to EIP-8246; it moves to fix/zkevm-stateless-v050-v2. IsEip8246Enabled now sits with the other Amsterdam EIP flags in the spec surfaces. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: drop the Amsterdam EIP-8246 activation note The flag is enabled one PR up (repricings, #12214) where the note is already gone. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: enable EIP-8246 in Amsterdam Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Marc Harvey-Hill <10379486+Marchhill@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…tent already present) into repricings-and-updates-v2
…evm-stateless-v050-v2
- Enforce the EIP-2780 => EIP-7708 co-activation invariant in ChainSpecBasedSpecProvider (with regression test). - Restore the MaxCallDepth capacity hint on the VM state stack. - Route the inlined net-spill expressions through GetUnrefundedStateGasSpill. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…evm-stateless-v050-v2
|
Claude finished @Marchhill's task in 3m 36s —— View job Review: BPO3 fork lineage fix
Verdict: LGTM — correct, well-scoped bugfix. No Critical/High/Medium issues. ✅ Why the reparent is correct
Blast radius is contained to the test path ✅I checked that the reparent does not affect real-network consensus. Live specs are assembled cumulatively-by-timestamp through Fixture additions verified ✅
Low / informational (non-blocking)
Nice catch on the missing CI coverage that let this slip through. |
BPO forks are blob-parameter-only forks chained off BPO2, parallel to Amsterdam (matching execution-spec-tests fork lineage). Inheriting Amsterdam wrongly enabled EIP-7928 (and the rest of Amsterdam) on BPO3/BPO4/BPO5, so BPO2->BPO3 transition blocks demanded a BAL hash (MissingBlockLevelAccessListHash). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tests-glamsterdam-devnet@v6.1.1 ships for_bpo2tobpo3attime15k and for_bpo3tobpo4attime15k under both blockchain_tests and blockchain_tests_engine, but Tests.cs stopped at Bpo2ToAmsterdam, so these transition fixtures were never run in CI - which is how the BPO3 fork-lineage bug went unnoticed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tests-glamsterdam-devnet ships for_tangerinewhistle and for_spuriousdragon under blockchain_tests and state_tests, but Tests.cs had no fixture classes for them, so they never ran. Completes the class-per-directory mapping: every for_* dir in the archive now has a matching fixture class across all five fixture trees. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nto fix/bpo-fork-lineage
92fb8fb to
f50396d
Compare
EVM Opcode Benchmark DiffAggregated runs: base=3, pr=3 No significant regressions or improvements detected. |
Changes
BPO3fromAmsterdam.InstancetoBPO2.Instance. BPO forks are blob-parameter-only forks chainedBPO1→BPO2→BPO3→BPO4→BPO5, with Amsterdam a parallel branch (matching the execution-spec-tests fork lineage). Inheriting Amsterdam wrongly enabled EIP-7928 (and every other Amsterdam EIP) on BPO3/BPO4/BPO5, so BPO2→BPO3 transition blocks demanded a BAL hash and failed withMissingBlockLevelAccessListHash.ForkTests.Bpo_forks_are_blob_only_and_do_not_inherit_Amsterdamasserting the BPO parent chain and that EIP-7928 stays Amsterdam-only.Bpo2ToBpo3AtTime15k/Bpo3ToBpo4AtTime15k(blockchain + engine variants) toEthereum.Blockchain.Pyspec.Test/Tests.cs.tests-glamsterdam-devnet@v6.1.1shipsfor_bpo2tobpo3attime15kandfor_bpo3tobpo4attime15kunder bothblockchain_tests/andblockchain_tests_engine/, butTests.csstopped atBpo2ToAmsterdamAtTime15k, so these transition fixtures were never run in CI — which is how the fork-lineage bug went unnoticed.TangerineWhistle/SpuriousDragonblockchain + state fixture classes: an audit of the archive foundfor_tangerinewhistleandfor_spuriousdragonunderblockchain_tests/andstate_tests/also had no fixture classes. Everyfor_*directory in the archive now maps to a fixture class across all five fixture trees (blockchain, engine, sync, state, transaction).Types of changes
What types of changes does your code introduce?
Testing
Requires testing
If yes, did you write tests?
Notes on testing
ForkTestspass, including the new lineage regression test.FullyQualifiedName~Bpo2ToBpo3AtTime15k|FullyQualifiedName~Bpo3ToBpo4AtTime15k); without the reparent these fail withMissingBlockLevelAccessListHash.AmsterdamParallel/AmsterdamBatchReadvariants by name.Documentation
Requires documentation update
Requires explanation in Release Notes
Remarks
The same
BPO3(Amsterdam.Instance)bug exists onmaster, but the fixture classes must not be added there: master pinstests-bal@v7.2.0, which has nofor_bpo2tobpo3attime15k/for_bpo3tobpo4attime15kdirs. The spec fix alone can be cherry-picked to master separately.🤖 Generated with Claude Code