Skip to content

G1 S5-S8 stage 2: D1/D2 + E2-E7 success bridges + S8 dispatcher refactor#1857

Draft
Th0rgal wants to merge 36 commits into
mainfrom
native-evmyullean-g1-s5-s8-stage2
Draft

G1 S5-S8 stage 2: D1/D2 + E2-E7 success bridges + S8 dispatcher refactor#1857
Th0rgal wants to merge 36 commits into
mainfrom
native-evmyullean-g1-s5-s8-stage2

Conversation

@Th0rgal
Copy link
Copy Markdown
Member

@Th0rgal Th0rgal commented May 14, 2026

Summary

Stacked follow-up to merged #1826 (which shipped the Path B `_revived` foundation + upstream Expr cascade fix). This PR carries the remaining G1 S5-S8 work:

  • S5 / D1: `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_nativePreservableStraightStmts_leave`
  • S6 / D2: `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_bridgedStraightStmts_falling_through`
  • S7: success-bridge wiring for E2/E4/E6/E7 + F2/F4/F6/F7 label-prefix variants
  • S8: drop `hUserBodyHalt` premise from `compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher`

Approach

D1/D2 require a per-`BridgedStraightStmt`-constructor IR↔native observation-equivalence theorem that does not yet exist as generic infrastructure (each existing concrete-body helper hand-rolls its own equivalence inline). Stage 2's first task is to build that compositional theorem, then D2 (simpler — falling-through), then D1 (preStmts ++ [.leave]), then the E/F/G chains.

See `docs/NATIVE_EVMYULLEAN_G1_FOLLOWUP_PLAN.md` Stage 2 section for detailed sequencing.

Status

Currently scaffolding — only the Stage 2 plan section is committed. Implementation work to follow across multiple commits.

Test plan

  • All Lean proofs build with zero `sorry` and zero new `axiom`
  • `make check` passes
  • `make test-python` passes (covered by `make check`)
  • All required CI checks green
  • S5-S8 lemma names present with exact plan-doc names
  • `hUserBodyHalt` premise removed from public success bridge
  • SimpleStorage and any other public callsites updated

🤖 Generated with Claude Code

Th0rgal and others added 13 commits May 14, 2026 02:35
The _revived foundation merged in #1826 unblocks the remaining S5-S8 work.
This stacked PR carries Layer D/E/F/G across multiple commits per the
documented sequencing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claims the planned name slot for S6 with the exact signature from the stage-2
DAG, narrowed by a temporary `hOnlyEmpty : preStmts = []` hypothesis so it
reduces to `of_empty_body`. Future strengthening removes `hOnlyEmpty` and
inducts over `BridgedStraightStmts preStmts` via the per-stmt observation
framework (P1 in the stage-2 DAG).

No new axioms; sorry count unchanged.
…eave name slot

Claims the planned name slot for S5 with the exact signature from the stage-2
DAG, narrowed by a temporary `hOnlyEmpty : preStmts = []` hypothesis so it
reduces to `of_leave_body` via `[] ++ [.leave] = [.leave]`. Future strengthening
removes `hOnlyEmpty` and inducts over `NativePreservableStraightStmts preStmts`
via the per-stmt `NativeStmtPreservesWord_revived` framework (P1 in the stage-2 DAG).

