Allow funding errors in `full_stack_target` fuzzer
What changed, and why it matters
This commit changes a fuzz test (a randomized testing harness) so it no longer crashes when it tries to fund a channel that isn't ready to be funded. The change only affects test code, not the real Lightning node software that users run. It is a test-hardening fix, not a security patch for a vulnerability in production code.
No production action required. Reviewers may want to confirm that ignoring all funding errors in the fuzzer does not mask a real invariant violation in the underlying ChannelManager, but the commit message gives a plausible rationale.
Security signals we found
Change is confined to fuzz test code (fuzz/src/full_stack.rs)
Removal of a panic path in a test harness
No modification to production channel funding logic
Commit message frames the change as fuzzer behavior adjustment, not security fix
Evidence from the diff
The diff modifies fuzz/src/full_stack.rs. Previously, batch_funding_transaction_generated() errors were inspected: ChannelUnavailable was tolerated, but any other APIError caused a panic. After the change, all funding errors are silently ignored, and pending_funding_signatures is only populated when funding succeeds. The commit message explains the panic could be triggered legitimately when a channel is replaced before funding due to repeated RNG outputs in fuzzing. This is a fuzzer robustness change; the production channelmanager behavior is unchanged.
Changed components
fuzz/src/full_stack.rs test harnessInspect captured patch +7 / −13
diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs
index 3a5a549..88e68e5 100644
--- a/fuzz/src/full_stack.rs
+++ b/fuzz/src/full_stack.rs
@@ -857,21 +857,15 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
}
if tx.version.0 <= 0xff && !channels.is_empty() {
let chans = channels.iter().map(|(a, b)| (a, b)).collect::<Vec<_>>();
- if let Err(e) =
- channelmanager.batch_funding_transaction_generated(&chans, tx.clone())
- {
- // It's possible the channel has been closed in the mean time, but any other
- // failure may be a bug.
- if let APIError::ChannelUnavailable { .. } = e {
- } else {
- panic!();
+ let res =
+ channelmanager.batch_funding_transaction_generated(&chans, tx.clone());
+ if res.is_ok() {
+ let funding_txid = tx.compute_txid();
+ for idx in 0..tx.output.len() {
+ let outpoint = OutPoint { txid: funding_txid, index: idx as u16 };
+ pending_funding_signatures.insert(outpoint, tx.clone());
}
}
- let funding_txid = tx.compute_txid();
- for idx in 0..tx.output.len() {
- let outpoint = OutPoint { txid: funding_txid, index: idx as u16 };
- pending_funding_signatures.insert(outpoint, tx.clone());
- }
}
},
11 => {
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.