Skip to content

Commit 847c511

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 2e9da4f commit 847c511

File tree

3 files changed

+18
-19
lines changed

3 files changed

+18
-19
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 10 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
},
@@ -5694,20 +5694,13 @@ mod tests {
56945694
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_third_raa);
56955695
check_added_monitors!(nodes[0], 1);
56965696

5697-
// There's an existing bug that generates a PaymentSent event for each MPP path, so handle that here.
56985697
let events = nodes[0].node.get_and_clear_pending_events();
56995698
match events[0] {
57005699
Event::PaymentSent { payment_preimage: ref preimage } => {
57015700
assert_eq!(payment_preimage, *preimage);
57025701
},
57035702
_ => panic!("Unexpected event"),
57045703
}
5705-
match events[1] {
5706-
Event::PaymentSent { payment_preimage: ref preimage } => {
5707-
assert_eq!(payment_preimage, *preimage);
5708-
},
5709-
_ => panic!("Unexpected event"),
5710-
}
57115704
}
57125705

57135706
#[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: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,12 @@ 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: we generate this event as soon as one of the payment paths succeeds. In
119+
/// the case of a buggy payee, this may be followed by a PaymentFailed or MPPFragmentFailed event
120+
/// if subsequent path(s) fail. However, this case should be extremely rare.
117121
PaymentSent {
118122
/// The preimage to the hash given to ChannelManager::send_payment.
119123
/// Note that this serves as a payment receipt, if you wish to have such a thing, you must

0 commit comments

Comments
 (0)