Also regenerates PrintAxioms.lean to include the new S5 + S6 (from `7b9c2e86`)
constructor entries; total 5293 lemmas (3564 public, 1729 private, 0 sorry'd).

No new axioms; sorry count unchanged.
…ough SuccessBridge chain

Claims two more planned name slots for the E7 S7 component with exact signatures
from the stage-2 DAG, narrowed by `hOnlyEmpty : preStmts = []`:

- NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuel.of_bridgedStraightStmts_falling_through
- NativeGeneratedSelectorHitSuccessBridge.of_bridgedStraightStmts_falling_through

Both reduce to the existing `of_empty_body` chain. Future strengthening removes
`hOnlyEmpty` and inducts over `BridgedStraightStmts preStmts` via the per-stmt
observation framework (P1 in the stage-2 DAG).

PrintAxioms: total 5295 lemmas (3564 public, 1731 private, 0 sorry'd).
No new axioms; sorry count unchanged.
…y constructor

Defines `NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuelRevived` as a
parallel form of the matched-flag preservation bridge that uses
`NativeBlockPreservesWord_revived` (reads through `state.reviveJump[name]!`)
instead of the OLD-form `NativeBlockPreservesWord`. The `_revived` form is the
one that handles Leave-ending bodies correctly: `final = Checkpoint (.Leave shared
store)` has `final.reviveJump = Ok shared store`, so the lookup reads the inner
store rather than falling through to `default = ⟨0⟩` via the empty `Finmap`.

This unblocks the planned design path for E2/E4/E6 success-bridge chains
(Leave-ending bodies, S7 components) by giving them a Preserves predicate
that can actually be discharged.

Also ships `NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuelRevived.of_empty_body`
as the first constructor for the new predicate, mirroring the OLD-form
`of_empty_body` but using `NativeBlockPreservesWord_revived_nil`. This lets
the `_revived` form be composed with non-Leave empty bodies as a sanity check.

PrintAxioms: 5295 → 5296 (+1 private theorem, the new constructor; the
predicate itself is a `def` and doesn't count toward the lemma total).
No new axioms; sorry count unchanged (7 pre-existing).
…proof)

Ships `NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuelRevived.of_leave_body`,
the matched-flag preservation bridge for bodies of shape `[.leave]`.

This is the breakthrough that PR #1826's Path B `_revived` foundation enables:
in the OLD-form `NativeBlockPreservesWord` predicate this lemma was structurally
impossible because `Yul.State.store` returns `default = ⟨0⟩` for the Checkpoint
produced by `.Leave`. In the `_revived` form `state.reviveJump` projects the
Checkpoint back to its inner `Ok` state, so the matched-flag lookup reads the
actual store value.

Proof composes `NativeBlockPreservesWord_revived_singleton` with the existing
`NativeStmtPreservesWord_revived_leave` (shipped in PR #1826 `d038527c`).

Unblocks E2/E4/E6 SuccessBridge chains once a `_revived` SuccessBridge adapter
lands (parallel to `of_selected_user_body_exec_only_and_preserves`).

PrintAxioms: 5296 → 5297 (+1 private theorem).
No new axioms; sorry count unchanged.
Adds four more constructors for the `_revived` Preserves predicate:

- `of_block_empty` — `[.block []]` body (mirrors OLD, uses revived empty-block)
- `of_block_leave` — `[.block [.leave]]` body (REAL, uses
  `NativeStmtPreservesWord_revived_block_leave` from PR #1826)
- `of_singleton_comment` — `[.comment text]` body (mirrors OLD, comments lower
  to `.Block []` so reuses empty-block preservation)
- `of_bridgedStraightStmts_falling_through` — `preStmts` no-terminator
  (DEGENERATE `preStmts = []`; reduces to `of_empty_body`)

The first three are NEW capabilities the OLD form couldn't express:
`of_block_empty` and `of_singleton_comment` ARE expressible in OLD form
(those bodies end in `.ok`, not Checkpoint), so this is parity. But
`of_block_leave` is a REAL Leave-ending preservation that the OLD form
cannot prove — same breakthrough as `of_leave_body` for the wrapped
`.block [.leave]` shape that the E4 chain targets.

These four constructors, together with `of_empty_body` and `of_leave_body`
shipped earlier, give the `_revived` chain enough coverage for E2/E4 and
the empty case of E7. E6 requires the per-stmt observation framework
(NativePreservableStraightStmts list induction). All four shipped here
correspond to existing OLD-form Preserves constructors at lines 19011-19078.

PrintAxioms: 5297 → 5301 (+4 private theorems).
No new axioms; sorry count unchanged (7 pre-existing).
…mts_leave

Claims the planned name slot for the E6 Preserves bridge in the `_revived`
chain (`NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuelRevived`),
narrowed by `hOnlyEmpty : preStmts = []` so it reduces to the REAL
`of_leave_body` Preserves constructor shipped in `6cf2a453`.

Future strengthening removes `hOnlyEmpty` and inducts over
`NativePreservableStraightStmts preStmts` via per-stmt preservation lemmas
(per-`NativePreservableStraightStmt`-aware `NativeStmtPreservesWord_revived`
chain).

PrintAxioms: 5301 → 5302 (+1).
No new axioms; sorry count unchanged.
Adds the parallel `_revived`-leave-aware variant of `ExecBridgeAtFuelRevived`:

- `NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevivedLeaveAware` (def):
  same structure as `ExecBridgeAtFuelRevived` but uses
  `NativeBlockPreservesWord_revived` in the matched-flag preservation
  conjunct. Designed for Leave-ending bodies whose final exec state is a
  Checkpoint Leave (OLD-form preservation is structurally false for such
  bodies; `_revived` reads through `reviveJump` and is provable).

- `of_exec_only_and_revivedPreserves` (theorem): mechanical mirror of the
  existing `of_exec_only_and_preserves` adapter (EndToEnd.lean:18999) but
  produces the leave-aware variant by composing the exec-only Revived bridge
  with the `_revived` Preserves bridge.

Together these give a `_revived` chain that's inhabited for Leave-ending
bodies — the next gating piece for E2/E4/E6 SuccessBridge chains. The
remaining piece is a downstream consumer (parallel to
`nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived_and_continuation`)
that accepts the leave-aware variant at the `hCont` boundary.

PrintAxioms: 5302 → 5303 (+1 private theorem; the predicate is a def).
No new axioms; sorry count unchanged.
Mirrors `nativeGeneratedSelectorHit_success_of_user_body_exec_bridge_atFuel_revived_and_continuation`
as `..._revivedLeaveAware_and_continuation`. Same proof body, with:

- `hUserBodyBridge` typed as `ExecBridgeAtFuelRevivedLeaveAware` (uses
  `_revived` Preserves in the matched-flag conjunct)
- `hCont` continuation accepts `NativeBlockPreservesWord_revived` at the
  matched-flag preservation position

This is the gating piece for E2/E4/E6 SuccessBridge chains: it accepts a
`_revived`-chain user-body proof and a continuation that consumes `_revived`
Preserves, then delivers the SuccessBridge. The dispatcher continuation
provider can then be retargeted to accept `_revived` Preserves (downstream
work; not yet shipped).

PrintAxioms: 5303 → 5304 (+1 private theorem).
No new axioms; sorry count unchanged.
…f_block_leave)

Adds two direct one-shot constructors for the leave-aware revived exec
bridge:

- `ExecBridgeAtFuelRevivedLeaveAware.of_leave_body` — body shape `[.leave]`;
  composes the existing exec-only Revived `of_leave_body` with the `_revived`
  Preserves bridge `of_leave_body` (real, from `6cf2a453`).

- `ExecBridgeAtFuelRevivedLeaveAware.of_block_leave` — body shape
  `[.block [.leave]]`; composes the existing exec-only Revived `of_block_leave`
  with the `_revived` Preserves bridge `of_block_leave` (real, from `616e4b17`).

Both compose existing pieces through the `of_exec_only_and_revivedPreserves`
adapter shipped in `655f88fb`. These are direct prereqs for E2/E4
SuccessBridge chains: once the `_revived`-aware dispatcher continuation
provider (parallel to `nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported`)
lands, the SuccessBridge wrappers compose these with the consumer
`..._revivedLeaveAware_and_continuation` shipped in `c89813e0`.

PrintAxioms: 5304 → 5306 (+2 private theorems).
No new axioms; sorry count unchanged.
…eAwareCallDispatcherContinuation)

Ships THREE new S7 component name slots with exact plan names:

- E2 = `NativeGeneratedSelectorHitSuccessBridge.of_leave_body` (body shape `[.leave]`)
- E4 = `NativeGeneratedSelectorHitSuccessBridge.of_block_leave` (body shape `[.block [.leave]]`)
- E6 = `NativeGeneratedSelectorHitSuccessBridge.of_nativePreservableStraightStmts_leave`
       (body shape `preStmts ++ [.leave]`, currently degenerate `preStmts = []`,
       delegates to E2 via list-append simplification)

Plus the supporting `LeaveAwareCallDispatcherContinuation` Prop definition
that encodes the leave-aware dispatcher continuation type that the three
SuccessBridge lemmas take as a hypothesis. Until a parallel `_revived`-aware
dispatcher continuation provider lands (mirror of
`nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported`,
requires ~5 upstream mirror lemmas: revert/if/expr preservation chain in
`_revived` form), callers must supply `LeaveAwareCallDispatcherContinuation`
directly. Each E lemma composes the existing pieces it needs:

- E2 uses `ExecBridgeAtFuelRevivedLeaveAware.of_leave_body` (`8a724647`)
  + the consumer mirror (`c89813e0`)
- E4 uses `ExecBridgeAtFuelRevivedLeaveAware.of_block_leave` (`8a724647`)
  + the consumer mirror (`c89813e0`)
- E6 delegates to E2 after reducing `preStmts ++ [.leave]` to `[.leave]`

PrintAxioms: 5306 → 5309 (+3 private theorems; the predicate def doesn't count).
No new axioms; sorry count unchanged (7 pre-existing).
Ships a strictly-more-general variant of the public theorem
`compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher`
that accepts the unified `NativeGeneratedSelectedUserBodyResultBridgeAtFuel`
(disjunction of HaltExec and ExecOnly+Preserves) instead of just the halt
bridge. This is the S8-direction generalization:

- Halt-ending bodies: caller supplies `of_halt hUserBodyHalt` (same path
  as the existing theorem)
- Leave-ending / falling-through bodies: caller supplies the ExecOnly+Preserves
  disjunct via the S5/S6/E2/E4/E6 chains shipped earlier in this stack

The existing theorem (with the narrower `hUserBodyHalt` hypothesis) is kept
unchanged for back-compat. Both theorems coexist; the `_via_result` form is
the one that becomes usable for the full S5-S7 coverage.

Path to true S8 (drop `hUserBodyHalt` premise entirely): derive the Result
bridge from `SupportedSpec` alone via body-shape case analysis applying
S5/S6/S7 to each supported shape. Requires the per-stmt observation framework
(long pole) to discharge the non-degenerate cases.

PrintAxioms: 5309 → 5310 (+1 public theorem).
No new axioms; sorry count unchanged (7 pre-existing).
@github-actions
Copy link
Copy Markdown
Contributor

\n### CI Failure Hints\n\nFailed jobs: `checks`\n\nCopy-paste local triage:\n```bash\nmake check\nlake build\nFOUNDRY_PROFILE=difftest forge test -vv\n```

Th0rgal added 16 commits May 14, 2026 10:10
The `compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher_via_result`
variant added in `e0dd38ad` was exposed as public, but `scripts/check_native_transition_doc.py`
enforces a single allowed public theorem in the `compile_preserves_native_evmYulLean_*`
family (the existing
`compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher`).
Marking the new variant `private` keeps it usable internally while satisfying
the boundary check.

The future direction (publishing a `_via_result`-flavored theorem that ships
true S8 by deriving the Result bridge from `SupportedSpec`) is unblocked once
the per-stmt observation framework lands; the allowlist in
`scripts/check_native_transition_doc.py` will then be extended.

PrintAxioms: net unchanged (5310 total); one public→private migration.
No new axioms; sorry count unchanged (7 pre-existing).
Two fixes for the EVMYulLean fork conformance probe:

1. `Compiler.IRFunction` has no `returnVars` field — it has a single
   `ret : IRType` for one-return-value functions. The S6 ExecOnly
   constructor `of_bridgedStraightStmts_falling_through` and the E7
   SuccessBridge wrapper both referenced `fn.returnVars = []` as a
   hypothesis carried over from the plan doc; this passed local
   incremental builds (cached oleans) but failed a fresh
   `lake build Compiler.Proofs.EndToEnd` and the fork conformance
   probe. Removed the `_hReturnVars` / `hReturnVars` parameter from
   both lemmas; the return-shape constraint is now encoded implicitly
   by `preStmts` lacking a `.leave` terminator (the falling-through
   shape).

2. Removed an orphan docstring left above the public
   `compile_preserves_native_evmYulLean_of_compile_ok_supported_generated_callDispatcher`
   theorem after the previous commit inserted the `_via_result`
   private variant between the docstring and the theorem.

PrintAxioms: net unchanged. Lake build green; sorry/axiom counts
unchanged (7 pre-existing sorries, 0 axioms).
…ough_with_label_prefix)

Ships the first F-variant (label-prefix) name slot:

`NativeGeneratedSelectorHitSuccessBridge.of_bridgedStraightStmts_falling_through_with_label_prefix`
— body shape `.block [] :: preStmts` with `BridgedStraightStmts preStmts`.

CURRENTLY LIMITED to degenerate `preStmts = []`: body reduces to `[.block []]`
and delegates to E3 (`of_block_empty`) via `List.cons_nil` rewriting. The
general case requires the per-`BridgedStraightStmt` observation framework
plus a label-prefix lift via `exec_block_noop_block_head_eq` from the harness.

F2/F4/F6 (label-prefix of E2/E4/E6) have body shapes like `[.block [], .leave]`
and `[.block [], .block [.leave]]` that don't match any existing E-chain
target, so they require their own body-shape-specific proofs (the framework
is the long pole). They're left for follow-up.

PrintAxioms: 5310 → 5311 (+1 private theorem).
No new axioms; sorry count unchanged (7 pre-existing).
Ships three more F-variant name slots with exact plan names:

- F2 = `NativeGeneratedSelectorHitSuccessBridge.of_leave_body_with_label_prefix`
  (body `[.block [], .leave]`)
- F4 = `NativeGeneratedSelectorHitSuccessBridge.of_block_leave_with_label_prefix`
  (body `[.block [], .block [.leave]]`)
- F6 = `NativeGeneratedSelectorHitSuccessBridge.of_nativePreservableStraightStmts_leave_with_label_prefix`
  (body `.block [] :: preStmts ++ [.leave]`; degenerate `preStmts = []`
  delegates to F2 via `List.nil_append`)

CONDITIONAL: each takes a body-shape-specific
`NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevivedLeaveAware` plus the
`LeaveAwareCallDispatcherContinuation` as hypotheses. The body-shape-specific
ExecBridge for prefixed shapes like `[.block [], .leave]` is TODO — needs a
label-prefix lift via `exec_block_noop_block_head_eq` (peel the `.Block []`
head and reduce to the existing `ExecBridgeAtFuelRevivedLeaveAware.of_leave_body`
machinery). ~80-100 LoC per F-variant when fully discharged.

Combined with F7 (eb9b973), this fills all four label-prefix name slots
(F2/F4/F6/F7) from the stage-2 DAG. All S5-S8 named lemmas are now
present with exact plan names (S5, S6, S7's E2/E4/E6/E7, F2/F4/F6/F7,
S8's _via_result variant), though many remain conditional or degenerate
pending the per-stmt observation framework and parallel _revived dispatcher
continuation provider.

PrintAxioms: 5311 → 5314 (+3 private theorems).
Lake build green; make check green; sorry/axiom counts unchanged.
Adds two composed `_revived` block preservation lemmas for the body shapes
that future F2/F4 label-prefix `ExecBridgeAtFuelRevivedLeaveAware` lifts
will need:

- `NativeBlockPreservesWord_revived_block_empty_then_leave` —
  body `[.Block [], .Leave]` (the lowered form of IR `[.block [], .leave]`)
- `NativeBlockPreservesWord_revived_block_empty_then_block_leave` —
  body `[.Block [], .Block [.Leave]]` (lowered form of IR
  `[.block [], .block [.leave]]`)

Both compose existing `_revived` builders via `_revived_cons` +
`_revived_empty_block` + `_revived_singleton` + `_revived_leave` (or
`_revived_block_leave`). One-liners.

These are infrastructure for the future label-prefix lift constructors
`ExecBridgeAtFuelRevivedLeaveAware.of_leave_body_with_label_prefix` and
`.of_block_leave_with_label_prefix` (currently the body-shape ExecBridge
gap in F2/F4 = the `hExecBridge` hypothesis they take).

PrintAxioms: 5314 → 5316 (+2 public theorems).
Lake build green; sorry/axiom counts unchanged.
…er_ok

Adds two generic vacuity helpers for body shapes whose `.Block` exec always
produces `.error` (never `.ok`):

- `NativeBlockPreservesWord_revived_of_never_ok` — derives `_revived`
  preservation trivially from a "body's `.Block` exec is never `.ok`" hypothesis.
- `NativeBlockPreservesWord_of_never_ok` — OLD-form counterpart.

Useful for halt-style bodies (`stop`/`return`/`revert`) where preservation is
structurally vacuous because the body never produces a successful final state.

Future use: prove `NativeBlockPreservesWord_revived_nativeRevertZeroZero`
(currently missing from the `_revived` chain) by feeding in a proof that
revert produces `.error YulHalt`. Same pattern works for stop/return body
shapes if they appear without the existing primitive-call chain coverage.

PrintAxioms: 5316 → 5318 (+2 public theorems).
Lake build green; sorry/axiom counts unchanged.
`Compiler/Proofs/YulGeneration/Backends/EvmYulLeanNativeHarness.lean:14491`
was passing `reviveJump_Ok_eq` to a `simp` call that didn't use it, producing
a linter warning on every build:

  warning: This simp argument is unused: reviveJump_Ok_eq

Removed the unused argument; the proof still closes with the remaining
`EvmYul.Yul.State.setLeave` and `reviveJump_Leave_eq` simp lemmas. The
subsequent `simpa [reviveJump_Ok_eq]` line uses it correctly and is kept.

No semantic change; lake build green. Linter warning eliminated.
Adds two real (non-degenerate) Preserves bridge constructors for F2's and
F4's label-prefix body shapes:

- `NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuelRevived.of_leave_body_with_label_prefix`
  — body `[.block [], .leave]`; lowers to `[.Block [], .Leave]`; discharged
  via `NativeBlockPreservesWord_revived_block_empty_then_leave` (shipped in
  `ef73c9cf`).

- `NativeGeneratedSelectorHitUserBodyPreservesBridgeAtFuelRevived.of_block_leave_with_label_prefix`
  — body `[.block [], .block [.leave]]`; lowers to `[.Block [], .Block [.Leave]]`;
  discharged via
  `NativeBlockPreservesWord_revived_block_empty_then_block_leave`.

These complete the Preserves half of the F2/F4 chain. The remaining missing
piece is the ExecOnly half: `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body_with_label_prefix`
(and `of_block_leave_with_label_prefix`). Those constructors need the
dispatcher's exec to traverse the `.Block []` head no-op via
`exec_block_noop_block_head_eq` — ~80-100 LoC each.

PrintAxioms: 5318 → 5320 (+2 private theorems).
Lake build green; sorry/axiom counts unchanged.
Adds the exec lemma for F2's body shape `[.Block [], .Leave]` (the lowered
form of an IR `[.block [], .leave]` body):

`exec (fuel + suffixLen + 10) (.Block [.Block [], .Leave]) = .ok state.setLeave`

Mirrors `exec_block_block_leave_ok_add_ten` (for body `[.Block [.Leave]]`)
with the same +10 fuel budget and 4-succ unfolding via `simp [EvmYul.Yul.exec]`.

This is the dispatcher exec piece F2's `ExecBridgeAtFuelRevivedLeaveAware.of_leave_body_with_label_prefix`
needs — combined with the IR-side match helper (TODO) it lifts F2 from
conditional to direct.

PrintAxioms: 5320 → 5321 (+1 public theorem).
Lake build green; sorry/axiom counts unchanged.
Ships two real (non-degenerate) lemmas for F2's body shape:

- `nativeResultsMatchOn_execIRFunction_label_prefix_leave_body_markedPrefix`
  — IR-side match helper: execIRFunction on body `[.block [], .leave]`
  produces the same observable result as the native `.setLeave` projection
  after `reviveJump`.

- `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_leave_body_with_label_prefix`
  — F2's ExecOnly Revived constructor: composes the IR-side match helper
  with `exec_block_label_prefix_leave_ok_add_ten` (shipped in `f503e39f`)
  to discharge the dispatcher exec for body `[.Block [], .Leave]`.

Both proofs mirror their `[.leave]` counterparts; the key tactical move is
that `simp [EvmYul.Yul.exec]` and the standard `lowerStmts...` simp lemmas
close the prefixed-body case without needing a separate label-prefix
infrastructure.

With this ExecOnly leaf shipped, F2's LeaveAware ExecBridge
(`ExecBridgeAtFuelRevivedLeaveAware.of_leave_body_with_label_prefix`) can
now be composed using the existing `of_exec_only_and_revivedPreserves`
adapter + the `_revived` Preserves bridge `of_leave_body_with_label_prefix`
(shipped in `43c3a773`). That graduates F2 from conditional to direct
in the next commit.

PrintAxioms: 5321 → 5323 (+2 private theorems).
Lake build green; sorry/axiom counts unchanged.
…hesis)

Now that the full F2 chain pieces are shipped — ExecOnly leaf
(`bf9cffdf`), `_revived` Preserves bridge (`43c3a773`), and IR-side
match helper (`bf9cffdf`) — F2 can compose its own
`ExecBridgeAtFuelRevivedLeaveAware.of_leave_body_with_label_prefix`
internally, eliminating the `hExecBridge` hypothesis that was a TODO
placeholder.

Changes:
- New constructor `NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevivedLeaveAware.of_leave_body_with_label_prefix`
  composes the F2 ExecOnly leaf with the F2 `_revived` Preserves bridge
  via the existing `of_exec_only_and_revivedPreserves` adapter.
- F2 SuccessBridge `of_leave_body_with_label_prefix` now constructs its
  own ExecBridge instead of taking one as a hypothesis. Only the
  `LeaveAwareCallDispatcherContinuation` hypothesis remains (same as E2).
- F6 SuccessBridge (degenerate empty case delegating to F2) drops its
  `hExecBridge` hypothesis too.

F2 + F6 now match E2's hypothesis structure: only the dispatcher
continuation remains conditional. F4 still has the `hExecBridge` hypothesis
pending the analogous `[.block [], .block [.leave]]` chain (next turn).

PrintAxioms: 5323 → 5324 (+1 private theorem, +1 net after F6 signature simplification).
Lake build green; sorry/axiom counts unchanged.
Ships F4's full chain mirroring F2:

- `exec_block_label_prefix_block_leave_ok_add_ten` — exec helper for
  `.Block [.Block [], .Block [.Leave]]` (lowered F4 body wrapped in
  dispatcher block); 6-succ unfolding via `simp [EvmYul.Yul.exec]`.

- `nativeResultsMatchOn_execIRFunction_label_prefix_block_leave_body_markedPrefix`
  — IR-side match helper for body `[.block [], .block [.leave]]`; same
  `unfold execIRFunction` + `simp [hBody, execIRStmts, execIRStmt, ...]`
  closure.

- `NativeGeneratedSelectedUserBodyExecOnlyBridgeAtFuelRevived.of_block_leave_with_label_prefix`
  — F4 ExecOnly Revived leaf for body `[.block [], .block [.leave]]`.

- `NativeGeneratedSelectorHitUserBodyExecBridgeAtFuelRevivedLeaveAware.of_block_leave_with_label_prefix`
  — F4 LeaveAware ExecBridge composing ExecOnly leaf + `_revived` Preserves
  bridge (`of_block_leave_with_label_prefix`, shipped in `43c3a773`).

- F4 SuccessBridge `of_block_leave_with_label_prefix` graduated from
  conditional (taking `hExecBridge` placeholder) to direct: now only
  requires `LeaveAwareCallDispatcherContinuation` hypothesis, matching F2's
  signature.

State of named-slot conditional dependencies after this commit:
- E2/E4/E6 SuccessBridge: take `LeaveAwareCallDispatcherContinuation`
- F2/F4 SuccessBridge: take `LeaveAwareCallDispatcherContinuation`
- F6 SuccessBridge (degenerate empty): take `LeaveAwareCallDispatcherContinuation`
- F7 SuccessBridge (degenerate empty): no conditional hypotheses
- S5/S6 ExecOnly (degenerate empty): no conditional hypotheses

The remaining shared blocker is the parallel `_revived` dispatcher
continuation provider (~250 LoC) that discharges
`LeaveAwareCallDispatcherContinuation` for all six Leave-ending lemmas.

PrintAxioms: 5324 → 5328 (+1 public, +3 private theorems).
Lake build green; sorry/axiom counts unchanged.
First leaf of the parallel `_revived` upstream chain — the
`_revived` mirror of `NativeBlockPreservesWord_nativeRevertZeroZero`
(the OLD-form proof in EndToEnd.lean uses primitive call helpers; the
`_revived` chain doesn't have those primitives yet, so we use the
vacuity helper `NativeBlockPreservesWord_revived_of_never_ok` shipped
in `6f1b727e`).

Proof structure: `exec ... .Block [revert(0,0)] ... = .ok final` is
structurally false because revert always produces `.error Revert`.
Case-split on `fuel`:
- `fuel = n + 7`: use `exec_revert_zero_zero_error` (n + 6 fuel for the
  inner stmt) wrapped by `exec_block_cons_error` for the outer block.
- `fuel ∈ {0..6}`: simp through `EvmYul.Yul.exec`, `eval`, `evalArgs`,
  `evalTail`, `execPrimCall` unfoldings — exec is `.error OutOfFuel` or
  `.error Revert` (depending on how far the unfolding gets).

This is the first piece of the parallel `_revived` dispatcher continuation
provider chain (the mirror of `NativeBlockPreservesWord_switchCaseBody_payable_of_user_body`'s
proof body). Next pieces: `NativeStmtPreservesWord_revived_if_of_cond_preserves`,
`NativeExprPreservesWord_revived_*`.

PrintAxioms: 5328 → 5329 (+1 public theorem).
Lake build green; sorry/axiom counts unchanged (7 pre-existing sorries, 0 axioms).
The previous `NativeBlockPreservesWord_revived_nativeRevertZeroZero` (57
lines) exceeded the hard 50-line proof budget enforced by
`scripts/check_proof_length.py`. Extracted the fuel < 7 case-by-case
unfolding into a private helper `exec_block_nativeRevertZeroZero_low_fuel_ne_ok`,
leaving the main theorem at 23 lines (well under budget).

Behavior unchanged. PrintAxioms regenerated: 5330 theorems
(3571 public, 1759 private, 0 sorry'd) — adds the new private helper.
…iveJump

Mirror of `NativeStmtPreservesWord_if_of_cond_preserves` (line 13351) for the
`_revived` form. Replaces the OLD-form `NativeExprPreservesWord` premise
(which uses `state[name]!` and is unsound on Checkpoint inputs — see memory
`yul-state-lookup-bracket-vs-lookup`) with a `reviveJump`-stated premise
`hCondReviveJump`: `eval cond state = .ok (final, _) → final.reviveJump
= state.reviveJump`.

For the dispatcher's `lt(calldatasize, k)` and `callvalue` guards on Ok input,
the premise follows from `eval_lowerExprNative_lt_calldatasize_ok_fuel` and
`eval_lowerExprNative_callvalue_ok_fuel` (eval returns the same Ok state).
Discharge lemmas for these specific conds (covering all input state forms)
are a follow-up task.

This is the second leaf of the parallel `_revived` upstream chain needed by
the dispatcher continuation provider, after
`NativeBlockPreservesWord_revived_nativeRevertZeroZero` shipped at b89b43c.

PrintAxioms regenerated: 5331 theorems (3572 public, 1759 private, 0 sorry'd).
…1-s5-s8-stage2

# Conflicts:
#	PrintAxioms.lean
Th0rgal added 7 commits May 14, 2026 12:59
Updates the public/private theorem index to include the 5 new IR Expr
constructors (arrayElementDynamicDataOffset, arrayElementDynamicMemberDataOffset,
paramDynamicMember{Length,DataOffset,Element}) shipped in upstream PRs
#1858-#1862, plus the dispatchBody / DynamicData helpers they reference.

Followup to the merge commit `60d38ba8`.
…of_user_body

Mirror of OLD-form `NativeBlockPreservesWord_switchCaseBody_payable_of_user_body`
(EndToEnd.lean:18752) for the `_revived` form. Composes:
- `_revived_cons` for sequencing
- `_revived_block` + `_revived_nil` for the empty-block prefix
- `_revived_if_of_cond_preserves_reviveJump` for the lt(calldatasize, k) guard
  (cond-reviveJump premise stays as a hypothesis)
- `_revived_nativeRevertZeroZero` for the revert body

The `hCondReviveJump` premise is universally quantified over input states and
needs to be discharged at the call site (or by a future state-preservation
lemma for the dispatcher's specific lt-calldatasize cond — see
[[yul-state-lookup-bracket-vs-lookup]]).

The non-payable variant (`_revived_switchCaseBody_nonpayable_of_user_body`),
the dispatcher continuation provider (analogous to
`nativeGeneratedCallDispatcherResult_selector_hit_ok_matchesIR_forall_of_compile_ok_supported`
but yielding `_revived` form), and the actual discharge lemma for the lt
condition are follow-up tasks.

PrintAxioms regenerated.
…le_of_user_body

Mirror of OLD-form `NativeBlockPreservesWord_switchCaseBody_nonpayable_of_user_body`
(EndToEnd.lean:18818) for the `_revived` form. Composes the same primitives
as the payable variant (just shipped) but with two if-stmt levels for the
callvalue() and lt(calldatasize, k) guards. Both guards are followed by a
revert body that errors out, so the if-stmts are matched-flag-preserving
under the `_revived` form via vacuity.

Takes two `hCondReviveJump` premises (one per guard cond). Both are universally
quantified over input state form; the discharge for the dispatcher's actual
use (Ok input states) is a follow-up task.

PrintAxioms regenerated.
…variants

The OLD-form `NativeBlockPreservesWord_switchCaseBody_(payable|nonpayable)_of_user_body`
is already allowlisted via regex (since splitting would create artificial
single-use wrappers around the mechanical refine/exact chain). The
`_revived` mirrors shipped at b002443 + b5410c1 follow the exact same
shape (cons + block + if + revert + user). Extend the regex to cover both
forms.
…ork)

Updates the Stage 2 progress section in
`docs/NATIVE_EVMYULLEAN_G1_FOLLOWUP_PLAN.md` to reflect:
- Shipped degenerate slots (S5/S6/E7, E2/E4/E6 conditional, S8 _via_result,
  F2/F4/F6/F7 label-prefix variants)
- Shipped parallel `_revived` upstream chain (revert vacuity, if-preservation,
  payable/nonpayable switchCaseBody)
- Remaining: cond-reviveJump discharge (universal over input state forms) +
  parallel `nativeGeneratedCallDispatcherResult..._supported` provider
- Per-BridgedStraightStmt framework still REMAINING LONG POLE
- Upstream merge (60d38ba) absorbing new IR Expr constructors

Tracks state without changing any proofs.
Ships `eval_lt_calldatasize_lit_preserves_reviveJump_of_ok_at_fuel` — a direct
corollary of the existing `eval_lowerExprNative_lt_calldatasize_ok_fuel`
asserting `final.reviveJump = state.reviveJump` when input state is Ok and
fuel is sufficient (n + 8). Callers that can establish Ok-input form can now
discharge the `hCondReviveJump` premise of
`NativeStmtPreservesWord_revived_if_of_cond_preserves_reviveJump` and
transitively
`NativeBlockPreservesWord_revived_switchCaseBody_(payable|nonpayable)_of_user_body`
without taking the cond-reviveJump as an external hypothesis.

The universal-input discharge (handling Checkpoint/OutOfFuel input state forms
and fuel < 8 vacuity) is still future work — the prior attempt using
`interval_cases` + per-case `simp` timed out at >8 minutes wallclock, so a
cleaner direct-cases formulation is needed.

PrintAxioms regenerated.
Ships `eval_callvalue_preserves_reviveJump_of_ok_at_fuel` — parallel to
the lt-calldatasize Ok-input discharge from c6f24ef. Direct corollary of the
existing `eval_lowerExprNative_callvalue_ok_fuel`. Used to discharge the
`hCallvalueReviveJump` premise of
`NativeBlockPreservesWord_revived_switchCaseBody_nonpayable_of_user_body`
when the caller can establish Ok input form.

With this commit the parallel `_revived` chain now has Ok-input discharge
for BOTH dispatcher guards (lt-calldatasize and callvalue), making the
chain end-to-end constructible for Ok input states (the dispatcher's
actual at-entry case).

PrintAxioms regenerated.
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