Skip to content

Commit 464798f

Browse files
Timeout expired outbound async payments.
1 parent 676b67c commit 464798f

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
@@ -1718,6 +1718,22 @@ impl OutboundPayments {
17181718
true
17191719
}
17201720
},
1721+
PendingOutboundPayment::StaticInvoiceReceived { route_params, payment_hash, .. } => {
1722+
let is_stale =
1723+
route_params.payment_params.expiry_time.unwrap_or_else(u64::max_value) <
1724+
duration_since_epoch.as_secs();
1725+
if is_stale {
1726+
let fail_ev = events::Event::PaymentFailed {
1727+
payment_id: *payment_id,
1728+
payment_hash: *payment_hash,
1729+
reason: Some(PaymentFailureReason::PaymentExpired)
1730+
};
1731+
pending_events.push_back((fail_ev, None));
1732+
false
1733+
} else {
1734+
true
1735+
}
1736+
},
17211737
_ => true,
17221738
});
17231739
}
@@ -1982,11 +1998,11 @@ mod tests {
19821998
use core::time::Duration;
19831999

19842000
use crate::events::{Event, PathFailure, PaymentFailureReason};
1985-
use crate::ln::types::PaymentHash;
2001+
use crate::ln::types::{PaymentHash, PaymentPreimage};
19862002
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
19872003
use crate::ln::features::{ChannelFeatures, NodeFeatures};
19882004
use crate::ln::msgs::{ErrorAction, LightningError};
1989-
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, Retry, RetryableSendFailure, StaleExpiration};
2005+
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PendingOutboundPayment, Retry, RetryableSendFailure, StaleExpiration};
19902006
#[cfg(feature = "std")]
19912007
use crate::offers::invoice::DEFAULT_RELATIVE_EXPIRY;
19922008
use crate::offers::offer::OfferBuilder;
@@ -2517,4 +2533,51 @@ mod tests {
25172533
assert!(outbound_payments.has_pending_payments());
25182534
assert!(pending_events.lock().unwrap().is_empty());
25192535
}
2536+
2537+
#[test]
2538+
fn time_out_unreleased_async_payments() {
2539+
let pending_events = Mutex::new(VecDeque::new());
2540+
let outbound_payments = OutboundPayments::new();
2541+
let payment_id = PaymentId([0; 32]);
2542+
let absolute_expiry = 60;
2543+
2544+
let mut outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2545+
let payment_params = PaymentParameters::from_node_id(test_utils::pubkey(42), 0)
2546+
.with_expiry_time(absolute_expiry);
2547+
let route_params = RouteParameters {
2548+
payment_params,
2549+
final_value_msat: 0,
2550+
max_total_routing_fee_msat: None,
2551+
};
2552+
let payment_hash = PaymentHash([0; 32]);
2553+
let outbound = PendingOutboundPayment::StaticInvoiceReceived {
2554+
payment_hash,
2555+
keysend_preimage: PaymentPreimage([0; 32]),
2556+
retry_strategy: Retry::Attempts(0),
2557+
payment_release_secret: [0; 32],
2558+
route_params,
2559+
};
2560+
outbounds.insert(payment_id, outbound);
2561+
core::mem::drop(outbounds);
2562+
2563+
// The payment will not be removed if it isn't expired yet.
2564+
outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry), &pending_events);
2565+
let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2566+
assert_eq!(outbounds.len(), 1);
2567+
let events = pending_events.lock().unwrap();
2568+
assert_eq!(events.len(), 0);
2569+
core::mem::drop(outbounds);
2570+
core::mem::drop(events);
2571+
2572+
outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry + 1), &pending_events);
2573+
let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2574+
assert_eq!(outbounds.len(), 0);
2575+
let events = pending_events.lock().unwrap();
2576+
assert_eq!(events.len(), 1);
2577+
assert_eq!(events[0], (Event::PaymentFailed {
2578+
payment_hash,
2579+
payment_id,
2580+
reason: Some(PaymentFailureReason::PaymentExpired),
2581+
}, None));
2582+
}
25202583
}

0 commit comments

Comments
 (0)