Skip to content

Commit 7e98017

Browse files
committed
Await invoice for variable number of timer ticks
PendingOutboundPayment::AwaitingInvoice counts the number of timer ticks that have passed awaiting a Bolt12Invoice for an InvoiceRequest. When a constant INVOICE_REQUEST_TIMEOUT_TICKS has passed, the payment is forgotten. However, this mechanism is insufficient for the Refund scenario, where the Refund's expiration should be used instead. Change AwaitingInvoice to store the number of timer ticks remaining instead of the number that has passed. This allows for a variable number of ticks that are instead counted down.
1 parent 1c5a7b3 commit 7e98017

File tree

1 file changed

+59
-22
lines changed

1 file changed

+59
-22
lines changed

lightning/src/ln/outbound_payment.rs

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub(crate) const IDEMPOTENCY_TIMEOUT_TICKS: u8 = 7;
4343
/// a response is timed out.
4444
///
4545
/// [`ChannelManager::timer_tick_occurred`]: crate::ln::channelmanager::ChannelManager::timer_tick_occurred
46-
const INVOICE_REQUEST_TIMEOUT_TICKS: u8 = 3;
46+
const INVOICE_REQUEST_TIMEOUT_TICKS: Option<u64> = Some(3);
4747

4848
/// Stores the session_priv for each part of a payment that is still pending. For versions 0.0.102
4949
/// and later, also stores information for retrying the payment.
@@ -52,7 +52,7 @@ pub(crate) enum PendingOutboundPayment {
5252
session_privs: HashSet<[u8; 32]>,
5353
},
5454
AwaitingInvoice {
55-
timer_ticks_without_response: u8,
55+
timer_ticks_without_response_remaining: Option<u64>,
5656
retry_strategy: Retry,
5757
max_total_routing_fee_msat: Option<u64>,
5858
},
@@ -1274,15 +1274,35 @@ impl OutboundPayments {
12741274
}
12751275

