Skip to content

Commit 7bdaf90

Browse files
Timeout expired outbound async payments.
1 parent 8e5c81e commit 7bdaf90

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,22 @@ impl OutboundPayments {
18191819
true
18201820
}
18211821
},
1822+
PendingOutboundPayment::StaticInvoiceReceived { route_params, payment_hash, .. } => {
1823+
let is_stale =
1824+
route_params.payment_params.expiry_time.unwrap_or_else(u64::max_value) <
1825+
duration_since_epoch.as_secs();
1826+
if is_stale {
1827+
let fail_ev = events::Event::PaymentFailed {
1828+
payment_id: *payment_id,
1829+
payment_hash: *payment_hash,
1830+
reason: Some(PaymentFailureReason::PaymentExpired)
1831+
};
1832+
pending_events.push_back((fail_ev, None));
1833+
false
1834+
} else {
1835+
true
1836+
}
1837+
},
18221838
_ => true,
18231839
});
18241840
}
@@ -2070,11 +2086,11 @@ mod tests {
20702086

20712087
use crate::blinded_path::EmptyNodeIdLookUp;
20722088
use crate::events::{Event, PathFailure, PaymentFailureReason};
2073-
use crate::ln::types::PaymentHash;
2089+
use crate::ln::types::{PaymentHash, PaymentPreimage};
20742090
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
20752091
use crate::ln::features::{ChannelFeatures, NodeFeatures};
20762092
use crate::ln::msgs::{ErrorAction, LightningError};
2077-
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, Retry, RetryableSendFailure, StaleExpiration};
2093+
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PendingOutboundPayment, Retry, RetryableSendFailure, StaleExpiration};
20782094
#[cfg(feature = "std")]
20792095
use crate::offers::invoice::DEFAULT_RELATIVE_EXPIRY;
20802096
use crate::offers::offer::OfferBuilder;
@@ -2613,4 +2629,51 @@ mod tests {
26132629
assert!(outbound_payments.has_pending_payments());
26142630
assert!(pending_events.lock().unwrap().is_empty());
26152631
}
2632+
2633+
#[test]
2634+
fn time_out_unreleased_async_payments() {
2635+
let pending_events = Mutex::new(VecDeque::new());
2636+
let outbound_payments = OutboundPayments::new();
2637+
let payment_id = PaymentId([0; 32]);
2638+
let absolute_expiry = 60;
2639+
2640+
let mut outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2641+
let payment_params = PaymentParameters::from_node_id(test_utils::pubkey(42), 0)
2642+
.with_expiry_time(absolute_expiry);
2643+
let route_params = RouteParameters {
2644+
payment_params,
2645+
final_value_msat: 0,
2646+
max_total_routing_fee_msat: None,
2647+
};
2648+
let payment_hash = PaymentHash([0; 32]);
2649+
let outbound = PendingOutboundPayment::StaticInvoiceReceived {
2650+
payment_hash,
2651+
keysend_preimage: PaymentPreimage([0; 32]),
2652+
retry_strategy: Retry::Attempts(0),
2653+
payment_release_secret: [0; 32],
2654+
route_params,
2655+
};
2656+
outbounds.insert(payment_id, outbound);
2657+
core::mem::drop(outbounds);
2658+
2659+
// The payment will not be removed if it isn't expired yet.
2660+
outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry), &pending_events);
2661+
let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2662+
assert_eq!(outbounds.len(), 1);
2663+
let events = pending_events.lock().unwrap();
2664+
assert_eq!(events.len(), 0);
2665+
core::mem::drop(outbounds);
2666+
core::mem::drop(events);
2667+
2668+
outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry + 1), &pending_events);
2669+
let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2670+
assert_eq!(outbounds.len(), 0);
2671+
let events = pending_events.lock().unwrap();
2672+
assert_eq!(events.len(), 1);
2673+
assert_eq!(events[0], (Event::PaymentFailed {
2674+
payment_hash,
2675+
payment_id,
2676+
reason: Some(PaymentFailureReason::PaymentExpired),
2677+
}, None));
2678+
}
26162679
}

0 commit comments

Comments
 (0)