Skip to content

Allow specifying a fee rate when splicing - #1159

Merged
tnull merged 3 commits into
lightningdevkit:mainfrom
shubhamkmr04:splice-fee-rate
Oct 15, 2026
Merged

tnull merged 3 commits into
lightningdevkit:mainfrom
shubhamkmr04:splice-fee-rate

Conversation

@shubhamkmr04

@shubhamkmr04 shubhamkmr04 commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Node::splice_in, Node::splice_in_with_all, and Node::splice_out always fund our contribution at the ChannelFunding feerate estimate. On-chain sends already accept an optional fee rate (#434), and #1099 proposes the same for channel opens. This extends that to splices, so applications and node operators can choose how quickly a splice confirms.

We're adding channel splicing to ZEUS's embedded LDK Node (ZeusLN/zeus#4703) and want users to be able to select the fee rate when splicing, as they already can for on-chain sends.

Changes

  • splice_in, splice_in_with_all, and splice_out take an optional fee_rate (FeeRate? in the bindings) as their last argument.
  • If set, it takes the place of the estimate as the feerate of our contribution. Everything derived from that feerate is unchanged: the maximum feerate (1.5x), raising it to the funding template's RBF minimum when contributing to a pending splice, and for splice_in_with_all, the amount spliced in, which is determined at the requested feerate. The docs note when we may pay up to 1.5x the requested feerate.
  • If unset, behavior is unchanged.
  • The contribution is built within the call, so unlike for channel opens the fee rate never has to be stored for a later event.
  • Prefactor: the optional fee rate conversion for the bindings moves from a macro in payment/onchain.rs into a function in ffi/mod.rs, so OnchainPayment and Node share it. Allow specifying a fee rate for channel-open funding transactions #1099 makes the same move; whichever lands second can drop its copy.
  • This changes the signatures of the three methods; a CHANGELOG entry is included.

Testing

  • New splice_channel_with_fee_rate integration test: splices out, then splices in all funds, at ten times the regtest feerate estimate, and checks each splice transaction pays the requested feerate (within 1% to allow for weight estimation). The splice-in would fail to fund its fee if the amount were determined at the estimate instead.
  • The macOS onchain_wallet_full_scan_stop_gap_recovers_far_esplora_and_electrum_funds failure also occurs on main and is unrelated to this change.

This change was developed with the assistance of Claude Code.

@ldk-reviews-bot

ldk-reviews-bot commented Oct 12, 2026 •

Copy link
Copy Markdown

👋 Thanks for assigning @tnull 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
ldk-reviews-bot requested a review from tnull October 12, 2026 16:38

@tnull tnull left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks! Mostly looks good I think, though I'll tag @jkczyz just to check if he sees any reason why specifying a fee rate for splicing would be a bad idea.

We'll want to wait until #1099 landed as it has the same maybe_ move prefactor.

Comment thread src/lib.rs Outdated
pub fn splice_in(
&self, user_channel_id: &UserChannelId, counterparty_node_id: PublicKey,
splice_amount_sats: u64,
splice_amount_sats: u64, fee_rate: Option<FfiFeeRate>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We should probably name this min_fee_rate in the API to make it clear it's just the lower bound.

@shubhamkmr04 shubhamkmr04 Oct 13, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Makes sense, will rename it to min_fee_rate and rebase once #1099 lands.

@tnull
tnull requested a review from jkczyz October 13, 2026 07:50
@shubhamkmr04 shubhamkmr04 mentioned this pull request Oct 14, 2026
10 of 29 tasks
@tnull

tnull commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

This needs a rebase now that #1099 landed.

@shubhamkmr04

Copy link
Copy Markdown
Contributor Author

This needs a rebase now that #1099 landed.

Rebased and renamed the parameter to min_fee_rate. This should be ready for another look.

@jkczyz jkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we do the same for bump_channel_funding_fee? Otherwise, looks good.

Comment thread src/lib.rs Outdated
/// pending splice that requires a higher feerate to be replaced, or when the counterparty
/// initiates a splice concurrently and our contribution is added to theirs.
///
/// The amount spliced in is determined at the feerate used for our contribution.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 The amount is actually determined at min_fee_rate (or the estimate), not at the feerate the contribution ends up using: it's computed before the funding template is obtained, and the contribution may then be built at a pending splice's RBF minimum. Suggest "determined at min_fee_rate, or at the estimate if unset". The underlying mismatch is covered by #1168, which replaces the amount computation with manually selected inputs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done, thanks.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yup see #1166.

@shubhamkmr04

Copy link
Copy Markdown
Contributor Author

Should we do the same for bump_channel_funding_fee? Otherwise, looks good.

Added min_fee_rate to bump_channel_funding_fee in a separate commit, with the test covering a bump at the requested feerate.

@tnull tnull left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This needs another rebase now I'm afraid.

`Node::splice_in`, `Node::splice_in_with_all`, and `Node::splice_out`
always contributed at our `ChannelFunding` feerate estimate, leaving no
way to choose the feerate of a splice, unlike for on-chain sends.

Add an optional `min_fee_rate` to all three. If set, it takes the place
of the estimate as the minimum feerate of our contribution: the existing
logic deriving the maximum feerate and meeting a pending splice's RBF
minimum applies to it unchanged, and `splice_in_with_all` determines
the amount to splice in at it. If unset, behavior is unchanged.

Developed with assistance from Claude Code.
`Node::bump_channel_funding_fee` always started from our
`ChannelFunding` feerate estimate, so the replacement couldn't be bumped
to a chosen feerate, unlike the splice itself.

Add the same optional `min_fee_rate`. If set, it takes the place of the
estimate as the minimum feerate of the replacement: we still pay the
pending splice's RBF minimum if that is higher, up to 1.5 times the
minimum, and fail if replacing it requires more. If unset, behavior is
unchanged.

Developed with assistance from Claude Code.
Splice out, splice in and fee-bump the pending splice-in, and then
splice in all funds, at feerates well above the one we estimate on
regtest, and check that each splice transaction pays the requested
feerate. Replacing the pending splice requires more than we would pay
at our estimate, so the bump only succeeds at the requested feerate. As
the amount to splice in is determined at the requested feerate, the
final splice-in would otherwise fail to fund its fee.

Developed with assistance from Claude Code.

@tnull tnull left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@tnull
tnull merged commit 55ca7a6 into lightningdevkit:main Oct 15, 2026
17 of 25 checks passed
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.

4 participants