Skip to content

Merge upstream changes - #56

Open
pdobacz wants to merge 60 commits into
forks/monad_ninefrom
from-upstream
Open

Merge upstream changes#56
pdobacz wants to merge 60 commits into
forks/monad_ninefrom
from-upstream

Conversation

@pdobacz

@pdobacz pdobacz commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

IMPORTANT: Merge with MERGE COMMIT!

NOTE: I'm adding a skill to perform this task with an agent: docs(skills): add the upstream merge skill

Greptile Summary

This PR merges a broad upstream execution-specification update into the Monad branch.

  • Updates fixture generation, EngineX pre-allocation grouping, hashing, SSZ handling, fork metadata, and execution-testing utilities.
  • Propagates upstream CREATE-collision behavior through the Monad forks and removes the obsolete storage-presence state interface.
  • Adds and revises Amsterdam protocol tests, ported static tests, documentation, and repository-agent skills.

Confidence Score: 5/5

The PR appears safe to merge because no concrete, changed-code-triggered defect remains after reviewing the runtime, fixture-generation, state-interface, and dependency changes.

The pre-allocation producer and consumer contracts remain aligned across packed and non-packed modes, and the Monad CREATE behavior consistently follows the upstream protocol decision to remove storage-only collisions.

Important Files Changed

Filename Overview
packages/testing/src/execution_testing/fixtures/pre_alloc_groups.py Reworks typed pre-allocation hashes, worker-file merging, compatible-group packing, index generation, and lazy group loading without an accepted correctness issue.
packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/filler.py Integrates the new two-phase grouping flow and reports EngineX consistency failures through pytest’s exit status and terminal summary.
packages/testing/src/execution_testing/fixtures/engine_x_checks.py Expands EngineX fixture consistency validation and explicit skip diagnostics; no concrete changed-code failure was established.
packages/testing/src/execution_testing/base_types/ssz.py Generalizes SSZ fork-schema keys from strings to opaque hashable values for direct fork-class use.
src/ethereum/forks/monad_nine/vm/instructions/system.py Aligns Monad CREATE collision handling with the upstream removal of the declined storage-only collision rule.
src/ethereum/state.py Removes the obsolete account_has_storage protocol method after storage-only CREATE collisions were dropped.
uv.lock Refreshes resolved dependencies, with no repository-reachable security consequence established from the changed resolution.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  T[Test pre-state] --> H[Compute phase-one group hash]
  H --> M[Merge worker partial groups]
  M --> P[Pack compatible groups]
  P --> I[Test-to-group index]
  I --> L[Phase-two group lookup]
  L --> F[Generate EngineX fixture]
  P --> C[Pre-allocation group file]
  C --> F
  F --> V[Execution consistency check]
Loading

Reviews (1): Last reviewed commit: "docs(skills): list the fork's own skills..." | Re-trigger Greptile

