Skip to content

Model keccak256 opcode, unaligned calldata, and SHA-256 engine in executable semantics#1943

Merged
Th0rgal merged 26 commits into
mainfrom
sphincs-raw-revert-support
Jun 2, 2026
Merged

Model keccak256 opcode, unaligned calldata, and SHA-256 engine in executable semantics#1943
Th0rgal merged 26 commits into
mainfrom
sphincs-raw-revert-support

Conversation

@Th0rgal

@Th0rgal Th0rgal commented Jun 1, 2026

Copy link
Copy Markdown
Member

Summary

Extends Verity's executable source semantics with the hash/calldata
primitives the SPHINCS- C13 accept-path refinement needs. Enables the
keccak accept path to be executed (and thus proved) rather than
reverting at the first hash.

  • keccak256(offset,size) modeled (SourceSemantics.lean): new
    keccakMemorySlice / memorySliceBytesBE / wordToBytesBE helpers and
    .keccak256 arms in evalExpr / evalExprWithHelpers, wired to the
    in-tree KeccakEngine. Previously the first keccak made execStmt
    revert, making the accept subdomain provably unreachable.
  • Unaligned calldataloadWord (Calldata.lean): EVM-faithful
    byte-addressed 32-byte window for unaligned offsets (r != 0), composing
    hi/lo words big-endian with zero-padding. Aligned reads (r = 0) reduce
    to the prior single-word behaviour exactly. Needed for C13 auth-path
    sibling reads at 16-byte-strided offsets.
  • Kernel-computable SHA-256 engine (Compiler/Sha256/Engine.lean),
    FIPS 180-4, verified against reference vectors. Infrastructure only — the
    SHA-256 precompile (0x02) is deliberately NOT wired into the interpreter
    yet (word-keyed memory cannot faithfully represent SLH-DSA's 16-byte
    precompile-input layout).

Trust docs (AXIOMS.md / TRUST_ASSUMPTIONS.md) updated for
keccak256_memory_slice_matches_evm. No new sorry; keccak engine is
cross-checked against the EVM engine.

Internal-helper proof composition & higher-order helpers

  • Compositional internal-helper proof reuse across callers (Layer 2 follow-on: replace SupportedSpec feature exclusions with compositional proof interfaces and widen coverage toward the full EDSL image #1630)
    (SourceSemantics.lean, Contract.lean): a first-class source-level
    interface that threads the once-proved global helper-summary catalog
    (SupportedHelperSummaryProofCatalog, carried by SupportedSpecHelperProofs)
    through to every selector-dispatched caller and call site.
    SupportedSpecHelperProofs.helperCallSummarySound delivers summary
    soundness at an arbitrary helper call site, and evalInternalCallObeysSummary
    / execInternalCallObeysSummary / execInternalCallAssignObeysSummary
    specialise it to the three helper call shapes (expression, void statement,
    assigning statement), landing the helper's summary contract directly on the
    interpreter result. A helper proved once is now consumed at each call without
    re-discharging its summary. The compiled-side body proof still reduces through
    the helper-closed SupportedStmtList fragment, so retargeting it to consume
    this reuse is the tracked next step; the trusted boundary is unchanged.
  • Higher-order internal helpers via monomorphization (verity_contract rejects function-pointer parameters #1747)
    (Verity/Macro/Translate.lean): a compile-time monomorphization pre-pass over
    the parsed FunctionDecl array, run before any model/IR lowering. For each
    call site that passes a statically-known internal helper in a function-pointer
    position, a first-order clone of the higher-order helper is synthesized
    (function-pointer params dropped, each occurrence replaced by the concrete
    helper) and the call site is rewritten to target the clone. Specialization runs
    to a fixpoint and the resulting helpers are topologically ordered so executable
    emission keeps callee-before-caller. Nothing downstream ever sees a function
    pointer, so the existing first-order machinery and proofs apply unchanged, with
    zero overhead when no helper is higher-order. Dynamic dispatch (a runtime value
    or expression in function-pointer position) still fails fast with a clear verity_contract rejects function-pointer parameters #1747
    diagnostic.

Author-facing usage docs

  • EDSL reference clarified for external calls and internal helpers
    (docs-site/content/edsl-api-reference.mdx): documents the higher-order
    internal-helper surface from verity_contract rejects function-pointer parameters #1747 (function-pointer parameters, passing a
    helper by name, and the static-callee-only restriction with its verity_contract rejects function-pointer parameters #1747
    diagnostic), and the three linked-external call forms — externalCall
    (single-word value position), tryExternalCall (prepended success flag,
    multi-return), and externalCallBind (statement position, no return).
    Corrects now-stale prose that claimed at-most-one return and rejected dynamic
    arguments; Array/Bytes arguments and multi-return are supported today.
    Cross-links the generic foreign-call surface to the named ECM module catalog.
    Documentation only — describes already-shipped behavior, so no trust/axiom
    boundary changes.

  • Agent-facing docs reorganization (docs-site/): names verity_contract
    as the canonical authoring surface and routes authors by intent.

    • New CanonicalSurface + TaskRouter components surface "which surface do
      I write?" and the three journeys (start from an idea, port from Solidity,
      prove an existing contract) on index, getting-started, first-contract,
      solidity-to-verity, and llms.txt.
    • New Capabilities & Limits page (capabilities.mdx): expressible vs
      partial vs trust-boundary vs unsupported, plus the deny-flag table for
      staying inside the proved subset.
    • New Diagnostics page (diagnostics.mdx): compiler / macro / linker
      error → cause → fix index.
    • Golden minimal contract skeleton (storage + function + spec + proof +
      register) in first-contract; the monad/spec/proof forms are labelled as
      the proof layer beneath verity_contract.
    • trust-model is now canonical for the Layer 1/2/3 split; the architecture
      re-teach is trimmed to one sentence + link.
    • Fixes stale Compiler/Specs.lean references to the real
      Contracts/Specs.lean (docs pages + generate_contract.py scaffold output).
      INTERPRETER_FEATURE_MATRIX updated: Layer 2 follow-on: replace SupportedSpec feature exclusions with compositional proof interfaces and widen coverage toward the full EDSL image #1630 helper-summary reuse is now a
      first-class proof interface (helperCallSummarySound + three corollaries).
      Documentation only — no trust/axiom boundary changes.

