Skip to content

[Early Draft][Splicing] Interactive tx negotiation, with a single ChannelContext #3715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from

Conversation

optout21
Copy link
Contributor

@optout21 optout21 commented Apr 8, 2025

This is a continuation of #3444, but without duplication of ChannelContext.
A RefundingV2(RefundingChannel) phase is introduced, where RefundingChannel acts both as funded and pending channel. It has:

  • the already funded channel (FundedChannel)
  • impllements PendingV2ChannelTrait, a new trait also implemented by PendingV2, so it can act as a Pending channel. RefundingChannel also has similar fields to PendingV2Channel, except for context, which is reused from the funded channel.

Related PRs:

Supersedes #3630 .

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Apr 8, 2025

👋 I see @wpaulino was un-assigned.
If you'd like another reviewer assignemnt, please click here.

Comment on lines +1494 to 1519
pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
match &mut self.phase {
ChannelPhase::UnfundedV2(chan) => chan.tx_add_input(msg),
#[cfg(splicing)]
ChannelPhase::RefundingV2(chan) => chan.tx_add_input(msg),
_ => panic!("Got tx_add_input in an invalid phase"),
}
}

pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput) -> InteractiveTxMessageSendResult {
match &mut self.phase {
ChannelPhase::UnfundedV2(chan) => chan.tx_add_output(msg),
#[cfg(splicing)]
ChannelPhase::RefundingV2(chan) => chan.tx_add_output(msg),
_ => panic!("Got tx_add_output in an invalid phase"),
}
}

pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
match &mut self.phase {
ChannelPhase::UnfundedV2(chan) => chan.tx_complete(msg),
#[cfg(splicing)]
ChannelPhase::RefundingV2(chan) => chan.tx_complete(msg),
_ => panic!("Got tx_complete in an invalid phase"),
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we can panic in these?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The aim of this PR is first to get the big picture right, conceptually, and not to work out all the details at once. Of course this has to be refined.

Comment on lines 1289 to 1305
pub fn as_funded(&self) -> Option<&FundedChannel<SP>> {
if let ChannelPhase::Funded(channel) = &self.phase {
Some(channel)
} else {
None
match &self.phase {
ChannelPhase::Funded(channel) => Some(&channel),
#[cfg(splicing)]
ChannelPhase::RefundingV2(channel) => Some(&channel.funded_channel),
_ => None,
}
}

pub fn as_funded_mut(&mut self) -> Option<&mut FundedChannel<SP>> {
if let ChannelPhase::Funded(channel) = &mut self.phase {
Some(channel)
} else {
None
match &mut self.phase {
ChannelPhase::Funded(channel) => Some(channel),
#[cfg(splicing)]
ChannelPhase::RefundingV2(channel) => Some(&mut channel.funded_channel),
_ => None,
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm... can we do this? For instance, internal_update_add_htlc calls as_funded_mut. Presumably, for the RefundingV2 case, the channel would be in quiescence, so the check in internal_update_add_htlc would prevent this from being an issue. So maybe this is desirable if we need to cover both cases elsewhere. IIUC, we would be in quiescence if and only if we are in ChannelPhase::RefundingV2. cc: @wpaulino

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Touchy question. If the phase when the new funding has been negotiated but not yet locked is not represented by RefundingV2, then you are probably right.
However, currently as_funded is used in many cases, such as listing channels or force close.

let (pending_splice_post, post_funding, dual_funding_context, unfunded_context) =
prev_chan.splice_init(msg, our_funding_contribution)?;

let _res = self.phase_from_funded_to_splice(post_funding, dual_funding_context, unfunded_context, pending_splice_post)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

We should just inline phase_from_funded_to_splice in the two places it is used rather than introducing unreachables. There isn't much happening in there to justify refactoring it into a method, IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I consider these concerns low-level code improvement, not in focus in this PR. Being in separate functions increases visibility. Should be addressed in non-draft PR.

// let (signing_session, holder_commitment_point, commitment_signed, event) =
let (commitment_signed, event) =
chan.funding_tx_constructed(signing_session, &&logger)?;
let _res = self.phase_from_splice_to_funded()?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why swallow the error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No error is swallowed here, ? is used. the return value is nothing (()). Or do you mean something else?

let (pending_splice_post, post_funding, dual_funding_context, unfunded_context, our_funding_contribution) =
prev_chan.splice_ack(msg)?;

let _res = self.phase_from_funded_to_splice(post_funding, dual_funding_context, unfunded_context, pending_splice_post)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Similarly, why swallow the error here and in splice_init?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No error is swallowed here, ? is used. the return value is nothing (()). Or do you mean something else?

@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 requested a review from wpaulino April 8, 2025 23:18
@wpaulino wpaulino removed their request for review April 10, 2025 00:42
@optout21
Copy link
Contributor Author

Continued in #3736, closing this one

@optout21 optout21 closed this Apr 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants