Skip to content

Commit 1d13f39

Browse files
authored
Merge pull request #4651 from valentinewallace/2026-06-paymentsent-unwrap
Fix missing `PaymentSent::fee_paid_msat`
2 parents 4cd9241 + 3e9e6e9 commit 1d13f39

4 files changed

Lines changed: 40 additions & 2 deletions

File tree

lightning/src/events/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,8 @@ pub enum Event {
12011201
/// If the recipient or an intermediate node misbehaves and gives us free money, this may
12021202
/// overstate the amount paid, though this is unlikely.
12031203
///
1204-
/// This is only `None` for payments initiated on LDK versions prior to 0.0.103.
1204+
/// This is only `None` for payments abandoned but ultimately claimed when using LDK versions
1205+
/// prior to 0.3, 0.2.3, or 0.1.10.
12051206
///
12061207
/// [`Route::get_total_fees`]: crate::routing::router::Route::get_total_fees
12071208
fee_paid_msat: Option<u64>,

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8579,7 +8579,7 @@ pub fn test_inconsistent_mpp_params() {
85798579
pass_along_path(&nodes[0], path_b, real_amt, hash, Some(payment_secret), event, true, None);
85808580

85818581
do_claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], &[path_a, path_b], preimage));
8582-
expect_payment_sent(&nodes[0], preimage, Some(None), true, true);
8582+
expect_payment_sent(&nodes[0], preimage, Some(Some(2000)), true, true);
85838583
}
85848584

85858585
#[xtest(feature = "_externalize_tests")]

lightning/src/ln/outbound_payment.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ pub(crate) enum PendingOutboundPayment {
164164
/// The total payment amount across all paths, used to be able to issue `PaymentSent` if
165165
/// an HTLC still happens to succeed after we marked the payment as abandoned.
166166
total_msat: Option<u64>,
167+
/// Preserved from `Retryable` so we can still report `fee_paid_msat` if an HTLC succeeds after
168+
/// the payment was abandoned. Added in 0.3.
169+
pending_fee_msat: Option<u64>,
167170
},
168171
}
169172

@@ -252,6 +255,7 @@ impl PendingOutboundPayment {
252255
fn get_pending_fee_msat(&self) -> Option<u64> {
253256
match self {
254257
PendingOutboundPayment::Retryable { pending_fee_msat, .. } => pending_fee_msat.clone(),
258+
PendingOutboundPayment::Abandoned { pending_fee_msat, .. } => pending_fee_msat.clone(),
255259
_ => None,
256260
}
257261
}
@@ -308,6 +312,7 @@ impl PendingOutboundPayment {
308312
_ => new_hash_set(),
309313
};
310314
let total_msat = self.total_msat();
315+
let pending_fee_msat = self.get_pending_fee_msat();
311316
match self {
312317
Self::Retryable { payment_hash, .. } |
313318
Self::InvoiceReceived { payment_hash, .. } |
@@ -318,6 +323,7 @@ impl PendingOutboundPayment {
318323
payment_hash: *payment_hash,
319324
reason: Some(reason),
320325
total_msat,
326+
pending_fee_msat,
321327
};
322328
},
323329
_ => {}
@@ -2778,6 +2784,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
27782784
(1, reason, upgradable_option),
27792785
(2, payment_hash, required),
27802786
(3, total_msat, option),
2787+
(5, pending_fee_msat, option),
27812788
},
27822789
(5, AwaitingInvoice) => {
27832790
(0, expiration, required),

lightning/src/ln/payment_tests.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2256,6 +2256,36 @@ fn abandoned_send_payment_idempotent() {
22562256
claim_payment(&nodes[0], &[&nodes[1]], second_payment_preimage);
22572257
}
22582258

2259+
#[test]
2260+
fn abandoned_payment_fulfilled_preserves_fee_paid_msat() {
2261+
// Previously, if we abandoned a payment with HTLCs in-flight and the payment eventually
2262+
// succeeded, we would set the `Event::PaymentSent::fee_paid_msat` to None, even though we had
2263+
// docs guaranteeing that it would always be Some after 0.0.103.
2264+
let chanmon_cfgs = create_chanmon_cfgs(3);
2265+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
2266+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
2267+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
2268+
2269+
create_announced_chan_between_nodes(&nodes, 0, 1);
2270+
create_announced_chan_between_nodes(&nodes, 1, 2);
2271+
2272+
let amt_msat = 10_000_000;
2273+
let (route, payment_hash, payment_preimage, payment_secret) =
2274+
get_route_and_payment_hash!(&nodes[0], nodes[2], amt_msat);
2275+
let payment_id = PaymentId(payment_hash.0);
2276+
let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
2277+
nodes[0].node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
2278+
check_added_monitors(&nodes[0], 1);
2279+
2280+
let path: &[&Node] = &[&nodes[1], &nodes[2]];
2281+
pass_along_route(&nodes[0], &[path], amt_msat, payment_hash, payment_secret);
2282+
2283+
nodes[0].node.abandon_payment(payment_id);
2284+
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
2285+
2286+
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], &[path], payment_preimage));
2287+
}
2288+
22592289
#[derive(PartialEq)]
22602290
enum InterceptTest {
22612291
Forward,

0 commit comments

Comments
 (0)