Review & CI follow-ups

Test plan


Note

Medium Risk
Changes executable source semantics (keccak, calldata) and compiler validation/CEI for raw Yul, plus macro monomorphization; well-tested and documented but affects verification reach and contract elaboration behavior.

Overview
This PR widens what Verity can execute and reason about in the source interpreter and tightens validation around raw Yul, while adding proof plumbing for internal helpers.

Hash and calldata. Expr.keccak256 no longer always reverts: evalExpr / evalExprWithHelpers hash a word-aligned memory slice via keccakMemorySlice and the in-tree KeccakEngine. Trust docs describe the word-aligned keccak256_memory_slice_matches_evm assumption. calldataloadWord is updated for unaligned byte windows (hi/lo composition); aligned reads stay behaviorally the same. A new FIPS 180-4 SHA-256 engine (with smoke tests pulled into Compiler.lean) is infrastructure only—the precompile is not hooked into the interpreter yet.

Helpers (#1747, #1630). The macro runs a monomorphization pre-pass before lowering: higher-order internal helpers with a statically known callee name become first-order clones; dynamic function-pointer arguments still error. In proofs, SupportedSpecHelperProofs gains helperCallSummarySound and three call-site corollaries so once-proved helper summaries reuse at every caller; SupportedSpec treats plain keccak256 as supported on helper/call surfaces (only operand subexpressions are scanned).

Validation. Raw Yul gets an AST scan for call / staticcall / delegatecall so CEI and external-call checks do not rely only on fragment metadata; unsafeYul no longer triggers misleading logical-purity “duplicate operand” diagnostics.

Reviewed by Cursor Bugbot for commit cebef44. Bugbot is set up for automated code reviews on this repo. Configure here.

Th0rgal added 14 commits May 28, 2026 12:30
Surface declared raw-Yul storage writes in the modifies() write-set,
flag computed-slot writes as untrackable, and treat fragment call
mechanics as external interactions for CEI ordering and external-call
detection.
…ntics

Make evalExpr/evalExprWithHelpers evaluate Expr.keccak256 via the in-tree
KeccakEngine over a word-aligned RuntimeState memory slice, instead of
returning none (revert). Adds keccakMemorySlice/memorySliceBytesBE/wordToBytesBE
helpers; updates evalExpr_keccak256 and the helper-surface equivalence case.

No new axiom or sorry: reuses the CI-cross-checked kernel Keccak. Trust docs
(AXIOMS.md, TRUST_ASSUMPTIONS.md) updated to record the word-aligned-access
faithfulness assumption (keccak256_memory_slice_matches_evm).

Builds green: SourceSemantics + 8 reverse-dependency importers + SphincsMinusVerifiers.
Pure-Lean, axiom-free SHA-256 over ByteArray (Sha256Engine.sha256), mirroring
KeccakEngine's role: prerequisite for modeling the EVM SHA-256 precompile (0x02)
in the executable source semantics with a computed 32-byte digest.

Verified against reference vectors (empty, "abc", quick-brown-fox, and the
56-byte padding-boundary case). UInt32 wrapping matches spec add-mod-2^32.
calldataloadWord now returns the EVM-faithful byte-addressed 32-byte
window for unaligned offsets (r != 0), composing the hi/lo words with
big-endian zero-padding. Aligned reads (r = 0) reduce to the prior
single-word behaviour exactly. Needed for the C13 auth-path sibling
reads at 16-byte-strided offsets in the Merkle-climb correspondence.
@vercel

vercel Bot commented Jun 1, 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, Comment Jun 2, 2026 3:54pm

Request Review

@Th0rgal

Th0rgal commented Jun 1, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Comment thread Compiler/CompilationModel/Validation.lean Outdated
Comment thread Compiler/CompilationModel/LogicalPurity.lean
@github-actions

github-actions Bot commented Jun 1, 2026

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

Comment thread Compiler/CompilationModel/LogicalPurity.lean Outdated
Th0rgal added 2 commits June 1, 2026 15:00
…pport

# Conflicts:
#	Compiler/CompilationModel/Types.lean
#	Compiler/CompilationModel/Validation.lean
#	Compiler/CompilationModelFeatureTest.lean
Comment thread Compiler/Proofs/IRGeneration/SourceSemantics.lean
…e-Yul review invariants

ff6c9c0 swapped calldataloadWord's aligned/unaligned branches (r = 0 now
selects the aligned word) but left calldataloadWord_lt_evmModulus expecting
the old layout, breaking the build at FunctionBody.lean:1969. Both branches
now reduce mod evmModulus, so each discharges via Nat.mod_lt.

