Skip to content

Commit 5a5d061

Browse files
committed
Stop skipping the line in quiescence if our peer speaks first
In the case where we prepare to initiate quiescence, but cannot yet send our `stfu` because we're waiting on some channel operations to settle, and our peer ultimately sends their `stfu` before we can, we would detect this case and, if we were able, send an `stfu` which would allow us to send "something fundamental" first. While this is a nifty optimization, its a bit overkill - the chance that both us and our peer decide to attempt something fundamental at the same time is pretty low, and worse this required additional state tracking. We simply remove this optimization here, simplifying the quiescence state machine a good bit.
1 parent 6a4169d commit 5a5d061

File tree

2 files changed

+18
-51
lines changed

2 files changed

+18
-51
lines changed

lightning/src/ln/channel.rs

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2742,10 +2742,6 @@ where
27422742
/// If we can't release a [`ChannelMonitorUpdate`] until some external action completes, we
27432743
/// store it here and only release it to the `ChannelManager` once it asks for it.
27442744
blocked_monitor_updates: Vec<PendingChannelMonitorUpdate>,
2745-
2746-
/// Only set when a counterparty `stfu` has been processed to track which node is allowed to
2747-
/// propose "something fundamental" upon becoming quiescent.
2748-
is_holder_quiescence_initiator: Option<bool>,
27492745
}
27502746

27512747
/// A channel struct implementing this trait can receive an initial counterparty commitment
@@ -3320,8 +3316,6 @@ where
33203316
blocked_monitor_updates: Vec::new(),
33213317

33223318
is_manual_broadcast: false,
3323-
3324-
is_holder_quiescence_initiator: None,
33253319
};
33263320

33273321
Ok((funding, channel_context))
@@ -3558,8 +3552,6 @@ where
35583552
blocked_monitor_updates: Vec::new(),
35593553
local_initiated_shutdown: None,
35603554
is_manual_broadcast: false,
3561-
3562-
is_holder_quiescence_initiator: None,
35633555
};
35643556

35653557
Ok((funding, channel_context))
@@ -8219,7 +8211,6 @@ where
82198211
self.context.channel_state.clear_local_stfu_sent();
82208212
self.context.channel_state.clear_remote_stfu_sent();
82218213
self.context.channel_state.clear_quiescent();
8222-
self.context.is_holder_quiescence_initiator.take();
82238214
}
82248215

82258216
self.context.channel_state.set_peer_disconnected();
@@ -11610,18 +11601,10 @@ where
1161011601
self.context.channel_state.clear_awaiting_quiescence();
1161111602
self.context.channel_state.clear_remote_stfu_sent();
1161211603
self.context.channel_state.set_quiescent();
11613-
if let Some(initiator) = self.context.is_holder_quiescence_initiator.as_ref() {
11614-
log_debug!(
11615-
logger,
11616-
"Responding to counterparty stfu with our own, channel is now quiescent and we are{} the initiator",
11617-
if !initiator { " not" } else { "" }
11618-
);
11619-
11620-
*initiator
11621-
} else {
11622-
debug_assert!(false, "Quiescence initiator must have been set when we received stfu");
11623-
false
11624-
}
11604+
// We are sending an stfu in response to our couterparty's stfu, but had not yet sent
11605+
// our own stfu (even if `awaiting_quiescence` was set). Thus, the counterparty is the
11606+
// initiator and they can do "something fundamental".
11607+
false
1162511608
} else {
1162611609
log_debug!(logger, "Sending stfu as quiescence initiator");
1162711610
debug_assert!(self.context.channel_state.is_awaiting_quiescence());
@@ -11652,9 +11635,7 @@ where
1165211635
));
1165311636
}
1165411637

