Skip to content

Commit 965e828

Browse files
Deduplicate PendingHTLCsForwardable events when generating
1 parent cc59f9e commit 965e828

File tree

3 files changed

+32
-34
lines changed

3 files changed

+32
-34
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3728,16 +3728,19 @@ where
37283728
// being fully configured. See the docs for `ChannelManagerReadArgs` for more.
37293729
match source {
37303730
HTLCSource::OutboundRoute { ref path, ref session_priv, ref payment_id, ref payment_params, .. } => {
3731-
self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path, session_priv, payment_id, payment_params, self.probing_cookie_secret, &self.secp_ctx, &self.pending_events, &self.logger);
3731+
if self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path,
3732+
session_priv, payment_id, payment_params, self.probing_cookie_secret, &self.secp_ctx,
3733+
&self.pending_events, &self.logger).is_some()
3734+
{ self.push_pending_forwards_ev(); }
37323735
},
37333736
HTLCSource::PreviousHopData(HTLCPreviousHopData { ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret, ref phantom_shared_secret, ref outpoint }) => {
37343737
log_trace!(self.logger, "Failing HTLC with payment_hash {} backwards from us with {:?}", log_bytes!(payment_hash.0), onion_error);
37353738
let err_packet = onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret);
37363739

3737-
let mut forward_event = None;
3740+
let mut push_forward_ev = false;
37383741
let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
37393742
if forward_htlcs.is_empty() {
3740-
forward_event = Some(Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS));
3743+
push_forward_ev = true;
37413744
}
37423745
match forward_htlcs.entry(*short_channel_id) {
37433746
hash_map::Entry::Occupied(mut entry) => {
@@ -3748,12 +3751,8 @@ where
37483751
}
37493752
}
37503753
mem::drop(forward_htlcs);
3754+
if push_forward_ev { self.push_pending_forwards_ev(); }
37513755
let mut pending_events = self.pending_events.lock().unwrap();
3752-
if let Some(time) = forward_event {
3753-
pending_events.push(events::Event::PendingHTLCsForwardable {
3754-
time_forwardable: time
3755-
});
3756-
}
37573756
pending_events.push(events::Event::HTLCHandlingFailed {
37583757
prev_channel_id: outpoint.to_channel_id(),
37593758
failed_next_destination: destination,
@@ -4830,7 +4829,7 @@ where
48304829
#[inline]
48314830
fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, OutPoint, u128, Vec<(PendingHTLCInfo, u64)>)]) {
48324831
for &mut (prev_short_channel_id, prev_funding_outpoint, prev_user_channel_id, ref mut pending_forwards) in per_source_pending_forwards {
4833-
let mut forward_event = None;
4832+
let mut push_forward_event = false;
48344833
let mut new_intercept_events = Vec::new();
48354834
let mut failed_intercept_forwards = Vec::new();
48364835
if !pending_forwards.is_empty() {
@@ -4888,7 +4887,7 @@ where
48884887
// We don't want to generate a PendingHTLCsForwardable event if only intercepted
48894888
// payments are being processed.
48904889
if forward_htlcs_empty {
4891-
forward_event = Some(Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS));
4890+
push_forward_event = true;
48924891
}
48934892
entry.insert(vec!(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
48944893
prev_short_channel_id, prev_funding_outpoint, prev_htlc_id, prev_user_channel_id, forward_info })));
@@ -4906,16 +4905,21 @@ where
49064905
let mut events = self.pending_events.lock().unwrap();
49074906
events.append(&mut new_intercept_events);
49084907
}
4908+
if push_forward_event { self.push_pending_forwards_ev() }
4909+
}
4910+
}
49094911

4910-
match forward_event {
4911-
Some(time) => {
4912-
let mut pending_events = self.pending_events.lock().unwrap();
4913-
pending_events.push(events::Event::PendingHTLCsForwardable {
4914-
time_forwardable: time
4915-
});
4916-
}
4917-
None => {},
4918-
}
4912+
// We only want to push a PendingHTLCsForwardable event if no others are queued.
4913+
fn push_pending_forwards_ev(&self) {
4914+
let mut pending_events = self.pending_events.lock().unwrap();
4915+
let forward_ev_exists = pending_events.iter()
4916+
.find(|ev| if let events::Event::PendingHTLCsForwardable { .. } = ev { true } else { false })
4917+
.is_some();
4918+
if !forward_ev_exists {
4919+
pending_events.push(events::Event::PendingHTLCsForwardable {
4920+
time_forwardable:
4921+
Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS),
4922+
});
49194923
}
49204924
}
49214925

lightning/src/ln/outbound_payment.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
1515

