Skip to content

Move keccak preimage handling into EVM.Keccak.Preimages, end infeasible paths at branch queries - #1163

Merged
msooseth merged 7 commits into
mainfrom
keccak-preimage-refactor
Oct 19, 2026
Merged

msooseth merged 7 commits into
mainfrom
keccak-preimage-refactor

Conversation

@msooseth

Copy link
Copy Markdown
Collaborator

Description

Keccak preimage handling (tables, the field-offset window lookup, folded-slot recovery, decoding recorded preimages, the assumed keccak range) now lives in one module, EVM.Keccak.Preimages, shared by the simplifier and the SMT keccak assumptions. This removes the simplifier's separate array preimage table.

Behaviour changes:

  • The simplifier decides keccak equalities with literals above the assumed range as false, matching the SMT assumptions.
  • Branch and solution queries also get the keccak preimages recorded during concrete execution (e.g. in setUp), as the final queries already did.
  • checkBranch took an unsatisfiable branch condition to mean the branch is not taken, even when the path conditions themselves were unsatisfiable, so such paths kept running, e.g. until the loop iteration limit. It now checks the negation too, and ends the path when both are unsatisfiable. This costs one extra solver query when a branch condition is unsatisfiable.

Checklist

  • tested locally
  • added automated tests
  • updated the docs
  • updated the changelog

msooseth and others added 5 commits October 19, 2026 12:16
Preimages are typed (mapping, array, raw), the simplifier and the SMT
keccak assumptions share one table of small array slots and one lookup
of the field-offset window, and the assumed keccak range is named.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
checkBranch took an unsatisfiable branch condition to mean the branch is
not taken, also when the path conditions themselves were unsatisfiable,
so such paths kept running, e.g. until the loop iteration limit. It now
checks the negation too and returns Infeasible when both fail, and the
path ends like a failed vm.assume.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
msooseth and others added 2 commits October 19, 2026 15:53
A copy with a symbolic size passes the memory access check during
execution, and its size can become a huge literal only once keccaks are
concretized for the SMT encoding, which then unrolled one store per byte
and exhausted memory. The encoder now rejects such sizes, using the limit
execution already applies to literal sizes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A parsed W256 or W64 stayed a thunk that held its string until used. In
the symbolic-execution fuzzer, a geth trace with deep stacks on every
line, read as a String and parsed this way, took several GB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@msooseth
msooseth merged commit dd2901b into main Oct 19, 2026
8 of 9 checks passed
@msooseth
msooseth deleted the keccak-preimage-refactor branch October 19, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant