Repository navigation
fuzz: add fuzzing that tests pruning - #404
Merged
apoelstra merged 2 commits intoNov 6, 2026
Merged
Conversation
stringhandler
marked this pull request as ready for review
November 6, 2026 10:29
stringhandler
force-pushed
the
st-fuzz-prune-generated
branch
from
November 6, 2026 10:30
efd860d to
0b5656c
Compare
Collaborator
|
In 229cc0c: Your commit message has a stray comment :) |
Collaborator
|
I can't tell whether the CI failure is related. I kicked the Windows job. It had a link error related to being unable to find |
The existing generator picks a combinator and then type checks it, so few of its programs are well-typed, and those are tiny. Add a generator which picks a type first, and then only combinators which can have that type, so every program is well-typed. It never generates fail, assertions or jets which can fail, so every program also runs. It reuses nodes, so that pruning sees nodes shared between hidden and kept code, runs some case nodes on two inputs, so that they take both branches, and generates disconnect nodes. It uses Elements jets, because libsimplicity decodes Elements jet codes. It does not generate separate nodes with one IHR but different types inside them, which only unit tests cover. Add check_prune, which prunes a generated program and checks that: * the pruned program keeps the CMR and runs, * it decodes to the same IHR and AMR and encodes back to the same bytes, * libsimplicity accepts it and computes the same CMR, AMR and IHR, * libsimplicity rejects the unpruned program as anti-DOS exactly when pruning hid a branch. Programs which pruning fails on with ExecutionError::PruningFailed are counted rather than checked, and the tests require them to be rare. Programs over a cost cap are skipped: their cost comes from running the same nodes many times, which takes time without exercising pruning. The prune_generated target calls check_prune, with long inputs from the start, as only those give large programs. A test of the fuzz library calls it on 1000 inputs, in a new job of the fuzz workflow. Also build ElementsEnv::dummy with the test-utils feature, so that the fuzz crate can run Elements jets. Assisted-by: Claude
stringhandler
force-pushed
the
st-fuzz-prune-generated
branch
from
November 6, 2026 14:50
0b5656c to
698a2b0
Compare
Contributor
Author
|
fixed both |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In #403 we added a fix for pruning. This PR adds code to fuzz pruning of programs, which didn't exist before. It is LLM generated. It is also built on top of #403, so it needs that PR to be merged first.
Results
Measured on 20,000 generated programs, from the inputs that
pseudorandom_inputsgives (the CI test uses the first 1,000):PruningFailed)disconnectnodeOn the commit before the #391 fix, 64 of the CI test's 1,000 programs fail, the first at input 1. libFuzzer, with the
-len_control=0 -max_len=4096thatfuzz.shnow passes, finds the bug from an empty corpus in 7, 12 and 32 seconds (3 runs).Coverage of
src/node/prune.rs, over the CI test's inputs and a 2,712-input libFuzzer corpus: 97.6% of lines and all 23 functions. The uncovered lines are error paths: programs that fail to run, and the rejections in the check after pruning.Not covered: the generator never produces separate nodes with one IHR but different types inside them (0 of 20,000), so only unit tests cover merging such nodes before pruning.