Skip to content

refactor(machine_state): split into Frame / Env / Substate#132

Merged
mw2000 merged 3 commits intomainfrom
refactor/split-machine-state
May 1, 2026
Merged

refactor(machine_state): split into Frame / Env / Substate#132
mw2000 merged 3 commits intomainfrom
refactor/split-machine-state

Conversation

@mw2000
Copy link
Copy Markdown
Owner

@mw2000 mw2000 commented May 1, 2026

Summary

Splits the monolithic MachineState envelope into three sub-structs that match the three lifecycles already implicit in the EVM:

  • Frame (state.frame) — per-call mutable: pc, stack, memory, gas, refund, code, return_data, contract, depth, is_static, parent return write-back location. Replaces and unifies the now-removed CallFrame.
  • Env (state.env) — per-call immutable: tx, block, hardfork config.
  • Substate (state.substate) — transaction-scoped accumulators: touched / accessed / created addresses, original storage, transient storage, logs.

Top-level on MachineState keeps only what crosses these boundaries: frame, env, substate, db, call_stack, status, tracer.

Stacked as three commits, one per phase:

  • af4d6ac — phase 1: extract Substate
  • 09a1110 — phase 2: extract Env
  • 9dbbf9c — phase 3: extract Frame, remove CallFrame

All opcode modules, handlers, and helpers now read fields through state.frame.X / state.env.X / state.substate.X and write via MachineState.update_frame/2. pop_frame carries child refund forward into the restored parent frame so the old envelope-level refund accumulation semantic is preserved.

Test plan

  • mix compile — clean
  • mix credo --strict — no issues
  • mix test — 4 doctests + 613 tests, 0 failures
  • StateTest harness still green

🤖 Generated with Claude Code

mw2000 and others added 3 commits April 30, 2026 22:42
Move the seven transaction-scoped accumulator fields out of MachineState
into a dedicated Substate struct: touched_addresses, accessed_addresses,
accessed_storage_keys, created_addresses, original_storage,
transient_storage, logs. These all share the same lifecycle — accumulate
across successful child frames, revert together on failure — so grouping
them simplifies Journal.merge_child_result and clarifies what is and
isn't substate per the Yellow Paper.

No behavioural change: every field keeps its name and semantics; only the
access path moves from state.X to state.substate.X.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Group the three immutable per-call inputs — tx, block, config — under a
single `env` field. They share a lifecycle (set on frame construction,
never mutated, inherited unchanged by children), so collapsing them
makes the distinction between "what evolves" (frame, substate) and "what
the call observes" (env) explicit at every access site.

Public API unchanged: `MachineState.new/2` still takes `tx:`, `block:`,
`config:` as flat keyword opts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Splits the per-call execution frame out of MachineState into its own
struct at lib/eevm/interpreter/machine_state/frame.ex, completing the
three-way split of the envelope into frame / env / substate.

Frame holds the per-call mutable execution context — pc, stack, memory,
gas, refund, code, return_data, contract, depth, is_static, plus the
parent-memory return write-back location. The active frame lives at
state.frame; suspended parent frames use the same struct in
state.call_stack. CallFrame is removed and its single usage replaced.

All opcode modules, handlers, and tests now read these fields through
state.frame.X and write via MachineState.update_frame/2 (which threads
the closure over the active frame). pop_frame now also carries the
child's refund forward into the restored parent frame, preserving the
old envelope-level refund accumulation semantic.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@mw2000 mw2000 merged commit fc52900 into main May 1, 2026
3 checks passed
@mw2000 mw2000 deleted the refactor/split-machine-state branch May 1, 2026 06:54
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.

1 participant