Skip to content

ir: add BIP152 getblocktxn/getdata(cmpctblock) generators + probe feedback loop#150

Draft
brunoerg wants to merge 1 commit into
oss-garage:masterfrom
brunoerg:compact-blocks
Draft

ir: add BIP152 getblocktxn/getdata(cmpctblock) generators + probe feedback loop#150
brunoerg wants to merge 1 commit into
oss-garage:masterfrom
brunoerg:compact-blocks

Conversation

@brunoerg

@brunoerg brunoerg commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Add GetCompactBlockGenerator and GetBlockTxnGenerator so the IR can drive the pull side of compact block relay: request a compact block via getdata(MSG_CMPCT_BLOCK) for a block the node announced, and follow up with a getblocktxn for a cmpctblock the node sent us.

Neither flow can be synthesized in a single program (a getblocktxn is only meaningful after the node itself sends a cmpctblock, which the IR cannot fabricate). Instead, extend the probe mechanism to record headers/inv and cmpctblock messages, decode them into BlockAnnouncement/ CompactBlockAnnouncement metadata, and let generators insert the matching follow-up request right after the instruction that triggered the announcement on a later mutation pass.

Refactor bin/ir.rs into fuzzamoto-scenarios/src/lib.rs as a generic IrScenario<TX, T, const CMPCT: bool> so the existing scenario and the new compact-block variant (scenario-ir-cmpctblock, bin/ir_cmpctblock.rs) share one implementation, differing only in which messages get recorded/drained (is there a better way to do it? I ended up creating this lib.rs to avoid duplicating code).

@dergoegge

Copy link
Copy Markdown
Member

Neither flow can be synthesized in a single program (a getblocktxn is only meaningful after the node itself sends a cmpctblock, which the IR cannot fabricate). Instead, extend the probe mechanism to record headers/inv and cmpctblock messages, decode them into BlockAnnouncement/ CompactBlockAnnouncement metadata, and let generators insert the matching follow-up request right after the instruction that triggered the announcement on a later mutation pass.

Any block a node announces will have been generated by the IR, so I'm not sure if we need to split into two separate scenarios. If the scenario receives an inv or cmpctblock etc., the probing should result in testcase metadata, that tells a generator/mutator details about what mutations would be useful (similar to how the probing for blocktxn already works).

@brunoerg

brunoerg commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Any block a node announces will have been generated by the IR, so I'm not sure if we need to split into two separate scenarios. If the scenario receives an inv or cmpctblock etc., the probing should result in testcase metadata, that tells a generator/mutator details about what mutations would be useful (similar to how the probing for blocktxn already works).

I was in doubt about this part, will see it better.

@brunoerg

brunoerg commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, @dergoegge. I've changed it back to be just one scenario with an identical approach of the probing for blocktxn. I will leave it running overnight and generate a coverage report.

@dergoegge dergoegge added the needs benchmark Run the benchmark pipeline on this PR label Jul 3, 2026
@dergoegge

Copy link
Copy Markdown
Member
📊 time: 36m-56s (x2) execs: 58924 cov: 9.663% corpus: 3994 exec/sec: 26.84 stability: 95.144% bugs: 0
📊 time: 36m-58s (x2) execs: 58985 cov: 9.663% corpus: 3995 exec/sec: 26.84 stability: 95.144% bugs: 0
📊 time: 37m-0s (x2) execs: 59006 cov: 9.663% corpus: 3996 exec/sec: 26.83 stability: 95.144% bugs: 0
📊 time: 37m-2s (x2) execs: 59032 cov: 9.663% corpus: 3997 exec/sec: 26.82 stability: 95.144% bugs: 0
💗 time: 37m-4s (x2) execs: 59065 cov: 9.663% corpus: 3998 exec/sec: 26.80 stability: 95.144% bugs: 0
📊 time: 37m-9s (x2) execs: 59310 cov: 9.663% corpus: 3998 exec/sec: 26.85 stability: 95.144% bugs: 0