12761276
#[allow(unused)]
1277-
pub(super) fn add_new_awaiting_invoice(
1277+
pub(super) fn add_new_awaiting_invoice_for_offer(
12781278
&self, payment_id: PaymentId, retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>
1279+
) -> Result<(), ()> {
1280+
self.add_new_awaiting_invoice(
1281+
payment_id, retry_strategy, max_total_routing_fee_msat, INVOICE_REQUEST_TIMEOUT_TICKS
1282+
)
1283+
}
1284+
1285+
#[allow(unused)]
1286+
pub(super) fn add_new_awaiting_invoice_for_refund(
1287+
&self, payment_id: PaymentId, retry_strategy: Retry,
1288+
max_total_routing_fee_msat: Option<u64>, timer_ticks_before_expiration: Option<u64>
1289+
) -> Result<(), ()> {
1290+
self.add_new_awaiting_invoice(
1291+
payment_id, retry_strategy, max_total_routing_fee_msat, timer_ticks_before_expiration
1292+
)
1293+
}
1294+
1295+
#[allow(unused)]
1296+
fn add_new_awaiting_invoice(
1297+
&self, payment_id: PaymentId, retry_strategy: Retry,
1298+
max_total_routing_fee_msat: Option<u64>, timer_ticks_before_expiration: Option<u64>
12791299
) -> Result<(), ()> {
12801300
let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
12811301
match pending_outbounds.entry(payment_id) {
12821302
hash_map::Entry::Occupied(_) => Err(()),
12831303
hash_map::Entry::Vacant(entry) => {
12841304
entry.insert(PendingOutboundPayment::AwaitingInvoice {
1285-
timer_ticks_without_response: 0,
1305+
timer_ticks_without_response_remaining: timer_ticks_before_expiration,
12861306
retry_strategy,
12871307
max_total_routing_fee_msat,
12881308
});
@@ -1550,9 +1570,11 @@ impl OutboundPayments {
15501570
*timer_ticks_without_htlcs = 0;
15511571
true
15521572
}
1553-
} else if let PendingOutboundPayment::AwaitingInvoice { timer_ticks_without_response, .. } = payment {
1554-
*timer_ticks_without_response += 1;
1555-
if *timer_ticks_without_response <= INVOICE_REQUEST_TIMEOUT_TICKS {
1573+
} else if let PendingOutboundPayment::AwaitingInvoice {
1574+
timer_ticks_without_response_remaining: Some(timer_ticks_remaining), ..
1575+
} = payment {
1576+
if *timer_ticks_remaining > 0 {
1577+
*timer_ticks_remaining -= 1;
15561578
true
15571579
} else {
15581580
#[cfg(invreqfailed)]
@@ -1778,7 +1800,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
17781800
(2, payment_hash, required),
17791801
},
17801802
(5, AwaitingInvoice) => {
1781-
(0, timer_ticks_without_response, required),
1803+
(0, timer_ticks_without_response_remaining, option),
17821804
(2, retry_strategy, required),
17831805
(4, max_total_routing_fee_msat, option),
17841806
},
@@ -2014,11 +2036,13 @@ mod tests {
20142036

20152037
assert!(!outbound_payments.has_pending_payments());
20162038
assert!(
2017-
outbound_payments.add_new_awaiting_invoice(payment_id, Retry::Attempts(0), None).is_ok()
2039+
outbound_payments.add_new_awaiting_invoice(
2040+
payment_id, Retry::Attempts(0), None, INVOICE_REQUEST_TIMEOUT_TICKS
2041+
).is_ok()
20182042
);
20192043
assert!(outbound_payments.has_pending_payments());
20202044

2021-
for _ in 0..INVOICE_REQUEST_TIMEOUT_TICKS {
2045+
for _ in 0..INVOICE_REQUEST_TIMEOUT_TICKS.unwrap() {
20222046
outbound_payments.remove_stale_payments(&pending_events);
20232047
assert!(outbound_payments.has_pending_payments());
20242048
assert!(pending_events.lock().unwrap().is_empty());
@@ -2034,13 +2058,16 @@ mod tests {
20342058
assert!(pending_events.lock().unwrap().is_empty());
20352059

20362060
assert!(
2037-
outbound_payments.add_new_awaiting_invoice(payment_id, Retry::Attempts(0), None).is_ok()
2061+
outbound_payments.add_new_awaiting_invoice(
2062+
payment_id, Retry::Attempts(0), None, INVOICE_REQUEST_TIMEOUT_TICKS
2063+
).is_ok()
20382064
);
20392065
assert!(outbound_payments.has_pending_payments());
20402066

20412067
assert!(
2042-
outbound_payments.add_new_awaiting_invoice(payment_id, Retry::Attempts(0), None)
2043-
.is_err()
2068+
outbound_payments.add_new_awaiting_invoice(
2069+
payment_id, Retry::Attempts(0), None, INVOICE_REQUEST_TIMEOUT_TICKS
2070+
).is_err()
20442071
);
20452072
}
20462073

@@ -2053,7 +2080,9 @@ mod tests {
20532080

20542081
assert!(!outbound_payments.has_pending_payments());
20552082
assert!(
2056-
outbound_payments.add_new_awaiting_invoice(payment_id, Retry::Attempts(0), None).is_ok()
2083+
outbound_payments.add_new_awaiting_invoice(
2084+
payment_id, Retry::Attempts(0), None, INVOICE_REQUEST_TIMEOUT_TICKS
2085+
).is_ok()
20572086
);
20582087
assert!(outbound_payments.has_pending_payments());
20592088

@@ -2083,7 +2112,9 @@ mod tests {
20832112
let payment_id = PaymentId([0; 32]);
20842113

20852114
assert!(
2086-
outbound_payments.add_new_awaiting_invoice(payment_id, Retry::Attempts(0), None).is_ok()
2115+
outbound_payments.add_new_awaiting_invoice(
2116+
payment_id, Retry::Attempts(0), None, INVOICE_REQUEST_TIMEOUT_TICKS
2117+
).is_ok()
20872118
);
20882119
assert!(outbound_payments.has_pending_payments());
20892120

@@ -2140,9 +2171,11 @@ mod tests {
21402171
.build().unwrap()
21412172
.sign(recipient_sign).unwrap();
21422173

2143-
assert!(outbound_payments.add_new_awaiting_invoice(
2144-
payment_id, Retry::Attempts(0), Some(invoice.amount_msats() / 100 + 50_000))
2145-
.is_ok()
2174+
assert!(
2175+
outbound_payments.add_new_awaiting_invoice(
2176+
payment_id, Retry::Attempts(0), Some(invoice.amount_msats() / 100 + 50_000),
2177+
INVOICE_REQUEST_TIMEOUT_TICKS
2178+
).is_ok()
21462179
);
21472180
assert!(outbound_payments.has_pending_payments());
21482181

@@ -2196,9 +2229,11 @@ mod tests {
21962229
.build().unwrap()
21972230
.sign(recipient_sign).unwrap();
21982231

2199-
assert!(outbound_payments.add_new_awaiting_invoice(
2200-
payment_id, Retry::Attempts(0), Some(invoice.amount_msats() / 100 + 50_000))
2201-
.is_ok()
2232+
assert!(
2233+
outbound_payments.add_new_awaiting_invoice(
2234+
payment_id, Retry::Attempts(0), Some(invoice.amount_msats() / 100 + 50_000),
2235+
INVOICE_REQUEST_TIMEOUT_TICKS
2236+
).is_ok()
22022237
);
22032238
assert!(outbound_payments.has_pending_payments());
22042239

@@ -2292,7 +2327,9 @@ mod tests {
22922327
assert!(pending_events.lock().unwrap().is_empty());
22932328

22942329
assert!(
2295-
outbound_payments.add_new_awaiting_invoice(payment_id, Retry::Attempts(0), Some(1234)).is_ok()
2330+
outbound_payments.add_new_awaiting_invoice(
2331+
payment_id, Retry::Attempts(0), Some(1234), INVOICE_REQUEST_TIMEOUT_TICKS
2332+
).is_ok()
22962333
);
22972334
assert!(outbound_payments.has_pending_payments());
22982335

0 commit comments

Comments
 (0)