Skip to content

Commit c9b1041

Browse files
jkczyzwpaulino
authored andcommitted
Update next_funding_txid logic for channel_reestablish
The splicing spec updates the logic pertaining to next_funding_txid when handling a channel_reestablish message. Specifically: A receiving node: - if `next_funding_txid` is set: - if `next_funding_txid` matches the latest interactive funding transaction or the current channel funding transaction: - if `next_commitment_number` is equal to the commitment number of the `commitment_signed` message it sent for this funding transaction: - MUST retransmit its `commitment_signed` for that funding transaction. - if it has already received `commitment_signed` and it should sign first, as specified in the [`tx_signatures` requirements](#the-tx_signatures-message): - MUST send its `tx_signatures` for that funding transaction. - if it has already received `tx_signatures` for that funding transaction: - MUST send its `tx_signatures` for that funding transaction. - if it also sets `next_funding_txid` in its own `channel_reestablish`, but the values don't match: - MUST send an `error` and fail the channel. - otherwise: - MUST send `tx_abort` to let the sending node know that they can forget this funding transaction. Note that the spec is in flux. Instead, next_funding_txid is replaced with next_funding, which contains both a txid and retransmit_flags. The latter is used instead of next_commitment_number to determine whether commitment_signed should be retransmitted. This commit updates FundedChannel::channel_reestablish accordingly. Co-authored-by: Wilmer Paulino <[email protected]> Co-authored-by: Jeffrey Czyz <[email protected]>
1 parent af15b81 commit c9b1041

File tree

3 files changed

+195
-116
lines changed

3 files changed

+195
-116
lines changed

lightning/src/ln/channel.rs

Lines changed: 139 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -9158,9 +9158,9 @@ where
91589158
}
91599159

91609160
if msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER ||
9161-
(msg.next_local_commitment_number == 0 && msg.next_funding_txid.is_none()) {
9161+
(msg.next_local_commitment_number == 0 && msg.next_funding.is_none()) {
91629162
// Note: This also covers the following case in the V2 channel establishment specification:
9163-
// if `next_funding_txid` is not set, and `next_commitment_number` is zero:
9163+
// if `next_funding` is not set, and `next_commitment_number` is zero:
91649164
// MUST immediately fail the channel and broadcast any relevant latest commitment transaction.
91659165
return Err(ChannelError::close("Peer sent an invalid channel_reestablish to force close in a non-standard way".to_owned()));
91669166
}
@@ -9211,34 +9211,135 @@ where
92119211

92129212
let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block.height, logger);
92139213

