fuzz: add chanmon holder signer fuzz ops
What changed, and why it matters
This commit only adds new fuzz-testing commands to an existing test harness. It lets the fuzzer temporarily block and then re-enable the local node's own signing operations during simulated channel failures. There is no change to production code, user-facing behavior, or real wallet security.
No action needed; this is a test-only change. Treat as routine fuzzing infrastructure improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch extends the chanmon_consistency fuzz target so that fuzz inputs can block SignHolderCommitment and SignHolderHtlcTransaction operations and later re-enable them, triggering retries of on-chain claim signing through the chain monitor. It is purely test infrastructure in fuzz/src/chanmon_consistency.rs; no library logic is modified.
Changed components
fuzz/src/chanmon_consistency.rsInspect captured patch +26 / −3
diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs
index 273af2a..c65e86d 100644
--- a/fuzz/src/chanmon_consistency.rs
+++ b/fuzz/src/chanmon_consistency.rs
@@ -880,13 +880,16 @@ impl SignerProvider for KeyProvider {
}
}
-// Since this fuzzer is only concerned with live-channel operations, we don't need to worry about
-// any signer operations that come after a force close.
-const SUPPORTED_SIGNER_OPS: [SignerOp; 4] = [
+// These signer operations can be blocked by fuzz bytes. The first four cover
+// live-channel and splice signing, while the holder-side operations cover local
+// on-chain claim signing after LDK has moved a channel to chain handling.
+const SUPPORTED_SIGNER_OPS: [SignerOp; 6] = [
SignerOp::SignCounterpartyCommitment,
SignerOp::GetPerCommitmentPoint,
SignerOp::ReleaseCommitmentSecret,
SignerOp::SignSpliceSharedInput,
+ SignerOp::SignHolderCommitment,
+ SignerOp::SignHolderHtlcTransaction,
];
impl KeyProvider {
@@ -1242,6 +1245,15 @@ impl<'a> HarnessNode<'a> {
self.node.timer_tick_occurred();
}
+ // Re-enables holder claim signing and asks the chain monitor to retry
+ // pending claim transactions. Different on-chain claim paths use
+ // SignHolderCommitment or SignHolderHtlcTransaction for force-closed channels.
+ fn enable_holder_signer_ops(&self) {
+ self.keys_manager.enable_op_for_all_signers(SignerOp::SignHolderCommitment);
+ self.keys_manager.enable_op_for_all_signers(SignerOp::SignHolderHtlcTransaction);
+ self.monitor.signer_unblocked(None);
+ }
+
fn current_feerate_sat_per_kw(&self) -> FeeRate {
self.fee_estimator.feerate_sat_per_kw()
}
@@ -3273,9 +3285,14 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
self.nodes[1].keys_manager.enable_op_for_all_signers(op);
self.nodes[2].keys_manager.enable_op_for_all_signers(op);
}
+ // Live-channel signer work retries through the manager, while
+ // on-chain holder claims retry through the chain monitor.
self.nodes[0].signer_unblocked(None);
self.nodes[1].signer_unblocked(None);
self.nodes[2].signer_unblocked(None);
+ self.nodes[0].monitor.signer_unblocked(None);
+ self.nodes[1].monitor.signer_unblocked(None);
+ self.nodes[2].monitor.signer_unblocked(None);
self.process_all_events();
@@ -3775,6 +3792,12 @@ pub fn do_test<Out: Output + MaybeSend + MaybeSync>(data: &[u8], out: Out) {
.enable_op_for_all_signers(SignerOp::SignSpliceSharedInput);
harness.nodes[2].signer_unblocked(None);
},
+ // The harness toggles signer availability at node granularity, not
+ // per channel, so each byte re-enables both holder claim ops and
+ // asks that node's monitors to retry.
+ 0xd3 => harness.nodes[0].enable_holder_signer_ops(),
+ 0xd4 => harness.nodes[1].enable_holder_signer_ops(),
+ 0xd5 => harness.nodes[2].enable_holder_signer_ops(),
0xd6 => harness.relay_broadcasts_for_node(0),
0xd7 => harness.relay_broadcasts_for_node(1),
0xd8 => harness.relay_broadcasts_for_node(2),
Why this scored 15/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.