Skip to content

Commit cf8d799

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 09974c8 commit cf8d799

File tree

3 files changed

+19
-19
lines changed

3 files changed

+19
-19
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3140,18 +3140,18 @@ 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);
3143+
let found_payment = loop {
3144+
if let Some(mut sessions) = outbounds.remove(&mpp_id) {
3145+
if sessions.remove(&session_priv_bytes) {
3146+
self.pending_events.lock().unwrap().push(
3147+
events::Event::PaymentSent { payment_preimage }
3148+
);
3149+
break true
31503150
}
3151-
} else {
3152-
log_trace!(self.logger, "Received duplicative fulfill for HTLC with payment_preimage {}", log_bytes!(payment_preimage.0));
31533151
}
3154-
} else {
3152+
break false
3153+
};
3154+
if !found_payment {
31553155
log_trace!(self.logger, "Received duplicative fulfill for HTLC with payment_preimage {}", log_bytes!(payment_preimage.0));
31563156
}
31573157
},
@@ -5691,20 +5691,15 @@ mod tests {
56915691
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa);
56925692
check_added_monitors!(nodes[0], 1);
56935693

5694-
// There's an existing bug that generates a PaymentSent event for each MPP path, so handle that here.
5694+
// Note that successful MPP payments will generate 1 event upon the first path's success. No
5695+
// further events will be generated for subsequence path successes.
56955696
let events = nodes[0].node.get_and_clear_pending_events();
56965697
match events[0] {
56975698
Event::PaymentSent { payment_preimage: ref preimage } => {
56985699
assert_eq!(payment_preimage, *preimage);
56995700
},
57005701
_ => panic!("Unexpected event"),
57015702
}
5702-
match events[1] {
5703-
Event::PaymentSent { payment_preimage: ref preimage } => {
5704-
assert_eq!(payment_preimage, *preimage);
5705-
},
5706-
_ => panic!("Unexpected event"),
5707-
}
57085703
}
57095704

57105705
#[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)