Skip to content

Commit 8abcdd3

Browse files
Timeout expired outbound async payments.
1 parent 14293fe commit 8abcdd3

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
@@ -1892,6 +1892,22 @@ impl OutboundPayments {
18921892
true
18931893
}
18941894
},
1895+
PendingOutboundPayment::StaticInvoiceReceived { route_params, payment_hash, .. } => {
1896+
let is_stale =
1897+
route_params.payment_params.expiry_time.unwrap_or(u64::MAX) <
1898+
duration_since_epoch.as_secs();
1899+
if is_stale {
1900+
let fail_ev = events::Event::PaymentFailed {
1901+
payment_id: *payment_id,
1902+
payment_hash: Some(*payment_hash),
1903+
reason: Some(PaymentFailureReason::PaymentExpired)
1904+
};
1905+
pending_events.push_back((fail_ev, None));
1906+
false
1907+
} else {
1908+
true
1909+
}
1910+
},
18951911
_ => true,
18961912
});
18971913
}
@@ -2172,11 +2188,11 @@ mod tests {
21722188

21732189
use crate::blinded_path::EmptyNodeIdLookUp;
21742190
use crate::events::{Event, PathFailure, PaymentFailureReason};
2175-
use crate::ln::types::PaymentHash;
2191+
use crate::ln::types::{PaymentHash, PaymentPreimage};
21762192
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
21772193
use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures};
21782194
use crate::ln::msgs::{ErrorAction, LightningError};
2179-
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, Retry, RetryableSendFailure, StaleExpiration};
2195+
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PendingOutboundPayment, Retry, RetryableSendFailure, StaleExpiration};
21802196
#[cfg(feature = "std")]
21812197
use crate::offers::invoice::DEFAULT_RELATIVE_EXPIRY;
21822198
use crate::offers::offer::OfferBuilder;
@@ -2726,4 +2742,51 @@ mod tests {
27262742
assert!(outbound_payments.has_pending_payments());
27272743
assert!(pending_events.lock().unwrap().is_empty());
27282744
}
2745+
2746+
#[test]
2747+
fn time_out_unreleased_async_payments() {
2748+
let pending_events = Mutex::new(VecDeque::new());
2749+
let outbound_payments = OutboundPayments::new(new_hash_map());
2750+
let payment_id = PaymentId([0; 32]);
2751+
let absolute_expiry = 60;
2752+
2753+
let mut outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2754+
let payment_params = PaymentParameters::from_node_id(test_utils::pubkey(42), 0)
2755+
.with_expiry_time(absolute_expiry);
2756+
let route_params = RouteParameters {
2757+
payment_params,
2758+
final_value_msat: 0,
2759+
max_total_routing_fee_msat: None,
2760+
};
2761+
let payment_hash = PaymentHash([0; 32]);
2762+
let outbound = PendingOutboundPayment::StaticInvoiceReceived {
2763+
payment_hash,
2764+
keysend_preimage: PaymentPreimage([0; 32]),
2765+
retry_strategy: Retry::Attempts(0),
2766+
payment_release_secret: [0; 32],
2767+
route_params,
2768+
};
2769+
outbounds.insert(payment_id, outbound);
2770+
core::mem::drop(outbounds);
2771+
2772+
// The payment will not be removed if it isn't expired yet.
2773+
outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry), &pending_events);
2774+
let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2775+
assert_eq!(outbounds.len(), 1);
2776+
let events = pending_events.lock().unwrap();
2777+
assert_eq!(events.len(), 0);
2778+
core::mem::drop(outbounds);
2779+
core::mem::drop(events);
2780+
2781+
outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry + 1), &pending_events);
2782+
let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
2783+
assert_eq!(outbounds.len(), 0);
2784+
let events = pending_events.lock().unwrap();
2785+
assert_eq!(events.len(), 1);
2786+
assert_eq!(events[0], (Event::PaymentFailed {
2787+
payment_hash: Some(payment_hash),
2788+
payment_id,
2789+
reason: Some(PaymentFailureReason::PaymentExpired),
2790+
}, None));
2791+
}
27292792
}

0 commit comments

Comments
 (0)