Skip to content

Commit 8f17631

Browse files
Prevent duplicate PaymentSent events
by removing all pending outbound payments associated with the same MPP payment after the preimage is received
1 parent ad81add commit 8f17631

File tree

3 files changed

+16
-20
lines changed

3 files changed

+16
-20
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3140,17 +3140,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31403140
let mut session_priv_bytes = [0; 32];
31413141
session_priv_bytes.copy_from_slice(&session_priv[..]);
31423142
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
3143-
if let Some(sessions) = outbounds.get_mut(&mpp_id) {
3144-
if sessions.remove(&session_priv_bytes) {
3145-
self.pending_events.lock().unwrap().push(
3146-
events::Event::PaymentSent { payment_preimage }
3147-
);
3148-
if sessions.len() == 0 {
3149-
outbounds.remove(&mpp_id);
3150-
}
3151-
} else {
3152-
log_trace!(self.logger, "Received duplicative fulfill for HTLC with payment_preimage {}", log_bytes!(payment_preimage.0));
3153-
}
3143+
let found_payment = if let Some(mut sessions) = outbounds.remove(&mpp_id) {
3144+
sessions.remove(&session_priv_bytes)
3145+
} else { false };
3146+
if found_payment {
3147+
self.pending_events.lock().unwrap().push(
3148+
events::Event::PaymentSent { payment_preimage }
3149+
);
31543150
} else {
31553151
log_trace!(self.logger, "Received duplicative fulfill for HTLC with payment_preimage {}", log_bytes!(payment_preimage.0));
31563152
}
@@ -5691,20 +5687,15 @@ mod tests {
56915687
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa);
56925688
check_added_monitors!(nodes[0], 1);
56935689

5694-
// There's an existing bug that generates a PaymentSent event for each MPP path, so handle that here.
5690+
// Note that successful MPP payments will generate 1 event upon the first path's success. No
5691+
// further events will be generated for subsequence path successes.
56955692
let events = nodes[0].node.get_and_clear_pending_events();
56965693
match events[0] {
56975694
Event::PaymentSent { payment_preimage: ref preimage } => {
56985695
assert_eq!(payment_preimage, *preimage);
56995696
},
57005697
_ => panic!("Unexpected event"),
57015698
}
5702-
match events[1] {
5703-
Event::PaymentSent { payment_preimage: ref preimage } => {
5704-
assert_eq!(payment_preimage, *preimage);
5705-
},
5706-
_ => panic!("Unexpected event"),
5707-
}
57085699
}
57095700

57105701
#[test]

lightning/src/ln/functional_test_utils.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,9 +1242,11 @@ pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, exp
12421242

12431243
if !skip_last {
12441244
last_update_fulfill_dance!(origin_node, expected_route.first().unwrap());
1245-
expect_payment_sent!(origin_node, our_payment_preimage);
12461245
}
12471246
}
1247+
if !skip_last {
1248+
expect_payment_sent!(origin_node, our_payment_preimage);
1249+
}
12481250
}
12491251

12501252
pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage) {

lightning/src/util/events.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,11 @@ pub enum Event {
112112
/// payment is to pay an invoice or to send a spontaneous payment.
113113
purpose: PaymentPurpose,
114114
},
115-
/// Indicates an outbound payment we made succeeded (ie it made it all the way to its target
115+
/// Indicates an outbound payment we made succeeded (i.e. it made it all the way to its target
116116
/// and we got back the payment preimage for it).
117+
///
118+
/// Note for MPP payments: in rare cases, this event may be preceded by a `PaymentFailed` event.
119+
/// In this situation, you SHOULD treat this payment as having succeeded.
117120
PaymentSent {
118121
/// The preimage to the hash given to ChannelManager::send_payment.
119122
/// Note that this serves as a payment receipt, if you wish to have such a thing, you must

0 commit comments

Comments
 (0)