11655-
if self.context.channel_state.is_awaiting_quiescence()
11656-
|| !self.context.channel_state.is_local_stfu_sent()
11657-
{
11638+
if !self.context.channel_state.is_local_stfu_sent() {
1165811639
if !msg.initiator {
1165911640
return Err(ChannelError::WarnAndDisconnect(
1166011641
"Peer sent unexpected `stfu` without signaling as initiator".to_owned()
@@ -11668,23 +11649,13 @@ where
1166811649
// then.
1166911650
self.context.channel_state.set_remote_stfu_sent();
1167011651

11671-
let is_holder_initiator = if self.context.channel_state.is_awaiting_quiescence() {
11672-
// We were also planning to propose quiescence, let the tie-breaker decide the
11673-
// initiator.
11674-
self.funding.is_outbound()
11675-
} else {
11676-
false
11677-
};
11678-
self.context.is_holder_quiescence_initiator = Some(is_holder_initiator);
11679-
1168011652
log_debug!(logger, "Received counterparty stfu proposing quiescence");
1168111653
return self.send_stfu(logger).map(|stfu| Some(stfu));
1168211654
}
1168311655

1168411656
// We already sent `stfu` and are now processing theirs. It may be in response to ours, or
1168511657
// we happened to both send `stfu` at the same time and a tie-break is needed.
1168611658
let is_holder_quiescence_initiator = !msg.initiator || self.funding.is_outbound();
11687-
self.context.is_holder_quiescence_initiator = Some(is_holder_quiescence_initiator);
1168811659

1168911660
// We were expecting to receive `stfu` because we already sent ours.
1169011661
self.mark_response_received();
@@ -11752,13 +11723,10 @@ where
1175211723
debug_assert!(!self.context.channel_state.is_local_stfu_sent());
1175311724
debug_assert!(!self.context.channel_state.is_remote_stfu_sent());
1175411725

11755-
if self.context.channel_state.is_quiescent() {
11756-
self.mark_response_received();
11757-
self.context.channel_state.clear_quiescent();
11758-
self.context.is_holder_quiescence_initiator.take().expect("Must always be set while quiescent")
11759-
} else {
11760-
false
11761-
}
11726+
self.mark_response_received();
11727+
let was_quiescent = self.context.channel_state.is_quiescent();
11728+
self.context.channel_state.clear_quiescent();
11729+
was_quiescent
1176211730
}
1176311731

1176411732
pub fn remove_legacy_scids_before_block(&mut self, height: u32) -> alloc::vec::Drain<'_, u64> {
@@ -14018,8 +13986,6 @@ where
1401813986

1401913987
blocked_monitor_updates: blocked_monitor_updates.unwrap(),
1402013988
is_manual_broadcast: is_manual_broadcast.unwrap_or(false),
14021-
14022-
is_holder_quiescence_initiator: None,
1402313989
},
1402413990
interactive_tx_signing_session,
1402513991
holder_commitment_point,

lightning/src/ln/quiescence_tests.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn test_quiescence_tie() {
3333
assert!(stfu_node_0.initiator && stfu_node_1.initiator);
3434

3535
assert!(nodes[0].node.exit_quiescence(&nodes[1].node.get_our_node_id(), &chan_id).unwrap());
36-
assert!(!nodes[1].node.exit_quiescence(&nodes[0].node.get_our_node_id(), &chan_id).unwrap());
36+
assert!(nodes[1].node.exit_quiescence(&nodes[0].node.get_our_node_id(), &chan_id).unwrap());
3737
}
3838

3939
#[test]
@@ -173,7 +173,8 @@ fn allow_shutdown_while_awaiting_quiescence(local_shutdown: bool) {
173173

174174
// Now that the state machine is no longer pending, and `closing_signed` is ready to be sent,
175175
// make sure we're still not waiting for the quiescence handshake to complete.
176-
local_node.node.exit_quiescence(&remote_node_id, &chan_id).unwrap();
176+
// Note that we never actually reached full quiescence here.
177+
assert!(!local_node.node.exit_quiescence(&remote_node_id, &chan_id).unwrap());
177178

178179
let _ = get_event_msg!(local_node, MessageSendEvent::SendClosingSigned, remote_node_id);
179180
check_added_monitors(local_node, 2); // One for the last revoke_and_ack, another for closing_signed
@@ -279,8 +280,8 @@ fn test_quiescence_waits_for_async_signer_and_monitor_update() {
279280
let stfu = get_event_msg!(&nodes[0], MessageSendEvent::SendStfu, node_id_1);
280281
nodes[1].node.handle_stfu(node_id_0, &stfu);
281282

282-
nodes[0].node.exit_quiescence(&node_id_1, &chan_id).unwrap();
283-
nodes[1].node.exit_quiescence(&node_id_0, &chan_id).unwrap();
283+
assert!(nodes[0].node.exit_quiescence(&node_id_1, &chan_id).unwrap());
284+
assert!(nodes[1].node.exit_quiescence(&node_id_0, &chan_id).unwrap());
284285

285286
// After exiting quiescence, we should be able to resume payments from nodes[0].
286287
send_payment(&nodes[0], &[&nodes[1]], payment_amount);
@@ -336,8 +337,8 @@ fn test_quiescence_on_final_revoke_and_ack_pending_monitor_update() {
336337
panic!();
337338
}
338339

339-
nodes[0].node.exit_quiescence(&node_id_1, &chan_id).unwrap();
340-
nodes[1].node.exit_quiescence(&node_id_0, &chan_id).unwrap();
340+
assert!(nodes[0].node.exit_quiescence(&node_id_1, &chan_id).unwrap());
341+
assert!(nodes[1].node.exit_quiescence(&node_id_0, &chan_id).unwrap());
341342
}
342343

343344
#[test]
@@ -406,8 +407,8 @@ fn quiescence_updates_go_to_holding_cell(fail_htlc: bool) {
406407
let stfu = get_event_msg!(&nodes[0], MessageSendEvent::SendStfu, node_id_1);
407408
nodes[1].node.handle_stfu(node_id_0, &stfu);
408409

409-
nodes[0].node.exit_quiescence(&node_id_1, &chan_id).unwrap();
410-
nodes[1].node.exit_quiescence(&node_id_0, &chan_id).unwrap();
410+
assert!(nodes[0].node.exit_quiescence(&node_id_1, &chan_id).unwrap());
411+
assert!(nodes[1].node.exit_quiescence(&node_id_0, &chan_id).unwrap());
411412

412413
// Now that quiescence is over, nodes are allowed to make updates again. nodes[1] will have its
413414
// outbound HTLC finally go out, along with the fail/claim of nodes[0]'s payment.

0 commit comments

Comments
 (0)