Skip to content

proof(L2): admit the pure exp builtin lane to the compile core (#2084) - #2397

Open
Th0rgal wants to merge 4 commits into
mainfrom
proof/l2-builtin-exp-foreign-surface-2084
Open

proof(L2): admit the pure exp builtin lane to the compile core (#2084)#2397
Th0rgal wants to merge 4 commits into
mainfrom
proof/l2-builtin-exp-foreign-surface-2084

Conversation

@Th0rgal

@Th0rgal Th0rgal commented Aug 22, 2026

Copy link
Copy Markdown
Member

Summary

Closes one more Tier-4 external-call/foreign surface from #2084 by giving the pure exp builtin a first-class compiler/proof surface instead of leaving it misfiled as a foreign call.

pow a b / a ^ b in the EDSL desugars to Expr.externalCall builtinExpName [base, exponent] (Verity/Macro/Translate/Expr.lean:3404). That node shape is pure arithmetic — it lowers to the Yul exp builtin and never reaches a foreign address — but every unsupported-surface predicate treated it as an opaque externalCall, so it was excluded from the compile core and undenoted.

This slice admits exactly that one sentinel-keyed shape:

  • Surface predicates (SupportedSpec.lean): all 8 predicates now recurse into base/exponent when name == builtinExpName, and keep their original constant for every other externalCall. Genuine foreign calls remain unsupported.
  • Compile core (ExprCore.lean): new ExprCompileCore.builtinExp constructor.
  • Source semantics (SourceSemantics.lean): evalExpr_externalCall_builtinExp, plus _of_ne / _of_arity lemmas pinning the non-exp behaviour.
  • Compiler-free denotation (Verity/Core/Model/Denote.lean): the exp lane denotes without an oracle; other externalCalls stay none.
  • IR bridge (FunctionBody/Base.lean): evalIRExpr_exp_of_eval, compileExpr_builtinExp_ok, eval_compileExpr_builtinExp_of_compiled.
  • EVMYulLean native lowering (EvmYulLeanPureBuiltinLemmas.lean): evalPureBuiltinViaEvmYulLean_exp_native, proved through uint256_powAux_toNat / uint256_pow_toNat. No native_decide.

All four planes agree on Uint256.pow, i.e. (a % 2^256) ^ (b % 2^256) % 2^256.

collectExprNames consistency fix

ValidationHelpers.collectExprNames prepended builtinExpName to its result. That is a fresh-name-avoidance collector feeding only pickFreshName (Compile.lean:109/116/123, 308/323/341), and builtinExpName is already in the reserved-identifier list (ValidationCalls.lean:83) so no user can bind it. TrustSurface.collectExternalExprNames:579-583 already skips the sentinel identically — this brings the two collectors into agreement. Without it, collectExprNames_mem_exprBoundNames_of_core is genuinely false for the exp lane and its downstream consumer eventCollectExprListNames_subset_scope breaks.

No gate was weakened: the proof-length limit hit on collectExprNames_mem_exprBoundNames_of_core (52 lines) was resolved by extracting collectExprNames_builtinExp_split, not by allowlisting.

Validation receipts

lake build                                              Build completed successfully (2473 jobs).   exit 0
lake build PrintAxioms                                  Build completed successfully (2622 jobs).   exit 0
lake build ...GenericInduction.Scope                    ✔ [1211/1211] (25s)                          exit 0
lake build ...IRGeneration.Function                     ✔ [1226/1226] (61s)                          exit 0
make check                                              All checks passed.                           exit 0
  └ 666 Python tests OK in 77.9s
lean_lint --only proof_length     Proof length check passed. 7275 scanned / 5417 <30 / 1218 30-50 / 640 allowlisted
lean_lint --only lean_hygiene     0 debug commands, 0 allowUnsafeReducibility, 0 sorry, 0 native_decide in proofs
check_compiler_boundaries.py      all 7 sub-checks passed

Forbidden-token scan on added lines vs origin/main: zero new sorry / admit / axiom / unsafe. Two benign textual hits only — the AUDIT.md prose "No native_decide." and the generated PrintAxioms.lean counter line 0 sorry'd.

PrintAxioms.lean regenerated via scripts/generate_print_axioms.py: 6849 → 6862 theorems (4918 public, 1944 private, 0 sorry'd). No new axiom, no new trust assumption; AUDIT.md gains a "Pure exp Builtin Lane (2026-08)" section.

Test plan

  • lake build green
  • lake build PrintAxioms green (note: Compiler.Proofs.IRGeneration.Function is reachable only through this target)
  • make check green
  • Proof-length and hygiene lints green without new allowlist entries
  • Forbidden-token scan clean

Excludes the reserved `builtinExpName` sentinel from `collectExprNames`: it is
a marker for the pure `exp` builtin, never a callee identifier reaching the
generated Yul, so it cannot collide with a compiler-generated temp name. This
keeps `collectExprNames ⊆ exprBoundNames` true on the compile core now that
`ExprCompileCore.builtinExp` admits the lane.
Threads the reserved `builtinExpName` lane through the constructor-mode
compilation equality, refreshes the axiom audit, and records the surface change
in AUDIT.md. Also decomposes `collectExprNames_mem_exprBoundNames_of_core` so
the 50-line proof gate stays satisfied.
@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
verity Ready Ready Preview Aug 23, 2026 4:52am

Request Review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72713d0737

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1489 to +1491
pure (Verity.Core.Uint256.pow
(Verity.Core.Uint256.ofNat baseVal)
(Verity.Core.Uint256.ofNat exponentVal)).val

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use modular exponentiation in the source evaluator

When the exponent comes from a uint256 parameter and is large, this newly reachable arm calls Uint256.pow, which is defined as ofNat (base.val ^ exponent.val) in Verity/Core/Uint256.lean. That materializes an astronomically large Nat before reducing it modulo 2^256, so source-semantics and denotation executions can hang or exhaust memory even though EVM EXP and the EvmYul backend finish using modular square-and-multiply. Compute the power modulo 2^256 incrementally so this admitted lane remains executable over its full input domain.

Useful? React with 👍 / 👎.

Resolves the Codex finding on PR #2397 (discussion r3836627045): the
newly reachable builtinExp arm called Uint256.pow, which materialises
base.val ^ exponent.val as a raw Nat before reducing mod 2^256, so
full-domain uint256 exponents hang the source semantics and denotation.

- Verity/Core/Uint256.lean: add powBySquaring (square-and-multiply
  accumulating acc * base ^ exp mod 2^256) with powBySquaring_val, and
  powEff with powEff_eq_pow : powEff base exponent = pow base exponent.
- SourceSemantics.evalExpr, evalExprWithHelpers, Denote.evalExpr: the
  exp lane now computes with powEff; proofs bridge to pow via
  powEff_eq_pow, so the compiler agreement theorems are unchanged.
- FunctionBody/Base.lean: evalExpr_lt_evmModulus_core_onExpr uses
  powEff (bounds proof identical through powEff_eq_pow).
- SourceSemanticsFeatureTest.lean: 4 regression examples exercising the
  lane at exponent 2^256 - 1 (executable, no Nat.pow blow-up), wrap
  fidelity (3^300), and the helper-aware and denotation evaluators.
- artifacts/trust_surface_report.json: regenerated (4 new test-only
  native_decide examples).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenCodeReview first-pass review

🟡 Scout triage only — not a full review. no findings; a human or Codex must still cover the unflagged hunks and proof obligations.

Lean packet budget exceeded: 13 Lean file(s), 722 changed supported line(s).

Warnings

  • routing : Diff exceeded bounded packet review capability; full OCR not attempted.
OCR pilot metrics & packet coverage

OCR pilot metrics

  • Routing: large-lean-hotspots (router-v10)
  • Changed files: 15 supported / 15 total; Lean 13, trust docs 1, workflow/scripts 1, contracts 0, docs 0
  • Changed lines: 722 supported; thresholds large Lean >=3 files or >800 lines
  • OCR: status large-lean-hotspots; comments 0; files 0; tokens 0; tool calls 0; warnings 1; duration 0s
  • Largest changed files: Compiler/Proofs/IRGeneration/SupportedSpec.lean (+175/-5), Compiler/Proofs/IRGeneration/FunctionBody/Base.lean (+141/-0), Compiler/Proofs/IRGeneration/SourceSemantics.lean (+76/-5), Verity/Core/Uint256.lean (+61/-0), Compiler/Proofs/YulGeneration/Backends/EvmYulLeanPureBuiltinLemmas.lean (+59/-0)

Packet coverage

  • Packet review: not used; selected 0/8 packet(s)
  • Scout: configured; status skipped_no_packets; model builtin/assistant
  • Scout lenses: provenance, verification-independence, environment-determinism, proof-soundness; rubric items checked 3
  • Strong review: required; status blocked_packet_input
  • Residual risk: Diff exceeded packet budget; use top changed files and deterministic signals as required Codex/human review checklist.
  • Strong packet-review blocker: OpenCodeReview 1.7.9 supports --from/--to full diff ranges, but this workflow does not have a safe packet/window input bridge for Lean hunks yet.

Pilot mode: advisory only. Codex Review remains the merge gate.

@Th0rgal

Th0rgal commented Aug 23, 2026

Copy link
Copy Markdown
Member Author

@codex review

Pushed head: e6c86407adfc979319f11768bb6ad3caf9ff8f67 (fast-forward on 72713d07).

Resolves the current-head P2 finding #2397 (comment) — the builtinExp source-semantics lane now computes modular exponentiation incrementally via Uint256.powEff (square-and-multiply, proved equal to Uint256.pow by powEff_eq_pow), wired identically through SourceSemantics.evalExpr, evalExprWithHelpers, and Denote.evalExpr, with full-domain (2^256 - 1 exponent) regression examples. Validation receipts: focused + full lake build green, make check green, PrintAxioms report + check_axioms.py PASS (4918 theorems, no sorryAx), no new sorry/admit/axiom/unsafe.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: e6c86407ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Th0rgal

Th0rgal commented Aug 23, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: e6c86407ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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