Skip to content

feat(vm): refine branches with path facts - #736

Open
Jon-Becker wants to merge 1 commit into
feat/symbolic-expression-domainfrom
feat/path-fact-refinement
Open

feat(vm): refine branches with path facts#736
Jon-Becker wants to merge 1 commit into
feat/symbolic-expression-domainfrom
feat/path-fact-refinement

Conversation

@Jon-Becker

Copy link
Copy Markdown
Owner

What changed? Why?

Stacked on #734 (after #733, #732, and #730).

Adds lightweight path predicates to the abstract CFG state and applies true/false assumptions on JUMPI edges. Repeated or logically implied conditions can now be proven infeasible without enumerating concrete executions or invoking an SMT solver.

Path fact domain

  • zero and non-zero constraints
  • exact values and excluded values
  • inclusive unsigned ranges
  • known-zero and known-one bit masks
  • symbolic equality and disequality relations
  • contradiction detection
  • conservative fact joins that retain only knowledge valid on every incoming path

Refinement

  • propagates assumptions through ISZERO
  • reasons about EQ, unsigned LT, and unsigned GT
  • narrows calldata-size and other symbolic ranges
  • propagates (value & mask) == constant facts to the unmasked value
  • evaluates repeated comparisons from retained ranges/equalities
  • records exactly which contextual edge directions were proven infeasible
  • applies refined facts independently to true and false successor states

Expression interning is also made fully structural: equivalent expressions computed at different PCs share one ExprId, while the arena separately records all producer sites. This is required for a later read of CALLDATASIZE, CALLER, or an equivalent expression to reuse facts established by an earlier branch.

Notes to reviewers

Key files:

  • crates/vm/src/core/facts.rs: constraints, assumptions, joins, implication checks, and tests
  • crates/vm/src/core/analysis.rs: fact-bearing states and branch-specific successors
  • crates/vm/src/core/context.rs: contextual branch refinement and diagnostics
  • crates/vm/src/core/symbolic.rs: structural interning with separate producer-site tracking
  • crates/vm/src/core/mod.rs: exports the fact domain

This is deliberately a cheap, incomplete bit-vector domain. Signed comparisons, complex arithmetic implications, and expressions outside these rules remain unknown for the next demand-driven SMT stage.

Exploratory 100-contract run

Compared with #734 over the same first 100 largest1k contracts:

metric #734 this PR
unique reachable blocks 52,630 52,620
contextual states 173,392 170,144
contextual edges 196,812 192,566
unresolved jump points 1,235 1,276
interned expressions 57,974 32,351
proven-infeasible contextual directions 4,811
runtime incl. process startup 66.22s 104.39s
failures 0 0

The graph is smaller because infeasible directions are removed and fewer downstream contexts are created. Structural interning accounts for the expression-count reduction. The ten-block decrease is consistent with pruning but is not yet a ground-truth precision claim. The runtime increase identifies path-fact representation and cloning as optimization targets before production migration.

How has it been tested?

  • cargo +nightly fmt --check --all
  • targeted Clippy on heimdall-vm with repository-standard allowances
  • cargo test --workspace --lib --tests
  • seven focused fact/refinement tests covering zero propagation, ranges, equality/disequality, masks, conservative joins, contradictions, and repeated-condition pruning
  • 100-contract largest1k exploratory run with no failures

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

❌ AI Evaluation Suite

The heimdall-eval run failed. See the workflow run for details.

  • Run AI Evaluation Suite

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Coverage Report for 809c61e

Metric Value
Base branch 70.88%
PR branch 72.84%
Diff +1.96%

@Jon-Becker
Jon-Becker force-pushed the feat/path-fact-refinement branch from f9f439c to 04cdeea Compare September 6, 2026 23:40
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Benchmark for 809c61e

Click to view benchmark
Test Base PR %
heimdall_cfg/complex 14.8±0.36ms 14.8±0.33ms 0.00%
heimdall_cfg/simple 1501.1±16.14µs 1501.4±17.09µs +0.02%
heimdall_decoder/seaport 56.2±3.31µs 55.8±2.62µs -0.71%
heimdall_decoder/transfer 3.8±0.44µs 4.1±0.50µs +7.89%
heimdall_decoder/uniswap 15.4±0.60µs 15.4±0.59µs 0.00%
heimdall_decompiler/abi_complex 60.2±1.31ms 59.0±0.74ms -1.99%
heimdall_decompiler/abi_simple 1587.7±36.52µs 1603.9±37.33µs +1.02%
heimdall_decompiler/sol_complex 75.9±1.13ms 73.0±0.76ms -3.82%
heimdall_decompiler/sol_simple 1993.4±12.58µs 2.0±0.02ms +0.33%
heimdall_decompiler/yul_complex 66.3±0.69ms 66.4±0.79ms +0.15%
heimdall_decompiler/yul_simple 1798.4±70.48µs 1806.4±49.58µs +0.44%
heimdall_disassembler/complex 1157.0±24.93µs 1397.3±24.98µs +20.77%
heimdall_disassembler/simple 57.8±8.52µs 65.9±10.71µs +14.01%
heimdall_vm/erc20_transfer 275.0±19.75µs 275.2±21.74µs +0.07%
heimdall_vm/fib 950.7±25.12µs 957.5±52.31µs +0.72%
heimdall_vm/ten_thousand_hashes 679.3±6.80ms 684.6±8.15ms +0.78%

📊 View the full Criterion report

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