Skip to content

Commit e60f8d7

Browse files
committed
Address ChannelState inconsistency throughout splicing
Once a channel open has become locked (i.e., we've entered `ChannelState::ChannelReady`), the channel is intended to remain within this state for the rest of its lifetime until shutdown. Previously, we had assumed a channel being spliced would go through the `ChannelState` lifecycle again starting from `NegotiatingFunding` but skipping `AwaitingChannelReady`. This inconsistency departs from what we strive to achieve with `ChannelState` and also makes the state of a channel harder to reason about. This commit ensures a channel undergoing a splice remains in `ChannelReady`, clearing the quiescent flag once the negotiation is complete. Dual funding is unaffected by this change as the channel is being opened and we want to maintain the same `ChannelState` lifecycle.
1 parent 65e46a5 commit e60f8d7

File tree

1 file changed

+38
-17
lines changed

1 file changed

+38
-17
lines changed

lightning/src/ln/channel.rs

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -699,9 +699,9 @@ enum ChannelState {
699699
/// `AwaitingChannelReady`. Note that this is nonsense for an inbound channel as we immediately generate
700700
/// `funding_signed` upon receipt of `funding_created`, so simply skip this state.
701701
///
702-
/// For inbound and outbound interactively funded channels (dual-funding/splicing), this flag indicates
702+
/// For inbound and outbound interactively funded channels (dual-funding/splicing), this state indicates
703703
/// that interactive transaction construction has been completed and we are now interactively signing
704-
/// the funding/splice transaction.
704+
/// the initial funding transaction.
705705
FundingNegotiated(FundingNegotiatedFlags),
706706
/// We've received/sent `funding_created` and `funding_signed` and are thus now waiting on the
707707
/// funding transaction to confirm.
@@ -1913,6 +1913,14 @@ where
19131913
let logger = WithChannelContext::from(logger, self.context(), None);
19141914
match &mut self.phase {
19151915
ChannelPhase::UnfundedV2(chan) => {
1916+
debug_assert_eq!(
1917+
chan.context.channel_state,
1918+
ChannelState::NegotiatingFunding(
1919+
NegotiatingFundingFlags::OUR_INIT_SENT
1920+
| NegotiatingFundingFlags::THEIR_INIT_SENT
1921+
),
1922+
);
1923+
19161924
let signing_session = chan
19171925
.interactive_tx_constructor
19181926
.take()
@@ -6068,7 +6076,6 @@ where
60686076
funding
60696077
.channel_transaction_parameters.funding_outpoint = Some(outpoint);
60706078
self.interactive_tx_signing_session = Some(signing_session);
6071-
self.channel_state = ChannelState::FundingNegotiated(FundingNegotiatedFlags::new());
60726079

60736080
if is_splice {
60746081
debug_assert_eq!(
@@ -6079,6 +6086,7 @@ where
60796086
return Err(AbortReason::InternalError("Splicing not yet supported"));
60806087
} else {
60816088
self.assert_no_commitment_advancement(holder_commitment_transaction_number, "initial commitment_signed");
6089+
self.channel_state = ChannelState::FundingNegotiated(FundingNegotiatedFlags::new());
60826090
}
60836091

60846092
let commitment_signed = self.get_initial_commitment_signed_v2(&funding, logger);
@@ -6163,9 +6171,7 @@ where
61636171
SP::Target: SignerProvider,
61646172
L::Target: Logger,
61656173
{
6166-
assert!(
6167-
matches!(self.channel_state, ChannelState::FundingNegotiated(_) if self.interactive_tx_signing_session.is_some())
6168-
);
6174+
debug_assert!(self.interactive_tx_signing_session.is_some());
61696175

61706176
let signature = self.get_initial_counterparty_commitment_signature(funding, logger);
61716177
if let Some(signature) = signature {
@@ -8538,6 +8544,27 @@ where
85388544
}
85398545
}
85408546

8547+
fn on_tx_signatures_exchange(&mut self, funding_tx: Transaction) {
8548+
debug_assert!(!self.context.channel_state.is_monitor_update_in_progress());
8549+
debug_assert!(!self.context.channel_state.is_awaiting_remote_revoke());
8550+
8551+
if let Some(pending_splice) = self.pending_splice.as_mut() {
8552+
if let Some(FundingNegotiation::AwaitingSignatures(mut funding)) =
8553+
pending_splice.funding_negotiation.take()
8554+
{
8555+
funding.funding_transaction = Some(funding_tx);
8556+
self.pending_funding.push(funding);
8557+
} else {
8558+
debug_assert!(false, "We checked we were in the right state above");
8559+
}
8560+
self.context.channel_state.clear_quiescent();
8561+
} else {
8562+
self.funding.funding_transaction = Some(funding_tx);
8563+
self.context.channel_state =
8564+
ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
8565+
}
8566+
}
8567+
85418568
pub fn funding_transaction_signed(
85428569
&mut self, funding_txid_signed: Txid, witnesses: Vec<Witness>,
85438570
) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), APIError> {
@@ -8585,10 +8612,9 @@ where
85858612
.provide_holder_witnesses(tx_signatures, &self.context.secp_ctx)
85868613
.map_err(|err| APIError::APIMisuseError { err })?;
85878614

8588-
if funding_tx_opt.is_some() {
8589-
self.funding.funding_transaction = funding_tx_opt.clone();
8590-
self.context.channel_state =
8591-
ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
8615+
if let Some(funding_tx) = funding_tx_opt.clone() {
8616+
debug_assert!(tx_signatures_opt.is_some());
8617+
self.on_tx_signatures_exchange(funding_tx);
85928618
}
85938619

85948620
Ok((tx_signatures_opt, funding_tx_opt))
@@ -8625,13 +8651,8 @@ where
86258651
let (holder_tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg)
86268652
.map_err(|msg| ChannelError::Warn(msg))?;
86278653

8628-
if funding_tx_opt.is_some() {
8629-
// TODO(splicing): Transition back to `ChannelReady` and not `AwaitingChannelReady`
8630-
// We will also need to use the pending `FundingScope` in the splicing case.
8631-
//
8632-
// We have a finalized funding transaction, so we can set the funding transaction.
8633-
self.funding.funding_transaction = funding_tx_opt.clone();
8634-
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
8654+
if let Some(funding_tx) = funding_tx_opt.clone() {
8655+
self.on_tx_signatures_exchange(funding_tx);
86358656
}
86368657

86378658
Ok((holder_tx_signatures_opt, funding_tx_opt))

0 commit comments

Comments
 (0)