Skip to content

Conversation

@jkczyz
Copy link
Contributor

@jkczyz jkczyz commented Dec 18, 2025

Rather than requiring the user to pass FundingTxInputs when initiating a splice, generate a FundingNeeded event once the channel has become quiescent. This simplifies error handling and UTXO / change address clean-up by consolidating it in SpliceFailed event handling.

Later, this event will be used for opportunistic contributions (i.e., when the counterparty wins quiescence or initiates), dual-funding, and RBF.

Based on #4261.

This is still fairly rough. It does not yet include any code for creating a FundingNegotiationContext from a FundingContribution. The former may need to a dedicated struct instead so that any data needed from ChannelManager or ChannelContext can be produced internally. Alternatively, that data could be included in FundingContribution, but it would need to be serializable.

When adding support for mixed splice-in and splice-out, the contribution
amount will need to be computed based on the splice-in and splice-out
values. Rather than add a third variant to SpliceContribution, which
could have an invalid contribution amount, use a more general struct
that can represent splice-in, splice-out, and mixed. Constructors are
provided for the typical splice-in and splice-out case whereas support
for the mixed case will be added in an independent change.
Some splicing use cases require to simultaneously splice in and out in
the same splice transaction. Add support for such splices using the
funding inputs to pay the appropriate fees just like the splice-in case,
opposed to using the channel value like the splice-out case. This
requires using the contributed input value when checking if the inputs
are sufficient to cover fees, not the net contributed value. The latter
may be negative in the net splice-out case.
@ldk-reviews-bot
Copy link

👋 Hi! I see this is a draft PR.
I'll wait to assign reviewers until you mark it as ready for review.
Just convert it out of draft status when you're ready for review!

@jkczyz jkczyz self-assigned this Dec 18, 2025
Rather than requiring the user to pass FundingTxInputs when initiating a
splice, generate a FundingNeeded event once the channel has become
quiescent. This simplifies error handling and UTXO / change address
clean-up by consolidating it in SpliceFailed event handling.

Later, this event will be used for opportunistic contributions (i.e.,
when the counterparty wins quiescence or initiates), dual-funding, and
RBF.
@jkczyz jkczyz force-pushed the 2025-12-new-splice-api branch from f5933e5 to 854e9ca Compare January 12, 2026 17:47
@jkczyz
Copy link
Contributor Author

jkczyz commented Jan 12, 2026

@TheBlueMatt @wpaulino Looking for some high-level feedback on the API introduced in the last commit. In summary:

  • User passes SpliceContribution -- which no longer contains any FundingTxInputs -- to ChannelManager::splice_channel
  • Upon quiescence LDK generates a FundingNeeded event which contains a FundingTemplate
  • User calls FundingTemplate::build or FundingTemplate::build_sync with a WalletSource or WalletSourceSync, respectively, to produce a FundingContribution
  • User passes FundingContribution -- which contains the FundingTxInputs -- to ChannelManager::funding_contributed
  • LDK validates that the FundingContribution can pay for inputs / outputs, causing LDK to either send splice_init or produce a SpliceFailed event.

The same mechanism can be used later for contributing inputs for counterparty-initiated splices or v2 channel opens since FundingTemplate and FundingContribution contains the context.

Test code still needs to be fixed up, and change_script generation will follow in another commit.

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.

The API design LGTM, though there's one issue with WalletSource. One thing users need to keep in mind now is that from the moment they receive FundingNeeded, they need to act quickly to ensure the counterparty doesn't disconnect due to quiescence taking too long.

fn list_confirmed_utxos(&self) -> Result<Vec<Utxo>, ()>;

///
fn select_confirmed_utxos(
Copy link
Contributor

Choose a reason for hiding this comment

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

Adding this here now requires implementers to satisfy this method when, in the context of anchor channels, WalletSource is only intended to be used such that we perform coin selection on behalf of the user. Ideally, we also give users the option between choosing WalletSource/CoinSelectionSource when funding channels.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Right, I guess I'm a bit confused why we can't use select_confirmed_utxos as-is? Indeed the claim_id is annoying, but we can make that either an enum across a ClaimId and some unit value describing a splice or just make it an Option. Aside from that it seems to be basically what we want.

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.

Aside from the above which-interface question I think the API is good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants