Skip to content

Conversation

jkczyz
Copy link
Contributor

@jkczyz jkczyz commented Jun 24, 2025

The splicing spec extends the channel_reestablish message with two more TLVs indicating which funding txid the sender has sent/received either explicitly via splice_locked or implicitly via channel_ready. This allows peers to detect if a splice_locked was lost during disconnection and must be retransmitted.

To this end, the spec updates the channel_reestablish logic to support splicing.

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Jun 24, 2025

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@jkczyz jkczyz assigned jkczyz and unassigned jkczyz Jun 26, 2025
@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch 2 times, most recently from 06c0dfc to f000b76 Compare June 27, 2025 17:04
@jkczyz jkczyz marked this pull request as ready for review June 27, 2025 17:12
@jkczyz
Copy link
Contributor Author

jkczyz commented Jun 27, 2025

@wpaulino Ready for review now.

Copy link

codecov bot commented Jun 27, 2025

Codecov Report

❌ Patch coverage is 61.25000% with 93 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.74%. Comparing base (a9bbb24) to head (a3a3a55).
⚠️ Report is 77 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/channel.rs 52.08% 67 Missing and 2 partials ⚠️
lightning/src/ln/channelmanager.rs 62.50% 8 Missing and 4 partials ⚠️
lightning/src/ln/msgs.rs 80.64% 12 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main    #3886    +/-   ##
========================================
  Coverage   88.74%   88.74%            
========================================
  Files         176      176            
  Lines      128845   129485   +640     
  Branches   128845   129485   +640     
========================================
+ Hits       114340   114912   +572     
- Misses      11912    11962    +50     
- Partials     2593     2611    +18     
Flag Coverage Δ
fuzzing 21.99% <9.04%> (+0.06%) ⬆️
tests 88.57% <61.25%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 3rd Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 4th Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@jkczyz jkczyz self-assigned this Jul 3, 2025
@jkczyz jkczyz moved this to Goal: Merge in Weekly Goals Jul 3, 2025
@ldk-reviews-bot
Copy link

🔔 5th Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@ldk-reviews-bot
Copy link

🔔 6th Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch from f000b76 to e2ea3bf Compare July 7, 2025 21:02
@jkczyz
Copy link
Contributor Author

jkczyz commented Jul 7, 2025

Rebased.

Copy link
Contributor

@wpaulino wpaulino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may need to double check our incoming channel_ready handling to make sure we can handle receiving one long after channel_ready was already exchanged due to the new logic surrounding your_last_funding_locked_txid.

@ldk-reviews-bot
Copy link

👋 The first review has been submitted!

Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer.

@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch from e2ea3bf to 69be701 Compare July 9, 2025 00:17
Copy link
Contributor Author

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may need to double check our incoming channel_ready handling to make sure we can handle receiving one long after channel_ready was already exchanged due to the new logic surrounding your_last_funding_locked_txid.

ACK. Also need to address https://github.com/lightningdevkit/rust-lightning/pull/3736/files#r2133028859.

@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch 2 times, most recently from f7b9785 to b0291f4 Compare July 9, 2025 21:49
@jkczyz
Copy link
Contributor Author

jkczyz commented Jul 9, 2025

Also need to address https://github.com/lightningdevkit/rust-lightning/pull/3736/files#r2133028859.

Latest push adds some commits to address this.

@jkczyz jkczyz requested a review from TheBlueMatt July 9, 2025 22:20
@jkczyz
Copy link
Contributor Author

jkczyz commented Jul 9, 2025

We may need to double check our incoming channel_ready handling to make sure we can handle receiving one long after channel_ready was already exchanged due to the new logic surrounding your_last_funding_locked_txid.

Looks like we have some logic below. I think the catch-all case still holds? We should only receive a channel_ready if we didn't set your_last_funding_locked_txid.

// If we reconnected before sending our `channel_ready` they may still resend theirs.
ChannelState::ChannelReady(_) => check_reconnection = true,
_ => return Err(ChannelError::close("Peer sent a channel_ready at a strange time".to_owned())),
}
if check_reconnection {
// They probably disconnected/reconnected and re-sent the channel_ready, which is
// required, or they're sending a fresh SCID alias.
let expected_point =
if self.context.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 {
// If they haven't ever sent an updated point, the point they send should match
// the current one.
self.context.counterparty_cur_commitment_point
} else if self.context.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 2 {
// If we've advanced the commitment number once, the second commitment point is
// at `counterparty_prev_commitment_point`, which is not yet revoked.
debug_assert!(self.context.counterparty_prev_commitment_point.is_some());
self.context.counterparty_prev_commitment_point
} else {
// If they have sent updated points, channel_ready is always supposed to match
// their "first" point, which we re-derive here.
Some(PublicKey::from_secret_key(&self.context.secp_ctx, &SecretKey::from_slice(
&self.context.commitment_secrets.get_secret(INITIAL_COMMITMENT_NUMBER - 1).expect("We should have all prev secrets available")
).expect("We already advanced, so previous secret keys should have been validated already")))
};
if expected_point != Some(msg.next_per_commitment_point) {
return Err(ChannelError::close("Peer sent a reconnect channel_ready with a different point".to_owned()));
}
return Ok(None);
}

