Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,13 +718,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 {
Expand Down Expand Up @@ -1024,6 +1027,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()
}
Expand Down Expand Up @@ -2959,9 +2971,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();

Expand Down Expand Up @@ -3383,6 +3400,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(),

0xf0 => harness.ab_link.complete_monitor_updates_for_node(
0,
Expand Down