Also document two invariants raised in the PR #1943 review:
- LogicalPurity: raw Yul is emitted verbatim, so the logicalAnd/logicalOr/ite
  operand-duplication predicate correctly returns false; fragment external
  calls are caught in Validation, not here.
- SourceSemantics: the keccak256 arm must evaluate offset/size with evalExpr to
  stay definitionally equal to evalExpr, because exprTouchesUnsupportedHelperSurface
  treats keccak256 as a helper-surface leaf and evalExprWithHelpers_eq_evalExpr
  depends on it.
Comment thread Compiler/Sha256/Engine.lean
Th0rgal added 2 commits June 2, 2026 11:01
Add a first-class, documented source-level interface that reuses the
once-proved global helper-summary catalog across every selector-dispatched
caller and call site:

- SupportedSpecHelperProofs.helperCallSummarySound delivers summary soundness
  at an arbitrary helper call site of any selector-dispatched function, sourced
  purely from the shared catalog carried in SupportedSpecHelperProofs.
- evalInternalCallObeysSummary / execInternalCallObeysSummary /
  execInternalCallAssignObeysSummary specialise that fact to the three helper
  call shapes (expression, void statement, assigning statement), landing the
  helper's summary contract directly on the interpreter result.

This is the cross-caller proof reuse that whole-contract correctness needs: a
helper proved once is consumed at each call without re-discharging its summary.
The compiled-side body proof still reduces through the helper-closed
SupportedStmtList fragment, so retargeting it to consume this reuse remains the
tracked next step; the trusted boundary is unchanged. Contract.lean comments
updated to reflect the now-available reuse interface.
…1747)

