Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3179,6 +3179,11 @@ pub enum RecentPaymentDetails {
/// Total amount (in msat, excluding fees) across all paths for this payment,
/// not just the amount currently inflight.
total_msat: u64,
/// Amount (in msat) currently locked in HTLCs.
///
/// `total_msat - inflight_msat` gives the amount waiting to be retried
/// Reserve both from spendable balance.
inflight_msat: u64,
},
/// When a pending payment is fulfilled, we continue tracking it until all pending HTLCs have
/// been resolved. Upon receiving [`Event::PaymentSent`], we delay for a few minutes before the
Expand Down Expand Up @@ -3884,11 +3889,12 @@ where
PendingOutboundPayment::StaticInvoiceReceived { .. } => {
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
},
PendingOutboundPayment::Retryable { payment_hash, total_msat, .. } => {
PendingOutboundPayment::Retryable { payment_hash, total_msat, pending_amt_msat, .. } => {
Some(RecentPaymentDetails::Pending {
payment_id: *payment_id,
payment_hash: *payment_hash,
total_msat: *total_msat,
inflight_msat: *pending_amt_msat,
})
},
PendingOutboundPayment::Abandoned { payment_hash, .. } => {
Expand Down
45 changes: 43 additions & 2 deletions lightning/src/ln/payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2098,8 +2098,16 @@ fn test_trivial_inflight_htlc_tracking() {
}
let pending_payments = nodes[0].node.list_recent_payments();
assert_eq!(pending_payments.len(), 1);
let details = RecentPaymentDetails::Pending { payment_id, payment_hash, total_msat: 500000 };
assert_eq!(pending_payments[0], details);
match &pending_payments[0] {
RecentPaymentDetails::Pending {
payment_id: pid, payment_hash: ph, total_msat: tm, ..
} => {
assert_eq!(*pid, payment_id);
assert_eq!(*ph, payment_hash);
assert_eq!(*tm, 500000);
},
_ => panic!("Expected Pending payment details"),
}

// Now, let's claim the payment. This should result in the used liquidity to return `None`.
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
Expand Down Expand Up @@ -2141,6 +2149,39 @@ fn test_trivial_inflight_htlc_tracking() {
assert_eq!(pending_payments.len(), 0);
}

#[test]
fn test_pending_payment_tracking() {
let chanmon_cfgs = create_chanmon_cfgs(3);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);

create_announced_chan_between_nodes(&nodes, 0, 1);
create_announced_chan_between_nodes(&nodes, 1, 2);

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

let pending_payments = nodes[0].node.list_recent_payments();
assert_eq!(pending_payments.len(), 1);
match &pending_payments[0] {
RecentPaymentDetails::Pending { payment_id: pid, total_msat, inflight_msat, .. } => {
assert_eq!(*pid, payment_id);
assert_eq!(*total_msat, payment_amt);
assert_eq!(*inflight_msat, payment_amt);
},
_ => panic!("Expected Pending payment details"),
}

claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);

for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS {
nodes[0].node.timer_tick_occurred();
}
assert!(nodes[0].node.list_recent_payments().is_empty());
}

#[test]
fn test_holding_cell_inflight_htlcs() {
let chanmon_cfgs = create_chanmon_cfgs(2);
Expand Down
6 changes: 6 additions & 0 deletions pending_changelog/3374-pending-retry-amount.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## API Updates

* `RecentPaymentDetails::Pending` now includes `inflight_msat`, tracking the
amount currently locked in HTLCs. The difference `total_msat - inflight_msat`
is the amount waiting to retry. Reserve both from spendable balance to avoid
balance flicker during payment retries (#3374).