jkczyz added 3 commits August 28, 2025 16:40
The splicing spec extends the channel_reestablish message with two more
TLVs indicating which funding txid the sender has sent/received either
explicitly via splice_locked or implicitly via channel_ready. This
allows peers to detect if a splice_locked was lost during disconnection
and must be retransmitted. This commit updates channel_reestablish with
the TLVs. Subsequent commits will implement the spec requirements.
The previous commit extended the channel_reestablish message with
your_last_funding_locked_txid and my_current_funding_locked_txid for use
as described there. This commit sets those fields to the funding txid
most recently sent/received accordingly.
During channel reestablishment, both commitment_signed and tx_signatures
messages may be retransmitted. However, commitment_signed must come
first, so re-arrange the ordering. This moves tx_abort as well to keep
the interactive tx messages together.
@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch from dc7379d to cce9421 Compare August 28, 2025 23:26
@jkczyz jkczyz requested review from wpaulino and TheBlueMatt August 28, 2025 23:26
@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch from cce9421 to 845360b Compare August 28, 2025 23:37
})
} else if msg.next_local_commitment_number == next_counterparty_commitment_number - 1 {
debug_assert!(commitment_update.is_none());
debug_assert!(tx_signatures.is_none());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is reachable if a counterparty sends a bogus message? If we're just trying to test for it we should #[cfg(test)] it, in general we try to avoid reachable debug_asserts as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, see #3886 (comment)

@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch from 845360b to 27f70b0 Compare August 29, 2025 21:50
@jkczyz jkczyz requested a review from TheBlueMatt August 29, 2025 21:52
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nits and one more issue I think.

@@ -8705,6 +8710,15 @@ where
}
}

// FIXME: Is this correct?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks right to me. Once we fix #4036 basically we can assume we're connected to the peer and in normal operation, which means an interactive signing session or awaiting-ready implies if we're sending a CS its an initial one, and otherwise we want to make sure we get our ready out first. Probably good to leave a comment describing that reasoning.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced the FIXME accordingly.

data:
"No active signing session. The associated funding transaction may have already been broadcast.".as_bytes().to_vec() }))
}
let channel_ready_order = if commitment_update.is_some() || tx_signatures.is_some() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're not sending any signatures does it matter? Can we not just always set SignaturesFirst?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Also, pulled out a new commit introducing ChannelReadyOrder since it's applicable for v2 channel establishment. Addressed this comment there.

shutdown_msg, announcement_sigs,
tx_signatures: None,
tx_signatures,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't send tx_signatures if is_monitor_update_in_progress, right? Probably need to check it in the interactive signing session stuff above, but also here cause we're specifically in a block because of it sometimes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Introduced a separate commit for the interactive signing session case since that preexist this PR. No additional logic is needed here since tx_signatures is initialized there.

@ldk-reviews-bot
Copy link

🔔 1st Reminder

Hey @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch from 27f70b0 to 51406e6 Compare September 2, 2025 23:14
@jkczyz jkczyz requested a review from TheBlueMatt September 2, 2025 23:14
@ldk-reviews-bot
Copy link

🔔 2nd Reminder

Hey @TheBlueMatt @wpaulino! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

jkczyz and others added 9 commits September 3, 2025 11:20
When handling channel_reestablish, the order in which channel_ready is
sent depends on whether or not the initial commitment_signed /
tx_signatures are being retransmitted. When they are, then channel_ready
should come after them. Otherwise, channel_ready should come before any
commitment_signed.
The ChannelMonitor must be successfully persisted before transmitting
any messages.
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 <wilmer@wilmerpaulino.com>
Co-authored-by: Jeffrey Czyz <jkczyz@gmail.com>
During channel_reestablish handling, next_local_commitment_number can
never be zero. Remove the unnecessary check conditioning on next_funding
not being set. Additionally, remove the spec requirement in the comment
that follows since it does not exist.
When a splice transaction is promoted (i.e., when splice_locked has been
exchanged), announcement_signatures must be sent. However, if we try to
send a channel_announcement before they are received, then the
signatures will be incorrect. To avoid this, clear the counterparty's
announcement_signatures upon promoting a FundingScope.
When handling a counterparties channel_reestablish, the spec dictates
that a splice_locked may be implied by my_current_funding_locked.
Compare that against any pending splices and handle an implicit
splice_locked message when applicable.
During channel reestablishment, announcement_signatures may need to be
retransmitted. The splicing spec allows doing so without retransmitting
splice_locked first, which could normally trigger retransmitting
announcement_signatures. Instead, my_current_funding_locked lets the
sender request retransmitting it.
The previous commit allowed requesting retransmission of
announcement_signatures during channel reestablishment. This commit
handles such requests.
@jkczyz jkczyz force-pushed the 2025-06-channel-reestablish branch from 51406e6 to a3a3a55 Compare September 3, 2025 18:20
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

// signatures should be sent before channel_ready.
let channel_ready_order = if self.interactive_tx_signing_session.is_some() {
ChannelReadyOrder::SignaturesFirst
} else if matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need to check this? We keep the signing session around until we receive channel_ready.

@@ -9289,6 +9289,9 @@ where
if session.holder_tx_signatures().is_none() {
log_debug!(logger, "Waiting for funding transaction signatures to be provided");
None
} else if self.context.channel_state.is_monitor_update_in_progress() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be necessary since the signing event isn't given to the user until after the monitor update completes.

ChannelError::Close(
(
message.clone(),
ClosureReason::HolderForceClosed { message, broadcasted_latest_txn: Some(false) },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be ClosureReason::ProcessingError

ChannelError::Close(
(
message.clone(),
ClosureReason::HolderForceClosed { message, broadcasted_latest_txn: Some(false) },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

@wpaulino wpaulino merged commit ecce859 into lightningdevkit:main Sep 5, 2025
24 checks passed
@github-project-automation github-project-automation bot moved this from Goal: Merge to Done in Weekly Goals Sep 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants