Skip to content

Commit 77747c0

Browse files
jkczyzwpaulino
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 73639c3 commit 77747c0

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
@@ -9121,9 +9121,9 @@ where
91219121
}
91229122

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

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

9177+
let mut commitment_update = None;
9178+
let mut tx_signatures = None;
9179+
let mut tx_abort = None;
9180+
9181+
// if next_funding is set:
9182+
if let Some(next_funding) = &msg.next_funding {
9183+
// - if `next_funding` matches the latest interactive funding transaction
9184+
// or the current channel funding transaction:
9185+
if let Some(session) = &self.interactive_tx_signing_session {
9186+
let our_next_funding_txid = session.unsigned_tx().compute_txid();
9187+
if our_next_funding_txid != next_funding.txid {
9188+
return Err(ChannelError::close(format!(
9189+
"Unexpected next_funding txid: {}; expected: {}",
9190+
next_funding.txid, our_next_funding_txid,
9191+
)));
9192+
}
9193+
9194+
if !session.has_received_commitment_signed() {
9195+
self.context.expecting_peer_commitment_signed = true;
9196+
}
9197+
9198+
// TODO(splicing): Add comment for spec requirements
9199+
if next_funding.should_retransmit(msgs::NextFundingFlag::CommitmentSigned) {
9200+
#[cfg(splicing)]
9201+
let funding = self
9202+
.pending_splice
9203+
.as_ref()
9204+
.and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
9205+
.and_then(|funding_negotiation| {
9206+
if let FundingNegotiation::AwaitingSignatures(funding) = &funding_negotiation {
9207+
Some(funding)
9208+
} else {
9209+
None
9210+
}
9211+
})
9212+
.or_else(|| Some(&self.funding))
9213+
.filter(|funding| funding.get_funding_txid() == Some(next_funding.txid))
9214+
.ok_or_else(|| {
9215+
let message = "Failed to find funding for new commitment_signed".to_owned();
9216+
ChannelError::Close(
9217+
(
9218+
message.clone(),
9219+
ClosureReason::HolderForceClosed { message, broadcasted_latest_txn: Some(false) },
9220+
)
9221+
)
9222+
})?;
9223+
#[cfg(not(splicing))]
9224+
let funding = &self.funding;
9225+
9226+
let commitment_signed = self.context.get_initial_commitment_signed_v2(&funding, logger)
9227+
// TODO(splicing): Support async signing
9228+
.ok_or_else(|| {
9229+
let message = "Failed to get signatures for new commitment_signed".to_owned();
9230+
ChannelError::Close(
9231+
(
9232+
message.clone(),
9233+
ClosureReason::HolderForceClosed { message, broadcasted_latest_txn: Some(false) },
9234+
)
9235+
)
9236+
})?;
9237+
9238+
commitment_update = Some(msgs::CommitmentUpdate {
9239+
commitment_signed: vec![commitment_signed],
9240+
update_add_htlcs: vec![],
9241+
update_fulfill_htlcs: vec![],
9242+
update_fail_htlcs: vec![],
9243+
update_fail_malformed_htlcs: vec![],
9244+
update_fee: None,
9245+
});
9246+
}
9247+
9248+
// - if it has already received `commitment_signed` and it should sign first
9249+
// - MUST send its `tx_signatures` for that funding transaction.
9250+
//
9251+
// - if it has already received `tx_signatures` for that funding transaction:
9252+
// - MUST send its `tx_signatures` for that funding transaction.
9253+
if (session.has_received_commitment_signed() && session.holder_sends_tx_signatures_first())
9254+
|| self.context.channel_state.is_their_tx_signatures_sent()
9255+
{
9256+
// If `holder_tx_signatures` is `None` here, the `tx_signatures` message will be sent
9257+
// when the holder provides their witnesses as this will queue a `tx_signatures` if the
9258+
// holder must send one.
9259+
if session.holder_tx_signatures().is_none() {
9260+
log_debug!(logger, "Waiting for funding transaction signatures to be provided");
9261+
} else if self.context.channel_state.is_monitor_update_in_progress() {
9262+
log_debug!(logger, "Waiting for monitor update before providing funding transaction signatures");
9263+
} else {
9264+
tx_signatures = session.holder_tx_signatures().clone();
9265+
}
9266+
}
9267+
} else {
9268+
// We'll just send a `tx_abort` here if we don't have a signing session for this channel
9269+
// on reestablish and tell our peer to just forget about it.
9270+
// Our peer is doing something strange, but it doesn't warrant closing the channel.
9271+
tx_abort = Some(msgs::TxAbort {
9272+
channel_id: self.context.channel_id(),
9273+
data:
9274+
"No active signing session. The associated funding transaction may have already been broadcast.".as_bytes().to_vec() });
9275+
}
9276+
}
9277+
91779278
if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) {
91789279
// If we're waiting on a monitor update, we shouldn't re-send any channel_ready's.
91799280
if !self.context.channel_state.is_our_channel_ready() ||
91809281
self.context.channel_state.is_monitor_update_in_progress() {
91819282
if msg.next_remote_commitment_number != 0 {
91829283
return Err(ChannelError::close("Peer claimed they saw a revoke_and_ack but we haven't sent channel_ready yet".to_owned()));
91839284
}
9184-
// Short circuit the whole handler as there is nothing we can resend them
9285+
91859286
return Ok(ReestablishResponses {
91869287
channel_ready: None,
9187-
channel_ready_order: ChannelReadyOrder::ChannelReadyFirst,
9188-
raa: None, commitment_update: None,
9189-
commitment_order: RAACommitmentOrder::CommitmentFirst,
9288+
channel_ready_order: ChannelReadyOrder::SignaturesFirst,
9289+
raa: None, commitment_update,
9290+
commitment_order: self.context.resend_order.clone(),
91909291
shutdown_msg, announcement_sigs,
9191-
tx_signatures: None,
9292+
tx_signatures,
91929293
tx_abort: None,
91939294
});
91949295
}
91959296

91969297
// We have OurChannelReady set!
91979298
return Ok(ReestablishResponses {
91989299
channel_ready: self.get_channel_ready(logger),
9199-
channel_ready_order: ChannelReadyOrder::ChannelReadyFirst,
9200-
raa: None, commitment_update: None,
9201-
commitment_order: RAACommitmentOrder::CommitmentFirst,
9300+
channel_ready_order: ChannelReadyOrder::SignaturesFirst,
9301+
raa: None, commitment_update,
9302+
commitment_order: self.context.resend_order.clone(),
92029303
shutdown_msg, announcement_sigs,
9203-
tx_signatures: None,
9204-
tx_abort: None,
9304+
tx_signatures,
9305+
tx_abort,
92059306
});
92069307
}
92079308