thread 'main' (21) panicked at fuzzamoto-ir/src/generators/get_compact_block.rs:59:14:
Inserting SendGetData should always succeed: VariableNotDefined(84)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

thread 'main' (14) panicked at /root/.cargo/git/checkouts/libafl-df9415290f13ce43/3b21190/crates/libafl/src/events/llmp/restarting.rs:899:21:
Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: 101)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Fuzzing stopped by user. Good bye.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Fuzzing Evaluation Report

Baseline (A): master (b4c4f699554d)
Experiment (B): compact-blocks (1d46a6abc8b2)

1. Summary Statistics

Evaluation window: 0.610 h · trials: 10 baseline / 10 experiment

Metric Baseline Experiment
Median final coverage (%) 9.700 9.836
Median AUC (coverage·h) 5.568 5.660
Median execs/s 23.507 24.655
Crashes (total) 0 0

Experiment vs. baseline comparison:

Statistic Coverage AUC (speed)
Adj. p-value 0.212 0.089
Â12 0.670 0.730

Raw P-values and Interquartile Ranges (IQRs) are available in evaluation_metrics.csv.


📦 Download the full report (visualizations + interpretation guide, as a zip).

@brunoerg

brunoerg commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author
📊 time: 36m-56s (x2) execs: 58924 cov: 9.663% corpus: 3994 exec/sec: 26.84 stability: 95.144% bugs: 0
📊 time: 36m-58s (x2) execs: 58985 cov: 9.663% corpus: 3995 exec/sec: 26.84 stability: 95.144% bugs: 0
📊 time: 37m-0s (x2) execs: 59006 cov: 9.663% corpus: 3996 exec/sec: 26.83 stability: 95.144% bugs: 0
📊 time: 37m-2s (x2) execs: 59032 cov: 9.663% corpus: 3997 exec/sec: 26.82 stability: 95.144% bugs: 0
💗 time: 37m-4s (x2) execs: 59065 cov: 9.663% corpus: 3998 exec/sec: 26.80 stability: 95.144% bugs: 0
📊 time: 37m-9s (x2) execs: 59310 cov: 9.663% corpus: 3998 exec/sec: 26.85 stability: 95.144% bugs: 0

thread 'main' (21) panicked at fuzzamoto-ir/src/generators/get_compact_block.rs:59:14:
Inserting SendGetData should always succeed: VariableNotDefined(84)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

thread 'main' (14) panicked at /root/.cargo/git/checkouts/libafl-df9415290f13ce43/3b21190/crates/libafl/src/events/llmp/restarting.rs:899:21:
Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: 101)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Fuzzing stopped by user. Good bye.

Got the same, fixing it. I think GetCompactBlockGenerator/GetBlockTxnGenerator trusted connection/block variable indices from cached per-corpus-entry probe metadata that could go stale.

@dergoegge dergoegge removed the needs benchmark Run the benchmark pipeline on this PR label Jul 3, 2026
…dback loop

Add GetCompactBlockGenerator and GetBlockTxnGenerator so the IR can drive
the pull side of compact block relay: request a compact block via
getdata(MSG_CMPCT_BLOCK) for a block the node announced, and follow up
with a getblocktxn for a cmpctblock the node sent us.

Neither flow can be synthesized in a single program (a getblocktxn is only
meaningful after the node itself sends a cmpctblock, which the IR cannot
fabricate). Instead, extend the probe mechanism to record headers/inv and
cmpctblock messages, decode them into BlockAnnouncement/
CompactBlockAnnouncement metadata, and let generators insert the matching
follow-up request right after the instruction that triggered the
announcement on a later mutation pass.

IrScenario now always records getblocktxn/cmpctblock/headers/inv and always
drains connections with recording enabled while probing; any block the node
announces was built by the IR itself on another connection, so there is
nothing to gate behind a separate mode.
@brunoerg

brunoerg commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Force-pushed 1d46a6a..23af266 with a fix for #150 (comment). I left it running for 2 days and didn't get any panics anymore. I'm generating a coverage 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.

2 participants