9214+
let mut commitment_update = None;
9215+
let mut tx_signatures = None;
9216+
let mut tx_abort = None;
9217+
9218+
// if next_funding is set:
9219+
if let Some(next_funding) = &msg.next_funding {
9220+
// - if `next_funding` matches the latest interactive funding transaction
9221+
// or the current channel funding transaction:
9222+
if let Some(session) = &self.interactive_tx_signing_session {
9223+
let our_next_funding_txid = session.unsigned_tx().compute_txid();
9224+
if our_next_funding_txid != next_funding.txid {
9225+
return Err(ChannelError::close(format!(
9226+
"Unexpected next_funding txid: {}; expected: {}",
9227+
next_funding.txid, our_next_funding_txid,
9228+
)));
9229+
}
9230+
9231+
if !session.has_received_commitment_signed() {
9232+
self.context.expecting_peer_commitment_signed = true;
9233+
}
9234+
9235+
// TODO(splicing): Add comment for spec requirements
9236+
if next_funding.should_retransmit(msgs::NextFundingFlag::CommitmentSigned) {
9237+
#[cfg(splicing)]
9238+
let funding = self
9239+
.pending_splice
9240+
.as_ref()
9241+
.and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
9242+
.and_then(|funding_negotiation| {
9243+
if let FundingNegotiation::AwaitingSignatures(funding) = &funding_negotiation {
9244+
Some(funding)
9245+
} else {
9246+
None
9247+
}
9248+
})
9249+
.or_else(|| Some(&self.funding))
9250+
.filter(|funding| funding.get_funding_txid() == Some(next_funding.txid))
9251+
.ok_or_else(|| {
9252+
let message = "Failed to find funding for new commitment_signed".to_owned();
9253+
ChannelError::Close(
9254+
(
9255+
message.clone(),
9256+
ClosureReason::HolderForceClosed { message, broadcasted_latest_txn: Some(false) },
9257+
)
9258+
)
9259+
})?;
9260+
#[cfg(not(splicing))]
9261+
let funding = &self.funding;
9262+
9263+
let commitment_signed = self.context.get_initial_commitment_signed_v2(&funding, logger)
9264+
// TODO(splicing): Support async signing
9265+
.ok_or_else(|| {
9266+
let message = "Failed to get signatures for new commitment_signed".to_owned();
9267+
ChannelError::Close(
9268+
(
9269+
message.clone(),
9270+
ClosureReason::HolderForceClosed { message, broadcasted_latest_txn: Some(false) },
9271+
)
9272+
)
9273+
})?;
9274+
9275+
commitment_update = Some(msgs::CommitmentUpdate {
9276+
commitment_signed: vec![commitment_signed],
9277+
update_add_htlcs: vec![],
9278+
update_fulfill_htlcs: vec![],
9279+
update_fail_htlcs: vec![],
9280+
update_fail_malformed_htlcs: vec![],
9281+
update_fee: None,
9282+
});
9283+
}
9284+
9285+
// - if it has already received `commitment_signed` and it should sign first
9286+
// - MUST send its `tx_signatures` for that funding transaction.
9287+
//
9288+
// - if it has already received `tx_signatures` for that funding transaction:
9289+
// - MUST send its `tx_signatures` for that funding transaction.
9290+
if (session.has_received_commitment_signed() && session.holder_sends_tx_signatures_first())
9291+
|| self.context.channel_state.is_their_tx_signatures_sent()
9292+
{
9293+
// If `holder_tx_signatures` is `None` here, the `tx_signatures` message will be sent
9294+
// when the holder provides their witnesses as this will queue a `tx_signatures` if the
9295+
// holder must send one.
9296+
if session.holder_tx_signatures().is_none() {
9297+
log_debug!(logger, "Waiting for funding transaction signatures to be provided");
9298+
} else if self.context.channel_state.is_monitor_update_in_progress() {
9299+
log_debug!(logger, "Waiting for monitor update before providing funding transaction signatures");
9300+
} else {
9301+
tx_signatures = session.holder_tx_signatures().clone();
9302+
}
9303+
}
9304+
} else {
9305+
// We'll just send a `tx_abort` here if we don't have a signing session for this channel
9306+
// on reestablish and tell our peer to just forget about it.
9307+
// Our peer is doing something strange, but it doesn't warrant closing the channel.
9308+
tx_abort = Some(msgs::TxAbort {
9309+
channel_id: self.context.channel_id(),
9310+
data:
9311+
"No active signing session. The associated funding transaction may have already been broadcast.".as_bytes().to_vec() });
9312+
}
9313+
}
9314+
92149315
if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) {
92159316
// If we're waiting on a monitor update, we shouldn't re-send any channel_ready's.
92169317
if !self.context.channel_state.is_our_channel_ready() ||
92179318
self.context.channel_state.is_monitor_update_in_progress() {
92189319
if msg.next_remote_commitment_number != 0 {
92199320
return Err(ChannelError::close("Peer claimed they saw a revoke_and_ack but we haven't sent channel_ready yet".to_owned()));
92209321
}
9221-
// Short circuit the whole handler as there is nothing we can resend them
9322+
92229323
return Ok(ReestablishResponses {
92239324
channel_ready: None,
9224-
channel_ready_order: ChannelReadyOrder::ChannelReadyFirst,
9225-
raa: None, commitment_update: None,
9226-
commitment_order: RAACommitmentOrder::CommitmentFirst,
9325+
channel_ready_order: ChannelReadyOrder::SignaturesFirst,
9326+
raa: None, commitment_update,
9327+
commitment_order: self.context.resend_order.clone(),
92279328
shutdown_msg, announcement_sigs,
9228-
tx_signatures: None,
9329+
tx_signatures,
92299330
tx_abort: None,
92309331
});
92319332
}
92329333

92339334
// We have OurChannelReady set!
92349335
return Ok(ReestablishResponses {
92359336
channel_ready: self.get_channel_ready(logger),
9236-
channel_ready_order: ChannelReadyOrder::ChannelReadyFirst,
9237-
raa: None, commitment_update: None,
9238-
commitment_order: RAACommitmentOrder::CommitmentFirst,
9337+
channel_ready_order: ChannelReadyOrder::SignaturesFirst,
9338+
raa: None, commitment_update,
9339+
commitment_order: self.context.resend_order.clone(),
92399340
shutdown_msg, announcement_sigs,
9240-
tx_signatures: None,
9241-
tx_abort: None,
9341+
tx_signatures,
9342+
tx_abort,
92429343
});
92439344
}
92449345