Higher-order internal calls (helpers with function-pointer parameters) are
now supported by a compile-time monomorphization pre-pass over the parsed
FunctionDecl array, run before any model/IR lowering. For each call site that
passes a statically-known internal helper in a function-pointer position, a
first-order clone of the higher-order helper is synthesized (function-pointer
parameters dropped, each occurrence replaced by the concrete helper) and the
call site is rewritten to target the clone. Specialization runs to a fixpoint;
the resulting helpers are topologically ordered so executable emission keeps
callee-before-caller. Nothing downstream ever sees a function pointer, so the
existing first-order machinery and proofs apply unchanged, with zero overhead
when no helper is higher-order. Dynamic dispatch (a runtime value or expression
in function-pointer position) still fails fast with a clear #1747 diagnostic.

Tests: positive FunctionPointerParamSmoke #check_contract plus a focused
negative test (FunctionPointerDynamicArgRejected) in Contracts/Smoke.lean, and
a worked HigherOrderDemo contract in CompilationModelFeatureTest.lean asserting
the monomorphized model shape and the executable result double(double(5)) = 20.

Docs: ROADMAP.md and VERIFICATION_STATUS.md updated for #1747, and also for the
#1630 helper-summary reuse interface now consumed at every call site
(SupportedSpecHelperProofs.helperCallSummarySound and its three source-semantics
call-shape lemmas evalInternalCallObeysSummary / execInternalCallObeysSummary /
execInternalCallAssignObeysSummary).
…eference

Document the author-facing surface the recent work added but left
undocumented:

- Higher-order internal helpers (#1747): function-pointer parameters,
  passing a helper by name, and the monomorphization restriction
  (statically-known callee only; #1747 diagnostic on dynamic dispatch).
- Linked-external call forms: externalCall (single-word value position),
  tryExternalCall (prepended success flag, multi-return), and
  externalCallBind (statement position, no-return). Corrects stale prose
  that claimed at-most-one-return and rejected dynamic args; Array/Bytes
  arguments and multi-return are supported today. Cross-links the generic
  foreign-call surface to the named ECM module catalog.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cebef44. Configure here.

Comment thread Compiler/Proofs/IRGeneration/SourceSemantics.lean Outdated
Th0rgal added 2 commits June 2, 2026 17:53
…eview)

- generate_macro_property_tests: skip higher-order (#1747) internal helpers,
  which are monomorphized away before lowering and have no external ABI
  signature to exercise; emitting one crashed the generator. Adds the
  generated PropertyFunctionPointerParamSmoke.t.sol and a regression test.
- check_proof_length: allowlist two #1630 single-delegation theorems whose
  reported span is inflated by the next theorem's doc-comment preamble.
- SourceSemantics: give the three #1630 helper-call corollaries
  (expression / void-stmt / assigning-stmt) shape-specific first conjuncts so
  their types are genuinely distinct, instead of three identical summary-only
  conclusions (Bugbot). The summary fact is still reused via
  helperCallSummarySound.
…ities/diagnostics pages

Agent-facing docs reorganization so contract authors land on verity_contract
as the canonical surface and can route by intent.

- Add CanonicalSurface + TaskRouter components; surface "which surface do I
  write?" and the three journeys (start from an idea, port Solidity, prove an
  existing contract) on index, getting-started, first-contract,
  solidity-to-verity, and llms.txt.
- New Capabilities & Limits page: expressible vs partial vs trust-boundary vs
  unsupported, plus the deny-flag table for staying in the proved subset.
- New Diagnostics page: compiler / macro / linker error -> cause -> fix index.
- Add a golden minimal contract skeleton (storage + function + spec + proof +
  register) in first-contract; label the monad/spec/proof forms as the proof
  layer beneath verity_contract.
- Make trust-model canonical for Layer 1/2/3; trim the architecture re-teach
  to one sentence + link.
- Fix stale Compiler/Specs.lean references to Contracts/Specs.lean (docs pages
  and generate_contract.py scaffold output/comments).
- INTERPRETER_FEATURE_MATRIX: #1630 helper-summary reuse is now a first-class
  proof interface (helperCallSummarySound + three call-shape corollaries).
@Th0rgal Th0rgal merged commit e405b21 into main Jun 2, 2026
36 of 37 checks passed
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