Skip to content

Conversation

@shruti2522
Copy link

fix #3374

adds inflight_msat to RecentPaymentDetails::Pending to expose the amount currently locked in HTLCs. this allows wallets to avoid balance flicker during payment retries by distinguishing between inflight funds and funds waiting to retry

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Jan 31, 2026

👋 Hi! This PR is now in draft status.
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!

@codecov
Copy link

codecov bot commented Jan 31, 2026

Codecov Report

❌ Patch coverage is 89.35185% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.01%. Comparing base (e9ce486) to head (b980cb6).
⚠️ Report is 165 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/channelmanager.rs 89.04% 22 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4366      +/-   ##
==========================================
- Coverage   86.54%   86.01%   -0.54%     
==========================================
  Files         158      156       -2     
  Lines      103166   103582     +416     
  Branches   103166   103582     +416     
==========================================
- Hits        89287    89096     -191     
- Misses      11456    11972     +516     
- Partials     2423     2514      +91     
Flag Coverage Δ
fuzzing ?
tests 86.01% <89.35%> (+0.17%) ⬆️

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

🔔 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.

@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.

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.

Please include the description of the changes in the commit message as well

/// Amount (in msat) currently locked in HTLCs.
///
/// `total_msat - inflight_msat` gives the amount waiting to be retried
/// Reserve both from spendable balance.
Copy link
Contributor

Choose a reason for hiding this comment

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

This line is not very clear to me, can you rephrase it?


let payment_amt = 100_000;
let (payment_preimage, _payment_hash, _, payment_id) =
route_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_amt);
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's route another payment but still only claim one so we can assert the in-flight amount of the remaining payment

@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.

@ldk-reviews-bot
Copy link

✅ Added second reviewer: @joostjager

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.

I'm not convinced this API is quite sufficient for what we need. We really want a single, consistent view of users' current balance. The problem with fetching information from two separate sources (here ChannelMonitor(s) + ChannelManager) is that we end up racing retries across them - calling them both in succession may double- or under-count pending payments. I'm not quite sure with the right answer is, maybe we need to list HTLCs in pending payments and have some utility that removes duplicated entries, or maybe we need to include total payment amounts in the ChannelMonitor balance list and have some logic to compare the pending payments list to remove payments that have partially MPP-timed-out.

@TheBlueMatt TheBlueMatt removed the request for review from joostjager February 7, 2026 16:25
@TheBlueMatt
Copy link
Collaborator

We'll have to explore it a bit, but I think the second option is compelling - we already have payment info in the monitors (I hope enough) so communicating that back may suffice. The only case we'd maybe want to worry about is whether we over-state the in-flight amount for payments where we've given up retrying but there are stuck MPP parts. In that case we'll need the pending payment info like you exposed here, but may need more information about the retry state.

@shruti2522
Copy link
Author

We'll have to explore it a bit, but I think the second option is compelling - we already have payment info in the monitors (I hope enough) so communicating that back may suffice. The only case we'd maybe want to worry about is whether we over-state the in-flight amount for payments where we've given up retrying but there are stuck MPP parts. In that case we'll need the pending payment info like you exposed here, but may need more information about the retry state.

Got it, will look into this and follow up

@shruti2522 shruti2522 force-pushed the feat/pending-balance branch 3 times, most recently from ca6d216 to 0934df6 Compare February 11, 2026 14:27
@shruti2522
Copy link
Author

shruti2522 commented Feb 11, 2026

I went with the second option, added payment info to the monitors, using them as the source of truth for in-flight amounts. Added payment_id to Balance::MaybeTimeoutClaimableHTLC so the monitors can report which payment each HTLC belongs to.

For the stuck MPP parts concern, I added is_retryable to the pending payment info to track retry state. That way we can tell the difference between payment is actively retrying vs we've given up but HTLCs are still stuck

Added reconcile_inflight_payments() utility that takes both sources and gives back a consistent view, it uses the monitor amounts (what's actually in channels) but pulls the retry status from ChannelManager. Returns a simple map of PaymentId -> (amount, is_retryable). This should eliminate the double-counting race since we're not trying to add up amounts from two separate calls.

/// returns msats.
///
/// [`reconcile_inflight_payments`]: crate::ln::channelmanager::reconcile_inflight_payments
pub fn aggregate_outbound_htlcs_by_payment(balances: &[Balance]) -> HashMap<PaymentId, u64> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a weird public API?

@@ -0,0 +1,27 @@
## API Updates
Copy link
Collaborator

Choose a reason for hiding this comment

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

No, please keep pending changelog entries condensed. Max a line or two wrapped at 80 chars. There should almost certainly only be one or two entries, each one or two sentences for a PR like this.

/// ```
pub fn reconcile_inflight_payments(
balances: &[Balance], recent_payments: &[RecentPaymentDetails],
) -> HashMap<PaymentId, (u64, bool)> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you feel like this is the right API? I really want to answer the question "what is my balance" not "what is the amount being sent for pending payments".

@shruti2522 shruti2522 force-pushed the feat/pending-balance branch 2 times, most recently from 291e7aa to 28c93e3 Compare February 12, 2026 03:45
Adds `get_spendable_balance_msat()` and `get_balance_breakdown()` to provide accurate balance information during payment retries.
The new `BalanceDetails` struct separates spendable funds from pending HTLCs and retry reserves, preventing wallets from showing incorrect balances when payments are being retried.
@shruti2522 shruti2522 marked this pull request as draft February 12, 2026 04:00
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.

Method to fetch pending-to-be-sent-but-not-in-HTLCs balance

4 participants