1616
use crate::chain::keysinterface::{EntropySource, NodeSigner, Recipient};
1717
use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
18-
use crate::ln::channelmanager::{ChannelDetails, HTLCSource, IDEMPOTENCY_TIMEOUT_TICKS, MIN_HTLC_RELAY_HOLDING_CELL_MILLIS, PaymentId};
18+
use crate::ln::channelmanager::{ChannelDetails, HTLCSource, IDEMPOTENCY_TIMEOUT_TICKS, PaymentId};
1919
use crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA as LDK_DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA;
2020
use crate::ln::msgs::DecodeError;
2121
use crate::ln::onion_utils::HTLCFailReason;
@@ -30,7 +30,6 @@ use crate::util::time::tests::SinceEpoch;
3030
use core::cmp;
3131
use core::fmt::{self, Display, Formatter};
3232
use core::ops::Deref;
33-
use core::time::Duration;
3433

3534
use crate::prelude::*;
3635
use crate::sync::Mutex;
@@ -1016,12 +1015,13 @@ impl OutboundPayments {
10161015
});
10171016
}
10181017

1018+
// Returns an Option indicating whether a PendingHTLCsForwardable event should be generated.
10191019
pub(super) fn fail_htlc<L: Deref>(
10201020
&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason,
10211021
path: &Vec<RouteHop>, session_priv: &SecretKey, payment_id: &PaymentId,
10221022
payment_params: &Option<PaymentParameters>, probing_cookie_secret: [u8; 32],
10231023
secp_ctx: &Secp256k1<secp256k1::All>, pending_events: &Mutex<Vec<events::Event>>, logger: &L
1024-
) where L::Target: Logger {
1024+
) -> Option<()> where L::Target: Logger {
10251025
#[cfg(test)]
10261026
let (network_update, short_channel_id, payment_retryable, onion_error_code, onion_error_data) = onion_error.decode_onion_failure(secp_ctx, logger, &source);
10271027
#[cfg(not(test))]
@@ -1038,11 +1038,11 @@ impl OutboundPayments {
10381038
let attempts_remaining = if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(*payment_id) {
10391039
if !payment.get_mut().remove(&session_priv_bytes, Some(&path)) {
10401040
log_trace!(logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
1041-
return
1041+
return None
10421042
}
10431043
if payment.get().is_fulfilled() {
10441044
log_trace!(logger, "Received failure of HTLC with payment_hash {} after payment completion", log_bytes!(payment_hash.0));
1045-
return
1045+
return None
10461046
}
10471047
let mut is_retryable_now = payment.get().is_auto_retryable_now();
10481048
if let Some(scid) = short_channel_id {
@@ -1092,7 +1092,7 @@ impl OutboundPayments {
10921092
is_retryable_now
10931093
} else {
10941094
log_trace!(logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
1095-
return
1095+
return None
10961096
};
10971097
core::mem::drop(outbounds);
10981098
log_trace!(logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0));
@@ -1124,9 +1124,7 @@ impl OutboundPayments {
11241124
// payment will sit in our outbounds forever.
11251125
if attempts_remaining {
11261126
debug_assert!(full_failure_ev.is_none());
1127-
pending_retry_ev = Some(events::Event::PendingHTLCsForwardable {
1128-
time_forwardable: Duration::from_millis(MIN_HTLC_RELAY_HOLDING_CELL_MILLIS),
1129-
});
1127+
pending_retry_ev = Some(());
11301128
}
11311129
events::Event::PaymentPathFailed {
11321130
payment_id: Some(*payment_id),
@@ -1147,7 +1145,7 @@ impl OutboundPayments {
11471145
let mut pending_events = pending_events.lock().unwrap();
11481146
pending_events.push(path_failure);
11491147
if let Some(ev) = full_failure_ev { pending_events.push(ev); }
1150-
if let Some(ev) = pending_retry_ev { pending_events.push(ev); }
1148+
pending_retry_ev
11511149
}
11521150

11531151
pub(super) fn abandon_payment(&self, payment_id: PaymentId,

lightning/src/ln/payment_tests.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2269,7 +2269,7 @@ fn no_extra_retries_on_back_to_back_fail() {
22692269
// Because we now retry payments as a batch, we simply return a single-path route in the
22702270
// second, batched, request, have that fail, ensure the payment was abandoned.
22712271
let mut events = nodes[0].node.get_and_clear_pending_events();
2272-
assert_eq!(events.len(), 4);
2272+
assert_eq!(events.len(), 3);
22732273
match events[0] {
22742274
Event::PaymentPathFailed { payment_hash: ev_payment_hash, payment_failed_permanently, .. } => {
22752275
assert_eq!(payment_hash, ev_payment_hash);
@@ -2288,10 +2288,6 @@ fn no_extra_retries_on_back_to_back_fail() {
22882288
},
22892289
_ => panic!("Unexpected event"),
22902290
}
2291-
match events[3] {
2292-
Event::PendingHTLCsForwardable { .. } => {},
2293-
_ => panic!("Unexpected event"),
2294-
}
22952291

22962292
nodes[0].node.process_pending_htlc_forwards();
22972293
let retry_htlc_updates = SendEvent::from_node(&nodes[0]);

0 commit comments

Comments
 (0)