Skip to content

Commit

Permalink
Timeout expired outbound async payments.
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinewallace committed Jul 10, 2024
1 parent 1f532c3 commit 02ea137
Showing 1 changed file with 65 additions and 2 deletions.
67 changes: 65 additions & 2 deletions lightning/src/ln/outbound_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,22 @@ impl OutboundPayments {
true
}
},
PendingOutboundPayment::StaticInvoiceReceived { route_params, payment_hash, .. } => {
let is_stale =
route_params.payment_params.expiry_time.unwrap_or_else(u64::max_value) <
duration_since_epoch.as_secs();
if is_stale {
let fail_ev = events::Event::PaymentFailed {
payment_id: *payment_id,
payment_hash: *payment_hash,
reason: Some(PaymentFailureReason::PaymentExpired)
};
pending_events.push_back((fail_ev, None));
false
} else {
true
}
},
_ => true,
});
}
Expand Down Expand Up @@ -2010,11 +2026,11 @@ mod tests {

use crate::blinded_path::EmptyNodeIdLookUp;
use crate::events::{Event, PathFailure, PaymentFailureReason};
use crate::ln::types::PaymentHash;
use crate::ln::types::{PaymentHash, PaymentPreimage};
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
use crate::ln::features::{ChannelFeatures, NodeFeatures};
use crate::ln::msgs::{ErrorAction, LightningError};
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, Retry, RetryableSendFailure, StaleExpiration};
use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PendingOutboundPayment, Retry, RetryableSendFailure, StaleExpiration};
#[cfg(feature = "std")]
use crate::offers::invoice::DEFAULT_RELATIVE_EXPIRY;
use crate::offers::offer::OfferBuilder;
Expand Down Expand Up @@ -2553,4 +2569,51 @@ mod tests {
assert!(outbound_payments.has_pending_payments());
assert!(pending_events.lock().unwrap().is_empty());
}

#[test]
fn time_out_unreleased_async_payments() {
let pending_events = Mutex::new(VecDeque::new());
let outbound_payments = OutboundPayments::new();
let payment_id = PaymentId([0; 32]);
let absolute_expiry = 60;

let mut outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
let payment_params = PaymentParameters::from_node_id(test_utils::pubkey(42), 0)
.with_expiry_time(absolute_expiry);
let route_params = RouteParameters {
payment_params,
final_value_msat: 0,
max_total_routing_fee_msat: None,
};
let payment_hash = PaymentHash([0; 32]);
let outbound = PendingOutboundPayment::StaticInvoiceReceived {
payment_hash,
keysend_preimage: PaymentPreimage([0; 32]),
retry_strategy: Retry::Attempts(0),
payment_release_secret: [0; 32],
route_params,
};
outbounds.insert(payment_id, outbound);
core::mem::drop(outbounds);

// The payment will not be removed if it isn't expired yet.
outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry), &pending_events);
let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
assert_eq!(outbounds.len(), 1);
let events = pending_events.lock().unwrap();
assert_eq!(events.len(), 0);
core::mem::drop(outbounds);
core::mem::drop(events);

outbound_payments.remove_stale_payments(Duration::from_secs(absolute_expiry + 1), &pending_events);
let outbounds = outbound_payments.pending_outbound_payments.lock().unwrap();
assert_eq!(outbounds.len(), 0);
let events = pending_events.lock().unwrap();
assert_eq!(events.len(), 1);
assert_eq!(events[0], (Event::PaymentFailed {
payment_hash,
payment_id,
reason: Some(PaymentFailureReason::PaymentExpired),
}, None));
}
}

0 comments on commit 02ea137

Please sign in to comment.