Skip to content

Conversation

@TheBlueMatt
Copy link
Collaborator

In some uses of LDK we need the ability to send HTLCs for only a
portion of some larger MPP payment. This allows payers to make
single payments which spend funds from multiple wallets, which may
be important for ecash wallets holding funds in multiple mints or
graduated wallets which hold funds across a trusted wallet and a
self-custodial wallet.

This adds support for it both in the more manual send_payment flow as well as pay_for_bolt11_invoice. Adding support for BOLT 12 is left for a followup. cc @benthecarman

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Feb 2, 2026

I've assigned @wpaulino 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.

@TheBlueMatt TheBlueMatt force-pushed the 2026-02-partial-mpp-payments branch 2 times, most recently from a4b00d4 to e8d40e1 Compare February 3, 2026 02:39
@codecov
Copy link

codecov bot commented Feb 3, 2026

Codecov Report

❌ Patch coverage is 84.71074% with 37 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.00%. Comparing base (4800a47) to head (b6b973f).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/outbound_payment.rs 77.61% 28 Missing and 2 partials ⚠️
lightning/src/ln/channelmanager.rs 90.00% 2 Missing and 2 partials ⚠️
lightning/src/ln/onion_utils.rs 94.33% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4373      +/-   ##
==========================================
- Coverage   86.01%   86.00%   -0.02%     
==========================================
  Files         156      156              
  Lines      102781   102886     +105     
  Branches   102781   102886     +105     
==========================================
+ Hits        88409    88485      +76     
- Misses      11864    11887      +23     
- Partials     2508     2514       +6     
Flag Coverage Δ
tests 86.00% <84.71%> (-0.02%) ⬇️

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.

At various points we've been stuck in our TLV read/write variants
but just want to break out and write some damn code to initialize
a field and some more code to decide what to write for a TLV.

We added the write-side part of this with the `legacy` TLV
read/write variant, but its useful to also be able to specify a
function which is called on the read side.

Here we add a `custom` TLV read/write variant which calls a method
both on read and write to either decide what to write or to map a
read value (if any) to the final field.
When `OutboundPayments` calls the provided `Router` to fetch a
`Route` it passes a `RouteParameters` with a specific max-fee. Here
we validate that the `Route` returned sticks to the limits
provided, and also that it meets the MPP rules of not having any
single MPP part which can be removed while still meeting the
desired payment amount.
In some uses of LDK we need the ability to send HTLCs for only a
portion of some larger MPP payment. This allows payers to make
single payments which spend funds from multiple wallets, which may
be important for ecash wallets holding funds in multiple mints or
graduated wallets which hold funds across a trusted wallet and a
self-custodial wallet.

In order to allow for this, we need to separate the concept of the
payment amount from the onion MPP amount. Here we start this
process by adding a `total_mpp_amount_msat` field to
`RecipientOnionFields` (which is the appropriate place for a field
describing something in the recipient onion).

We currently always assert that it is equal to the existing fields,
but will relax this in the coming commit(s).

We also start including a payment preimage on probe attempts,
which appears to have been the intent of the code, but which did
not work correctly.

The bulk of the test updates were done by Claude.
@TheBlueMatt TheBlueMatt force-pushed the 2026-02-partial-mpp-payments branch 2 times, most recently from ff2b608 to 93228cf Compare February 3, 2026 14:08
In some uses of LDK we need the ability to send HTLCs for only a
portion of some larger MPP payment. This allows payers to make
single payments which spend funds from multiple wallets, which may
be important for ecash wallets holding funds in multiple mints or
graduated wallets which hold funds across a trusted wallet and a
self-custodial wallet.

In the previous commit we added a new field to
`RecipientOnionFields` to describe the total value of an MPP
payment. Here we start using this field when building onions,
dropping existing arguments to onion-building methods.
In some uses of LDK we need the ability to send HTLCs for only a
portion of some larger MPP payment. This allows payers to make
single payments which spend funds from multiple wallets, which may
be important for ecash wallets holding funds in multiple mints or
graduated wallets which hold funds across a trusted wallet and a
self-custodial wallet.

In the previous commits we moved the total-MPP-value we set in
onions from being manually passed through onion-building to passing
it via `RecipientOnionFields`. This introduced a subtle bug, though
 - payments which are retried will get a fresh
`RecipientOnionFields` built from the data in
`PendingOutboundPayment::Retryable`, losing any custom
total-MPP-value settings and causing retries to fail.

Here we fix this by storing the total-MPP-value directly in
`PendingOutboundPayment::Retryable`.
In some uses of LDK we need the ability to send HTLCs for only a
portion of some larger MPP payment. This allows payers to make
single payments which spend funds from multiple wallets, which may
be important for ecash wallets holding funds in multiple mints or
graduated wallets which hold funds across a trusted wallet and a
self-custodial wallet.

In the previous few commits we added support for making these
kinds of payments when using the payment methods which explicitly
accepted a `RecipientOnionFields`. Here we also add support for
such payments made via the `pay_for_bolt11_invoice` method,
utilizing the new `OptionalBolt11PaymentParams` to hide the
parameter from most calls.

Test mostly by Claude
@TheBlueMatt TheBlueMatt force-pushed the 2026-02-partial-mpp-payments branch from 93228cf to b6b973f Compare February 3, 2026 14:12
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.

2 participants