@@ -9244,88 +9345,6 @@ where
92449345
log_debug!(logger, "Reconnected channel {} with no loss", &self.context.channel_id());
92459346
}
92469347

9247-
// if next_funding_txid is set:
9248-
let (commitment_update, tx_signatures, tx_abort) = if let Some(next_funding_txid) = msg.next_funding_txid {
9249-
if let Some(session) = &self.interactive_tx_signing_session {
9250-
// if next_funding_txid matches the latest interactive funding transaction:
9251-
let our_next_funding_txid = session.unsigned_tx().compute_txid();
9252-
if our_next_funding_txid == next_funding_txid {
9253-
debug_assert_eq!(session.unsigned_tx().compute_txid(), self.maybe_get_next_funding_txid().unwrap());
9254-
9255-
let commitment_update = if !self.context.channel_state.is_their_tx_signatures_sent() && msg.next_local_commitment_number == 0 {
9256-
// if it has not received tx_signatures for that funding transaction AND
9257-
// if next_commitment_number is zero:
9258-
// MUST retransmit its commitment_signed for that funding transaction.
9259-
let commitment_signed = self.context.get_initial_commitment_signed_v2(&self.funding, logger)
9260-
// TODO(splicing): Support async signing
9261-
.ok_or_else(|| {
9262-
let message = "Failed to get signatures for new commitment_signed".to_owned();
9263-
ChannelError::Close(
9264-
(
9265-
message.clone(),
9266-
ClosureReason::HolderForceClosed { message, broadcasted_latest_txn: Some(false) },
9267-
)
9268-
)})?;
9269-
Some(msgs::CommitmentUpdate {
9270-
commitment_signed: vec![commitment_signed],
9271-
update_add_htlcs: vec![],
9272-
update_fulfill_htlcs: vec![],
9273-
update_fail_htlcs: vec![],
9274-
update_fail_malformed_htlcs: vec![],
9275-
update_fee: None,
9276-
})
9277-
} else { None };
9278-
let tx_signatures = if (
9279-
// if it has not received tx_signatures for that funding transaction AND
9280-
// if it has already received commitment_signed AND it should sign first, as specified in the tx_signatures requirements:
9281-
// MUST send its tx_signatures for that funding transaction.
9282-
!self.context.channel_state.is_their_tx_signatures_sent() && session.has_received_commitment_signed() && session.holder_sends_tx_signatures_first()
9283-
// else if it has already received tx_signatures for that funding transaction:
9284-
// MUST send its tx_signatures for that funding transaction.
9285-
) || self.context.channel_state.is_their_tx_signatures_sent() {
9286-
// If `holder_tx_signatures` is `None` here, the `tx_signatures` message will be sent
9287-
// when the holder provides their witnesses as this will queue a `tx_signatures` if the
9288-
// holder must send one.
9289-
if session.holder_tx_signatures().is_none() {
9290-
log_debug!(logger, "Waiting for funding transaction signatures to be provided");
9291-
None
9292-
} else if self.context.channel_state.is_monitor_update_in_progress() {
9293-
log_debug!(logger, "Waiting for monitor update before providing funding transaction signatures");
9294-
None
9295-
} else {
9296-
session.holder_tx_signatures().clone()
9297-
}
9298-
} else {
9299-
None
9300-
};
9301-
if !session.has_received_commitment_signed() {
9302-
self.context.expecting_peer_commitment_signed = true;
9303-
}
9304-
(commitment_update, tx_signatures, None)
9305-
} else {
9306-
// The `next_funding_txid` does not match the latest interactive funding transaction so we
9307-
// MUST send tx_abort to let the remote know that they can forget this funding transaction.
9308-
(None, None, Some(msgs::TxAbort {
9309-
channel_id: self.context.channel_id(),
9310-
data: format!(
9311-
"next_funding_txid {} does match our latest interactive funding txid {}",
9312-
next_funding_txid, our_next_funding_txid,
9313-
).into_bytes() }))
9314-
}
9315-
} else {
9316-
// We'll just send a `tx_abort` here if we don't have a signing session for this channel
9317-
// on reestablish and tell our peer to just forget about it.
9318-
// Our peer is doing something strange, but it doesn't warrant closing the channel.
9319-
(None, None, Some(msgs::TxAbort {
9320-
channel_id: self.context.channel_id(),
9321-
data:
9322-
"No active signing session. The associated funding transaction may have already been broadcast.".as_bytes().to_vec() }))
9323-
}
9324-
} else {
9325-
// Don't send anything related to interactive signing if `next_funding_txid` is not set.
9326-
(None, None, None)
9327-
};
9328-
93299348
Ok(ReestablishResponses {
93309349
channel_ready,
93319350
channel_ready_order: ChannelReadyOrder::SignaturesFirst,
@@ -9338,6 +9357,12 @@ where
93389357
tx_abort,
93399358
})
93409359
} else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 {
9360+
debug_assert!(commitment_update.is_none());
9361+
9362+
// TODO(splicing): Assert in a test that we don't retransmit tx_signatures instead
9363+
#[cfg(test)]
9364+
assert!(tx_signatures.is_none());
9365+
93419366
if required_revoke.is_some() || self.context.signer_pending_revoke_and_ack {
93429367
log_debug!(logger, "Reconnected channel {} with lost outbound RAA and lost remote commitment tx", &self.context.channel_id());
93439368
} else {
@@ -9353,7 +9378,7 @@ where
93539378
commitment_update: None, raa: None,
93549379
commitment_order: self.context.resend_order.clone(),
93559380
tx_signatures: None,
9356-
tx_abort: None,
9381+
tx_abort,
93579382
})
93589383
} else {
93599384
let commitment_update = if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst
@@ -9379,7 +9404,7 @@ where
93799404
raa, commitment_update,
93809405
commitment_order: self.context.resend_order.clone(),
93819406
tx_signatures: None,
9382-
tx_abort: None,
9407+
tx_abort,
93839408
})
93849409
}
93859410
} else if msg.next_local_commitment_number < next_counterparty_commitment_number {
@@ -10971,15 +10996,29 @@ where
1097110996
}
1097210997