marioevz and others added 30 commits August 19, 2026 11:10
…ons (ethereum#3399)

Add `test_bal_cross_tx_reverted_storage_reads`: two transactions each
`SSTORE` a different slot on the same account in a frame that reverts,
so the account's block-level `storage_reads` must hold both slots.

Reported in erigontech/erigon#23407.
…tion (ethereum#3421)

Clearing a delegation resets the authority's code and must leave its
storage untouched. Every existing fixture that clears a delegation has an
authority with empty storage, so the storage half of the rule was never
asserted.

Put both the delegation designation and a non-empty slot in the
pre-state, so the delegation is older than the block being executed, and
assert the slot survives three ways: on its own, after clearing and
re-delegating in one authorization list, and when read back by a later
transaction of the same block.

The read-back cases pin more than the post state: touching the
authority's storage in the same block as the clear forces the live slot
set to be consulted, and writing a previously untouched slot forces the
storage root to be recomputed from that set.
…reum#3420)

Parametrize the direct precompile call made by a frame that was entered
through a 7702 delegation over CALL, CALLCODE, DELEGATECALL and
STATICCALL; only the CALL variant was covered before.

The frame calls the identity precompile and stores the call result,
RETURNDATASIZE and the echoed word, so the precompile's execution is
pinned by its output rather than only by a gas difference, which keeps
the observable meaningful under STATICCALL.
* perf(test-client-clis,test-specs): don't verify the BAL hash against itself

* chore: clean up comment

---------

Co-authored-by: LouisTsai <q1030176@gmail.com>
…over (ethereum#3431)

* feat(tests): ensure pubkey isn't calculated twice

* feat: signing optimization

* test: add key, addr mismatch scenario

---------

Co-authored-by: LouisTsai <q1030176@gmail.com>
Co-authored-by: danceratopz <danceratopz@gmail.com>
…erification (ethereum#3383)

Co-authored-by: spencer-tb <spencer.tb@ethereum.org>
Make StorageAction a proper Enum instead of a plain class holding bare
auto() sentinels (which only worked by object identity), and fix the stale
"Returns: (bytecode, loop_cost, overhead)" docstrings in
create_storage_initializer / create_benchmark_executor, which return a
single IteratingBytecode.
* feat(fill): Make pre-alloc groups packing optional

* fix(bug): Bug due to untyped structs

* nit

* claude findings

* claude updated docs

* fix: backwards compatible index reading

* fix: properly skip amsterdam skip list for engine x

* fix: bug saving pre-alloc group builder as final product

* fix: hasher

* fix: typo

* fix: chain ID typing

* fix: unit test

* fix: remove `env` from the final pre-alloc group

* fix: Review comments

Co-authored-by: danceratopz <danceratopz@gmail.com>

---------

Co-authored-by: danceratopz <danceratopz@gmail.com>
* feat: implement placeholder

* test: add more placeholder cases

* refactor: fix opcode listing issue

* fix: refactor

* fixes: Make `substitute` in-place, guard `bytes` method

* fix: Exception types in bytecode.py

---------

Co-authored-by: marioevz <marioevz@gmail.com>
…& misc tests (Pt. 2c) (ethereum#3321)

* fix(tests): enhance & un-skip Amsterdam ported static SSTORE, refund & misc tests (Pt. 2c)

* refactor(tests): Further refactor tests and expand coverage

* fix(test-forks): Add EIP-160 mixin

* fix(test-forks): Fix CODE_INIT_PER_WORD pre-Shanghai

---------

Co-authored-by: marioevz <marioevz@gmail.com>
* refactor: state gas call scenario

* refactor: state gas calldata floor scenario

* refactor: state gas multi block scenario

* refactor: state gas ordering scenario

* refactor: state gas pricing scenario

* refactor: state gas sstore scenario

* tests: more fixes, added coverage

---------

Co-authored-by: marioevz <marioevz@gmail.com>
…RACT_EMPTY (ethereum#3465)

Geth rejects blocks whose request system call targets a codeless contract with
"failed to process <queue>: empty system contract: no code at <addr>" (since
ethereum/go-ethereum#35514), which GethExceptionMapper could not map.

Claude-Session: https://claude.ai/code/session_015PPcN9JS3yMPYWCYqusrEm
…ereum#3459)

`R == -G` is the input class where the Shamir/interleaved-MSM
precomputation `P + Q` (with `P = G`, `Q = R`) is the point at infinity.
Implementations that special-case it reduce `u1*G + u2*R` to
`(u1 - u2)*G`, which branches on the ordering of `u1` and `u2`.

Only `u1 > u2` was covered. Add the two neighbouring cases:

- `u1_lt_u2_R_eq_neg_G`: `u1 = 1`, `u2 = 2`, so the difference is
  negative and the recovered key is `-G`.
- `u1_eq_u2_R_eq_neg_G`: `u1 == u2`, so the recovered point is the point
  at infinity and the precompile returns empty.

Fixes ethereum#3458
The first stable release of ethereum-hive; it pools Hive API connections in a shared keep-alive session, which fixes sporadic `EADDRNOTAVAIL` failures and silently lost test results at high simulator throughput (ethereum/hive-python-api#18).
spencer-tb and others added 27 commits August 31, 2026 20:31
…eum#3480)

* fix(test-forks): price pre-Berlin account and storage access flat in the opcode gas model

Claude-Session: https://claude.ai/code/session_01YN5aAKMhVpZwfFYXAKEuxp

* fix(test-forks): model the pre-Berlin SSTORE, call value and refund schedules

Claude-Session: https://claude.ai/code/session_01YN5aAKMhVpZwfFYXAKEuxp

* fix(tests): use the metadata call cost in the byzantium precompile gas tests

Claude-Session: https://claude.ai/code/session_01YN5aAKMhVpZwfFYXAKEuxp
* feat(tests): add type-0 transaction RLP validity tests

Port the core malformation classes of the legacy TransactionTests
suites (ttWrongRLP, ttNonce, ttValue, ttRSValue, ttVValue, ttAddress),
which were never converted because the ported-static pipeline only
handles state-test fillers and the raw malformed bytes cannot
round-trip through a structured transaction model.

A local RLP encoder builds each corruption deliberately, since a
correct encoder cannot emit non-canonical forms: per-field leading
zeros, 33-byte field overflows, 19 and 21 byte addresses, fields
encoded as lists, structural corruptions of the outer list (truncation,
trailing bytes, wrong element counts, header size mismatches, size
with leading zeros), and well-encoded but invalid signature values.
A valid re-encoded control case anchors the encoder to the framework's
byte-exact output.

The transaction_test fixture format records the declared exception
without consulting the transition tool, so all 30 cases were verified
externally by feeding the generated fixture bytes through EELS
decode_transaction, recover_sender and validate_transaction at
Frontier, London and Cancun: every invalid vector is rejected and the
control is accepted with the matching sender. Notably the gas limit
and gas price are unbounded scalars in the spec, so their oversized
encodings are valid at the transaction level; the overflow cases cover
the 256-bit bounded fields (nonce, value, r, s) only.

* fix(tests): accept client-divergent transaction RLP exceptions

Declare exception lists where clients legitimately report different
errors for the same malformed transaction:

- `header_declares_less`: the mutation leaves both a truncated final
  field and a trailing byte at the top level, so clients report it as
  either an EOF or a size error.
- `v_29`: post EIP-155 clients may derive a chain id from any v other
  than 27 or 28 and reject the mismatch instead of the signature, as
  already documented in `test_bad_v_r_s`.

* chore(tests): correct the transaction field overflow docstring

The nonce is decoded as a 256-bit scalar by the spec; the 64-bit bound
is an EIP-2681 validation rule, not a decoding one. Also note that the
signature v is a bounded 256-bit field whose oversized encoding is
uncovered only because no field-specific decoding exception exists.

* feat(tests): add r and s field-as-list transaction RLP cases

Extend `test_field_as_list` to the signature r and s fields, porting
`TRANSCT_rvalue_GivenAsListCopier` and `TRANSCT_svalue_GivenAsListCopier`
with the same `RLP_INVALID_SIGNATURE_R`/`_S` exceptions the legacy
suite declares. The gas price and v fields remain uncovered for lack
of a field-specific decoding exception.

* feat(tests): add a non-canonical single-byte transaction RLP case

Encode the single-byte nonce payload behind a one-byte string header
(0x8101) instead of as the byte itself. This ports the
`RLPIncorrectByteEncoding{00,01,127}Copier` legacy tests, which corrupt
the nonce this way and declare `RLP_LEADING_ZEROS_NONCE_SIZE`.

* feat(tests): add a data size leading zeros transaction RLP case

Encode the size of the data field's long-form string header with a
leading zero byte, porting `RLPArrayLengthWithFirstZerosCopier` with
the `RLP_LEADING_ZEROS_DATA_SIZE` exception it declares. This covers
the string-header variant of the list-header case already tested by
the `list_size_leading_zeros` mutation.

* feat(tests): add a zero v transaction signature case

A zero v is well-encoded (empty payload) but is neither 27, 28 nor an
EIP-155 value. Declare `INVALID_CHAINID` as an acceptable alternative
for the same reason as the other invalid v cases: post EIP-155 clients
may derive a chain id from any v other than 27 or 28.

* chore(tests): cite more covered legacy transaction test fillers

Add `ported_from` references for legacy fillers whose malformation
class is already exercised by an existing case:

- Leading zeros: the `tt{Nonce,GasPrice,GasLimit,Value}` zero-prefixed
  fillers and the `TRANSCT_*_Prefixed0000` copiers.
- Overflow: the `TRANSCT_{r,s}value_TooLarge` copiers.
- Address size: `AddressMoreThan20` and the `TRANSCT_to_*` copiers.
- Field as list: the remaining `TRANSCT_*_GivenAsList` copiers.
- Structure: `RLPTransactionGivenAsArray`, matching the
  `tx_as_byte_string` mutation.

All referenced fillers were inspected at the pinned commit to confirm
the corruption and declared exception match the covering case.

* fix(tests): fund only senders that send in transaction RLP tests

In execute mode, `pre.fund_eoa()` defers the funding amount until the
EOA sends a transaction; an EOA that never sends one fails the run
with "Sender balance must be set before sending". The senders of the
corrupted transactions never send: only their raw serialization is
submitted, expecting rejection. Fund them with `amount=0` so execute
mode derives an address without scheduling a funding transaction.

The signing keys are derived from the account content, so the
corrupted vectors' bytes change; all vectors were re-verified against
EELS decoding and validation at Frontier, London and Cancun.

* chore(tests): mark transaction RLP tests as inclusion tests

Each case asserts whether one transaction can be included in a block,
which is what the `inclusion_test` marker denotes.

* fix(tests): accept a type error for a transaction given as a byte string

EIP-2718 reads a byte string in the transaction list as a typed
transaction, so from Berlin on the corruption is reported as an
unsupported transaction type rather than an RLP header error. Verified
against EELS decoding at Frontier, Berlin and Cancun.

---------

Co-authored-by: danceratopz <danceratopz@gmail.com>
No spec-specific constants were useful to add here. This may change but
the import from the relevant spec is preferred over adding them here if they
are not BALs specific.
ethereum#3490)

* feat(tests): pin cross-frame state gas refund placement and settlement

* feat(tests): EIP-8037 cross-frame refund split across a child's own spill

Test that one frame's refund both repays a different slot's borrow and
puts the excess in the reservoir, that the split state merges cleanly
on success, and that it is fully unwound on revert and halt.

* chore(tests): use fork transaction gas limit cap, not constant val

* fix: apply comments from PR ethereum#3490

---------

Co-authored-by: fselmo <fselmo2@gmail.com>
* refactor: state gas create scenario

* feat(tests): Add more variants

---------

Co-authored-by: marioevz <marioevz@gmail.com>
…by the target fork (ethereum#3488)

Co-authored-by: danceratopz <danceratopz@gmail.com>
…calars (ethereum#3486)

* feat(tests,test-specs): EIP-7928 - reject non-minimally encoded BAL scalars

* feat(tests,test-specs): EIP-7928 - cover every non-minimally encoded BAL scalar

* fix(clis): map besu's block access list decode error

With besu-eth/besu#11216, besu answers a block access list that fails
RLP decoding with {status: INVALID} and the validationError "Failed to
decode block access list payload parameter (...)", as execution-apis#869
requires for engine_newPayloadV5. No pattern matched that message, so a
besu that correctly rejects the payload failed with an undefined
exception instead. Geth's and Nethermind's equivalents were already
mapped.

* fix(test-specs): make BAL scalar leaf lookup explicit and unit-test encoding modifiers

* feat(tests,test-specs): cover non-minimal block_access_index and nonce encodings

* feat(tests,test-specs): cover the header committing to non-minimal BAL bytes

* fix(test-specs): refuse RLP blockchain fixtures for payload-only BAL re-encodings

---------

Co-authored-by: fselmo <fselmo2@gmail.com>
…#3510)

* fix(test-specs): refuse BAL modifiers on blocks that declare no failure

* fix(test-specs): refuse an explicit payload BAL alongside modify_rlp

* fix(test-specs): refuse undeliverable BAL re-encodings after the block is built

* fix(test-specs): refuse BAL modifiers that leave the list unchanged

* test(test-specs): pin what a filled engine payload's block hash commits to

* fix(test-specs): refuse a second modify or modify_rlp on the same expectation

* fix(test-specs): name the misuse when a BAL modifier returns the wrong kind

* fix(test-specs): name blocks consistently in the BAL guards and accept hex overrides

* fix(test-specs): refuse modify_rlp after override_rlp on the same block

* test(test-specs): tighten the BAL guard tests after review

* chore: fixes from comments on PR ethereum#3510
* feat(tests): EIP-6110 maximum CL deposits test

* Update tests/prague/eip6110_deposits/test_deposits.py

Co-authored-by: spencer <spencer.tb@ethereum.org>

* fix: Review comments

Co-authored-by: spencer <spencer.tb@ethereum.org>

---------

Co-authored-by: spencer <spencer.tb@ethereum.org>
… enginex consistency check (ethereum#3265)

Co-authored-by: danceratopz <danceratopz@gmail.com>
)

Co-authored-by: danceratopz <danceratopz@gmail.com>
Conflict markers are committed as-is; resolved in the follow-up commit.

Co-Authored-By: Claude <claude-opus-5>
Union the split imports, keep the Monad ported_static opt-out and the
runloop env overrides, drop the conftest orphaned by the removal of the
EIP-7610 tests, and move the fork's adopt-upstream-eip skill into the
shared .agents/skills layout.

Co-Authored-By: Claude <claude-opus-5>
Drop EIP-7610's storage-only create collision, whose PreState hook
upstream removed, and the stale get_last_256_block_hashes TODO.

Co-Authored-By: Claude <claude-opus-5>
The flag took the literal `--stdin`, which argparse read as an option
rather than a value, so every `statetest` run died in the parser.

Co-Authored-By: Claude <claude-opus-5>
Co-Authored-By: Claude <claude-opus-5>
Co-Authored-By: Claude <claude-opus-5>
@pdobacz
pdobacz requested review from QEDK and mijovic as code owners September 3, 2026 15:39
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedethereum-hive@​0.1.0a5 ⏵ 0.1.09910010010070

View full report

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.