@@ -9281,88 +9382,6 @@ where
92819382
log_debug!(logger, "Reconnected channel {} with no loss", &self.context.channel_id());
92829383
}
92839384

9284-
// if next_funding_txid is set:
9285-
let (commitment_update, tx_signatures, tx_abort) = if let Some(next_funding_txid) = msg.next_funding_txid {
9286-
if let Some(session) = &self.interactive_tx_signing_session {
9287-
// if next_funding_txid matches the latest interactive funding transaction:
9288-
let our_next_funding_txid = session.unsigned_tx().compute_txid();
9289-
if our_next_funding_txid == next_funding_txid {
9290-
debug_assert_eq!(session.unsigned_tx().compute_txid(), self.maybe_get_next_funding_txid().unwrap());
9291-
9292-
let commitment_update = if !self.context.channel_state.is_their_tx_signatures_sent() && msg.next_local_commitment_number == 0 {
9293-
// if it has not received tx_signatures for that funding transaction AND
9294-
// if next_commitment_number is zero:
9295-
// MUST retransmit its commitment_signed for that funding transaction.
9296-
let commitment_signed = self.context.get_initial_commitment_signed_v2(&self.funding, logger)
9297-
// TODO(splicing): Support async signing
9298-
.ok_or_else(|| {
9299-
let message = "Failed to get signatures for new commitment_signed".to_owned();
9300-
ChannelError::Close(
9301-
(
9302-
message.clone(),
9303-
ClosureReason::HolderForceClosed { message, broadcasted_latest_txn: Some(false) },
9304-
)
9305-
)})?;
9306-
Some(msgs::CommitmentUpdate {
9307-
commitment_signed: vec![commitment_signed],
9308-
update_add_htlcs: vec![],
9309-
update_fulfill_htlcs: vec![],
9310-
update_fail_htlcs: vec![],
9311-
update_fail_malformed_htlcs: vec![],
9312-
update_fee: None,
9313-
})
9314-
} else { None };
9315-
let tx_signatures = if (
9316-
// if it has not received tx_signatures for that funding transaction AND
9317-
// if it has already received commitment_signed AND it should sign first, as specified in the tx_signatures requirements:
9318-
// MUST send its tx_signatures for that funding transaction.
9319-
!self.context.channel_state.is_their_tx_signatures_sent() && session.has_received_commitment_signed() && session.holder_sends_tx_signatures_first()
9320-
// else if it has already received tx_signatures for that funding transaction:
9321-
// MUST send its tx_signatures for that funding transaction.
9322-
) || self.context.channel_state.is_their_tx_signatures_sent() {
9323-
// If `holder_tx_signatures` is `None` here, the `tx_signatures` message will be sent
9324-
// when the holder provides their witnesses as this will queue a `tx_signatures` if the
9325-
// holder must send one.
9326-
if session.holder_tx_signatures().is_none() {
9327-
log_debug!(logger, "Waiting for funding transaction signatures to be provided");
9328-
None
9329-
} else if self.context.channel_state.is_monitor_update_in_progress() {
9330-
log_debug!(logger, "Waiting for monitor update before providing funding transaction signatures");
9331-
None
9332-
} else {
9333-
session.holder_tx_signatures().clone()
9334-
}
9335-
} else {
9336-
None
9337-
};
9338-
if !session.has_received_commitment_signed() {
9339-
self.context.expecting_peer_commitment_signed = true;
9340-
}
9341-
(commitment_update, tx_signatures, None)
9342-
} else {
9343-
// The `next_funding_txid` does not match the latest interactive funding transaction so we
9344-
// MUST send tx_abort to let the remote know that they can forget this funding transaction.
9345-
(None, None, Some(msgs::TxAbort {
9346-
channel_id: self.context.channel_id(),
9347-
data: format!(
9348-
"next_funding_txid {} does match our latest interactive funding txid {}",
9349-
next_funding_txid, our_next_funding_txid,
9350-
).into_bytes() }))
9351-
}
9352-
} else {
9353-
// We'll just send a `tx_abort` here if we don't have a signing session for this channel
9354-
// on reestablish and tell our peer to just forget about it.
9355-
// Our peer is doing something strange, but it doesn't warrant closing the channel.
9356-
(None, None, Some(msgs::TxAbort {
9357-
channel_id: self.context.channel_id(),
9358-
data:
9359-
"No active signing session. The associated funding transaction may have already been broadcast.".as_bytes().to_vec() }))
9360-
}
9361-
} else {
9362-
// Don't send anything related to interactive signing if `next_funding_txid` is not set.
9363-
(None, None, None)
9364-
};
9365-
93669385
Ok(ReestablishResponses {
93679386
channel_ready,
93689387
channel_ready_order: ChannelReadyOrder::SignaturesFirst,
@@ -9375,6 +9394,12 @@ where
93759394
tx_abort,
93769395
})
93779396
} else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 {
9397+
debug_assert!(commitment_update.is_none());
9398+
9399+
// TODO(splicing): Assert in a test that we don't retransmit tx_signatures instead
9400+
#[cfg(test)]
9401+
assert!(tx_signatures.is_none());
9402+
93789403
if required_revoke.is_some() || self.context.signer_pending_revoke_and_ack {
93799404
log_debug!(logger, "Reconnected channel {} with lost outbound RAA and lost remote commitment tx", &self.context.channel_id());
93809405
} else {
@@ -9390,7 +9415,7 @@ where
93909415
commitment_update: None, raa: None,
93919416
commitment_order: self.context.resend_order.clone(),
93929417
tx_signatures: None,
9393-
tx_abort: None,
9418+
tx_abort,
93949419
})
93959420
} else {
93969421
let commitment_update = if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst
@@ -9416,7 +9441,7 @@ where
94169441
raa, commitment_update,
94179442
commitment_order: self.context.resend_order.clone(),
94189443
tx_signatures: None,
9419-
tx_abort: None,
9444+
tx_abort,
94209445
})
94219446
}
94229447
} else if msg.next_local_commitment_number < next_counterparty_commitment_number {
@@ -11007,15 +11032,29 @@ where
1100711032
}
1100811033