1097310998
#[rustfmt::skip]
10974-
fn maybe_get_next_funding_txid(&self) -> Option<Txid> {
10999+
fn maybe_get_next_funding(&self) -> Option<msgs::NextFunding> {
1097511000
// If we've sent `commtiment_signed` for an interactively constructed transaction
10976-
// during a signing session, but have not received `tx_signatures` we MUST set `next_funding_txid`
11001+
// during a signing session, but have not received `tx_signatures` we MUST set `next_funding`
1097711002
// to the txid of that interactive transaction, else we MUST NOT set it.
1097811003
if self.context.channel_state.is_interactive_signing() {
1097911004
// Since we have a signing_session, this implies we've sent an initial `commitment_signed`...
1098011005
if !self.context.channel_state.is_their_tx_signatures_sent() {
1098111006
// ...but we didn't receive a `tx_signatures` from the counterparty yet.
10982-
self.interactive_tx_signing_session.as_ref().map(|signing_session| signing_session.unsigned_tx().compute_txid())
11007+
self.interactive_tx_signing_session
11008+
.as_ref()
11009+
.map(|signing_session| {
11010+
let mut next_funding = msgs::NextFunding {
11011+
txid: signing_session.unsigned_tx().compute_txid(),
11012+
retransmit_flags: 0,
11013+
};
11014+
11015+
// TODO(splicing): Add comment for spec requirements
11016+
if !signing_session.has_received_commitment_signed() {
11017+
next_funding.retransmit(msgs::NextFundingFlag::CommitmentSigned);
11018+
}
11019+
11020+
next_funding
11021+
})
1098311022
} else {
1098411023
// ...and we received a `tx_signatures` from the counterparty.
1098511024
None
@@ -11056,7 +11095,7 @@ where
1105611095
next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER - self.context.counterparty_next_commitment_transaction_number - 1,
1105711096
your_last_per_commitment_secret: remote_last_secret,
1105811097
my_current_per_commitment_point: dummy_pubkey,
11059-
next_funding_txid: self.maybe_get_next_funding_txid(),
11098+
next_funding: self.maybe_get_next_funding(),
1106011099
my_current_funding_locked: self.maybe_get_my_current_funding_locked(),
1106111100
}
1106211101
}

lightning/src/ln/channelmanager.rs

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

0 commit comments

Comments
 (0)