Manually exit quiescence in fuzzing upon disconnect
What changed, and why it matters
This commit changes only a fuzzing test harness (chanmon_consistency.rs). It updates how the test handles peer-disconnect errors so that, when a disconnect happens during a quiescent (splice-related) state, the test manually clears that quiescent state on both sides. This is a test-only fix to prevent fuzzing false-positives; it does not change production code or fix a real-world security vulnerability.
No security action required. Treat as routine test/fuzzing harness maintenance.
Security signals we found
No production code changed
Change is confined to fuzz/src/chanmon_consistency.rs
Uses existing test-only helper ChannelManager::exit_quiescence
Commit message frames change as a fuzzing/test maintenance fix
Evidence from the diff
The diff renames assert_action_timeout_awaiting_response to assert_disconnect_action and makes it return the warning message and a flag indicating whether the disconnect was triggered by a quiescence/splice-locked error. Call sites in the fuzzing harness now, on detecting such a quiescent disconnect, call ChannelManager::exit_quiescence on both nodes. This is a test helper invocation inside fuzzing code only; no production logic is modified.
Changed components
fuzz/src/chanmon_consistency.rsInspect captured patch +24 / −16
diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs
index 4af1d13..532d4fc 100644
--- a/fuzz/src/chanmon_consistency.rs
+++ b/fuzz/src/chanmon_consistency.rs
@@ -769,19 +769,19 @@ type ChanMan<'a> = ChannelManager<
>;
#[inline]
-fn assert_action_timeout_awaiting_response(action: &msgs::ErrorAction) {
+fn assert_disconnect_action(action: &msgs::ErrorAction) -> (&msgs::WarningMessage, bool) {
// Since sending/receiving messages may be delayed, `timer_tick_occurred` may cause a node to
// disconnect their counterparty if they're expecting a timely response.
- assert!(
- matches!(
- action,
- msgs::ErrorAction::DisconnectPeerWithWarning { msg }
- if msg.data.contains("Disconnecting due to timeout awaiting response")
- || msg.data.contains("already sent splice_locked, cannot RBF")
- ),
- "Expected timeout disconnect, got: {:?}",
- action,
- );
+ if let msgs::ErrorAction::DisconnectPeerWithWarning { ref msg } = action {
+ let is_quiescent_msg = msg.data.contains("already sent splice_locked, cannot RBF");
+ if !msg.data.contains("Disconnecting due to timeout awaiting response") && !is_quiescent_msg
+ {
+ panic!("Unexpected disconnect case: {}", msg.data);
+ }
+ (msg, is_quiescent_msg)
+ } else {
+ panic!("Expected disconnect, got: {:?}", action);
+ }
}
#[derive(Clone, Copy, PartialEq)]
@@ -1286,7 +1286,7 @@ impl EventQueues {
*node_id == a_id
},
MessageSendEvent::HandleError { ref action, ref node_id } => {
- assert_action_timeout_awaiting_response(action);
+ assert_disconnect_action(action);
if Some(*node_id) == expect_drop_id {
panic!(
"peer_disconnected should drop msgs bound for the disconnected peer"
@@ -1335,7 +1335,7 @@ impl EventQueues {
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
MessageSendEvent::SendChannelUpdate { .. } => {},
MessageSendEvent::HandleError { ref action, .. } => {
- assert_action_timeout_awaiting_response(action);
+ assert_disconnect_action(action);
},
_ => panic!("Unhandled message event"),
}
@@ -1354,7 +1354,7 @@ impl EventQueues {
MessageSendEvent::BroadcastChannelUpdate { .. } => {},
MessageSendEvent::SendChannelUpdate { .. } => {},
MessageSendEvent::HandleError { ref action, .. } => {
- assert_action_timeout_awaiting_response(action);
+ assert_disconnect_action(action);
},
_ => panic!("Unhandled message event"),
}
@@ -2645,8 +2645,16 @@ impl<'a, Out: Output + MaybeSend + MaybeSync> Harness<'a, Out> {
nodes[dest_idx].handle_splice_locked(source_node_id, msg);
None
},
- MessageSendEvent::HandleError { ref action, .. } => {
- assert_action_timeout_awaiting_response(action);
+ MessageSendEvent::HandleError { ref action, ref node_id, .. } => {
+ let (msg, is_quiescent) = assert_disconnect_action(action);
+ let dest_idx = log_peer_message(node_idx, node_id, nodes, out, "warning");
+ if is_quiescent {
+ nodes[node_idx].node.exit_quiescence(node_id, &msg.channel_id).unwrap();
+ nodes[dest_idx]
+ .node
+ .exit_quiescence(&source_node_id, &msg.channel_id)
+ .unwrap();
+ }
None
},
MessageSendEvent::SendChannelReady { .. }
Why this scored 16/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.