1100911034
#[rustfmt::skip]
11010-
fn maybe_get_next_funding_txid(&self) -> Option<Txid> {
11035+
fn maybe_get_next_funding(&self) -> Option<msgs::NextFunding> {
1101111036
// If we've sent `commtiment_signed` for an interactively constructed transaction
11012-
// during a signing session, but have not received `tx_signatures` we MUST set `next_funding_txid`
11037+
// during a signing session, but have not received `tx_signatures` we MUST set `next_funding`
1101311038
// to the txid of that interactive transaction, else we MUST NOT set it.
1101411039
if self.context.channel_state.is_interactive_signing() {
1101511040
// Since we have a signing_session, this implies we've sent an initial `commitment_signed`...
1101611041
if !self.context.channel_state.is_their_tx_signatures_sent() {
1101711042
// ...but we didn't receive a `tx_signatures` from the counterparty yet.
11018-
self.interactive_tx_signing_session.as_ref().map(|signing_session| signing_session.unsigned_tx().compute_txid())
11043+
self.interactive_tx_signing_session
11044+
.as_ref()
11045+
.map(|signing_session| {
11046+
let mut next_funding = msgs::NextFunding {
11047+
txid: signing_session.unsigned_tx().compute_txid(),
11048+
retransmit_flags: 0,
11049+
};
11050+
11051+
// TODO(splicing): Add comment for spec requirements
11052+
if !signing_session.has_received_commitment_signed() {
11053+
next_funding.retransmit(msgs::NextFundingFlag::CommitmentSigned);
11054+
}
11055+
11056+
next_funding
11057+
})
1101911058
} else {
1102011059
// ...and we received a `tx_signatures` from the counterparty.
1102111060
None
@@ -11092,7 +11131,7 @@ where
1109211131
next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER - self.context.counterparty_next_commitment_transaction_number - 1,
1109311132
your_last_per_commitment_secret: remote_last_secret,
1109411133
my_current_per_commitment_point: dummy_pubkey,
11095-
next_funding_txid: self.maybe_get_next_funding_txid(),
11134+
next_funding: self.maybe_get_next_funding(),
1109611135
my_current_funding_locked: self.maybe_get_my_current_funding_locked(),
1109711136
}
1109811137
}

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11115,7 +11115,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1111511115
next_remote_commitment_number: 0,
1111611116
your_last_per_commitment_secret: [1u8; 32],
1111711117
my_current_per_commitment_point: PublicKey::from_slice(&[2u8; 33]).unwrap(),
11118-
next_funding_txid: None,
11118+
next_funding: None,
1111911119
my_current_funding_locked: None,
1112011120
},
1112111121
});

0 commit comments

Comments
 (0)