Skip to content

Minset corpus edge indices#14856

Open
0xalpharush wants to merge 2 commits into
foundry-rs:masterfrom
0xalpharush:minset-corpus-edge-indices
Open

Minset corpus edge indices#14856
0xalpharush wants to merge 2 commits into
foundry-rs:masterfrom
0xalpharush:minset-corpus-edge-indices

Conversation

@0xalpharush
Copy link
Copy Markdown
Collaborator

@0xalpharush 0xalpharush commented May 21, 2026

Stacked on #14853

Motivation

The current corpora may not retain an entry for which it is the only one coverage that edge. Additionally, once a corpus entry is on disk, we no longer splice it, losing some diversity of earlier discoveries if a subsequent entry "wins".

OSS-187

Solution

Replace mutation-count favorability with top-rated minset culling for coverage-guided corpora. Corpus entries now track the coverage indices they contribute, and favored entries are selected as the cheapest known representatives for covered edges rather than by historical mutation success ratio.

Remove total_mutations/new_finds_produced, the favorability threshold, and the obsolete corpus_min_mutations config. Culling now keeps the configured minimum corpus size and evicts non-minset entries.

Track hash coverage hit indices explicitly alongside hitcounts so minset bookkeeping can use stable edge IDs without scanning the dense hitcount map. Collision-free mode continues to use stable EdgeIndexMap IDs.

Add two on-disk crossover mutations:

  • CrossoverInsert inserts a transaction loaded from a persisted corpus entry into the current sequence.

  • CrossoverReplace replaces a transaction in the current sequence with one loaded from a persisted corpus entry.

Cache persisted corpus file entries to avoid rescanning the corpus directory on every crossover while preserving the on-disk donor source.

Experiment

On aave scfuzzbench target, I observe higher throughput and a smaller corpus. This was for a short run and more thorough benchmarking should probably be done.

@grandizzy
Copy link
Copy Markdown
Collaborator

Benchmark: 1h Aave v4 SCFuzzBench campaign (seed=42)

Stacked-PR follow-up to the #14853 benchmark. Same setup: Recon-Fuzz/aave-v4-scfuzzbench, forge test --mc CryticToFoundry --fuzz-seed 42, FOUNDRY_INVARIANT_TIMEOUT=3600, same host, sequential runs.

Results

Config total txs tx/s (peak) edges features corpus favored inv breaks handler asserts total bugs peak RSS
master (collision_free=false, include_call_depth=false) 29.95M ~862 352–373 372–488 306–368 3 4 7 4.29 GB
#14853 default (collision_free=true, include_call_depth=false) 30.27M ~901 376–378 442–475 322–351 4 3 7 4.45 GB
#14853 (collision_free=true, include_call_depth=true) 28.45M ~790 396–401 422–447 364–380 3 2 5 4.43 GB
#14853 (collision_free=false, include_call_depth=true) 32.16M ~1117 371–409 421–500 325–398 4 3 7 4.39 GB
#14856 default (minset + crossover, on top of #14853 default) 29.85M ~841 364–374 338–413 297–318 151–160 3 3 6 9.08 GB

Unique bugs by config

Bug master #14853 default #14853 +depth #14853 hash+depth #14856 default
invariant_canary
invariant_shouldNotBecomeLiquidatable
invariant_totalBorrowedLessThanSupplied_v0
invariant_totalBorrowedLessThanSupplied_v1
invariant_totalBorrowedLessThanSupplied_v2
iHub_mintFeeShares_ASSERTION_MINT_FEE_SHARES_PPS_CHANGE
iSpoke_repay_ASSERTION_REPAY_DOS
iSpoke_withdraw_ASSERTION_WITHDRAW_DOS
assert_canary_ASSERTION_CANARY
Total 7 7 5 7 6

Key findings

  1. Peak RSS roughly doubled vs feat: add configurable collision-free EVM edge coverage #14853 default (4.45 GB → 9.08 GB, +104%). The "smaller corpus" effect is real (final corpus 297–318 vs 322–351, ~8% smaller) but it's more than offset by the new bookkeeping — per-entry unique_edges_covered: Vec<usize>, the top_rated: HashMap<usize, (Uuid, usize)> index, and the disk_corpus_entries cache. Worth investigating whether this is sustainable for longer campaigns.
  2. Bug count dropped from 7 to 6 at seed=42. The two newly-found bugs in feat: add configurable collision-free EVM edge coverage #14853 default (totalBorrowedLessThanSupplied_v1 and _v2) were lost. iSpoke_withdraw_DOS came back though (which the CF+depth variant of feat: add configurable collision-free EVM edge coverage #14853 had lost). Caveat: single-seed run, real bug-finding variance is meaningful — would want multi-seed runs to call this a regression.
  3. Throughput regressed ~7% (901 → 841 tx/s) and ~1.4% fewer txs processed in the same wall time (30.27M → 29.85M). Consistent with the additional work for minset recomputation on each new entry and disk crossover I/O on each mutation.
  4. Edges and features both came in lower than feat: add configurable collision-free EVM edge coverage #14853 default (edges 376–378 → 364–374; features 442–475 → 338–413). Counter to the expectation that minset would preserve more coverage signal — possibly the corpus dilution from on-disk crossover with stale entries is fighting the minset retention.
  5. Favored items is now a meaningful metric — 151–160 per worker, vs always-0 in the historic favorability scheme. Each worker keeps roughly half its corpus as minset representatives.

@0xalpharush
Copy link
Copy Markdown
Collaborator Author

#14856 (comment)
doesn't this show 8 bugs on this PR?

Replace mutation-count favorability with top-rated minset culling for coverage-guided corpora. Corpus entries now track the coverage indices they contribute, and favored entries are selected as the cheapest known representatives for covered edges rather than by historical mutation success ratio.

Remove total_mutations/new_finds_produced, the favorability threshold, and the obsolete corpus_min_mutations config. Culling now keeps the configured minimum corpus size and evicts non-minset entries.

Track hash coverage hit indices explicitly alongside hitcounts so minset bookkeeping can use stable edge IDs without scanning the dense hitcount map. Collision-free mode continues to use stable EdgeIndexMap IDs.

Add two on-disk crossover mutations:

- CrossoverInsert inserts a transaction loaded from a persisted corpus entry into the current sequence.

- CrossoverReplace replaces a transaction in the current sequence with one loaded from a persisted corpus entry.

Cache persisted corpus file entries to avoid rescanning the corpus directory on every crossover while preserving the on-disk donor source.
@0xalpharush 0xalpharush force-pushed the minset-corpus-edge-indices branch from d08cf34 to e170eef Compare May 27, 2026 01:54
@grandizzy
Copy link
Copy Markdown
Collaborator

#14856 (comment) doesn't this show 8 bugs on this PR?

will redo the benches with the new per contract approach (similar with #14902 (comment)) and post back

@0xalpharush 0xalpharush marked this pull request as draft May 27, 2026 14:51
@0xalpharush
Copy link
Copy Markdown
Collaborator Author

actually i am going to push another commit to see if i can shrink memory usage

@0xalpharush 0xalpharush force-pushed the minset-corpus-edge-indices branch from 23cb414 to 333d94e Compare May 27, 2026 15:09
@0xalpharush 0xalpharush marked this pull request as ready for review May 28, 2026 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants