Skip to content

Commit 59659d3

Browse files
authored
Merge pull request #1059 from jkczyz/2021-08-payment-retry
Payment Retries
2 parents 2ed1ba6 + 010436d commit 59659d3

18 files changed

+1332
-147
lines changed

fuzz/src/full_stack.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,Ig
3838
use lightning::ln::msgs::DecodeError;
3939
use lightning::ln::script::ShutdownScript;
4040
use lightning::routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
41-
use lightning::routing::router::{get_route, Payee};
41+
use lightning::routing::router::{find_route, Payee, RouteParameters};
4242
use lightning::routing::scorer::Scorer;
4343
use lightning::util::config::UserConfig;
4444
use lightning::util::errors::APIError;
@@ -437,9 +437,14 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
437437
}
438438
},
439439
4 => {
440-
let value = slice_to_be24(get_slice!(3)) as u64;
440+
let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
441441
let payee = Payee::new(get_pubkey!());
442-
let route = match get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, value, 42, Arc::clone(&logger), &scorer) {
442+
let params = RouteParameters {
443+
payee,
444+
final_value_msat,
445+
final_cltv_expiry_delta: 42,
446+
};
447+
let route = match find_route(&our_id, &params, &net_graph_msg_handler.network_graph, None, Arc::clone(&logger), &scorer) {
443448
Ok(route) => route,
444449
Err(_) => return,
445450
};
@@ -455,9 +460,14 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
455460
}
456461
},
457462
15 => {
458-
let value = slice_to_be24(get_slice!(3)) as u64;
463+
let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
459464
let payee = Payee::new(get_pubkey!());
460-
let mut route = match get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, value, 42, Arc::clone(&logger), &scorer) {
465+
let params = RouteParameters {
466+
payee,
467+
final_value_msat,
468+
final_cltv_expiry_delta: 42,
469+
};
470+
let mut route = match find_route(&our_id, &params, &net_graph_msg_handler.network_graph, None, Arc::clone(&logger), &scorer) {
461471
Ok(route) => route,
462472
Err(_) => return,
463473
};

fuzz/src/router.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use lightning::chain::transaction::OutPoint;
1616
use lightning::ln::channelmanager::{ChannelDetails, ChannelCounterparty};
1717
use lightning::ln::features::InitFeatures;
1818
use lightning::ln::msgs;
19-
use lightning::routing::router::{get_route, Payee, RouteHint, RouteHintHop};
19+
use lightning::routing::router::{find_route, Payee, RouteHint, RouteHintHop, RouteParameters};
2020
use lightning::routing::scorer::Scorer;
2121
use lightning::util::logger::Logger;
2222
use lightning::util::ser::Readable;
@@ -250,10 +250,14 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
250250
}
251251
let scorer = Scorer::new(0);
252252
for target in node_pks.iter() {
253-
let payee = Payee::new(*target).with_route_hints(last_hops.clone());
254-
let _ = get_route(&our_pubkey, &payee, &net_graph,
253+
let params = RouteParameters {
254+
payee: Payee::new(*target).with_route_hints(last_hops.clone()),
255+
final_value_msat: slice_to_be64(get_slice!(8)),
256+
final_cltv_expiry_delta: slice_to_be32(get_slice!(4)),
257+
};
258+
let _ = find_route(&our_pubkey, &params, &net_graph,
255259
first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
256-
slice_to_be64(get_slice!(8)), slice_to_be32(get_slice!(4)), Arc::clone(&logger), &scorer);
260+
Arc::clone(&logger), &scorer);
257261
}
258262
},
259263
}

lightning-invoice/src/lib.rs

+50-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
//! * For parsing use `str::parse::<Invoice>(&self)` (see the docs of `impl FromStr for Invoice`)
1616
//! * For constructing invoices use the `InvoiceBuilder`
1717
//! * For serializing invoices use the `Display`/`ToString` traits
18+
pub mod payment;
1819
pub mod utils;
1920

2021
extern crate bech32;
2122
extern crate bitcoin_hashes;
22-
extern crate lightning;
23+
#[macro_use] extern crate lightning;
2324
extern crate num_traits;
2425
extern crate secp256k1;
2526

@@ -1187,6 +1188,19 @@ impl Invoice {
11871188
.unwrap_or(Duration::from_secs(DEFAULT_EXPIRY_TIME))
11881189
}
11891190

1191+
/// Returns whether the invoice has expired.
1192+
pub fn is_expired(&self) -> bool {
1193+
Self::is_expired_from_epoch(self.timestamp(), self.expiry_time())
1194+
}
1195+
1196+
/// Returns whether the expiry time from the given epoch has passed.
1197+
pub(crate) fn is_expired_from_epoch(epoch: &SystemTime, expiry_time: Duration) -> bool {
1198+
match epoch.elapsed() {
1199+
Ok(elapsed) => elapsed > expiry_time,
1200+
Err(_) => false,
1201+
}
1202+
}
1203+
11901204
/// Returns the invoice's `min_final_cltv_expiry` time, if present, otherwise
11911205
/// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY`].
11921206
pub fn min_final_cltv_expiry(&self) -> u64 {
@@ -1219,8 +1233,13 @@ impl Invoice {
12191233
self.signed_invoice.currency()
12201234
}
12211235

1236+
/// Returns the amount if specified in the invoice as millisatoshis.
1237+
pub fn amount_milli_satoshis(&self) -> Option<u64> {
1238+
self.signed_invoice.amount_pico_btc().map(|v| v / 10)
1239+
}
1240+
12221241
/// Returns the amount if specified in the invoice as pico <currency>.
1223-
pub fn amount_pico_btc(&self) -> Option<u64> {
1242+
fn amount_pico_btc(&self) -> Option<u64> {
12241243
self.signed_invoice.amount_pico_btc()
12251244
}
12261245
}
@@ -1867,6 +1886,7 @@ mod test {
18671886
assert!(invoice.check_signature().is_ok());
18681887
assert_eq!(invoice.tagged_fields().count(), 10);
18691888

1889+
assert_eq!(invoice.amount_milli_satoshis(), Some(123));
18701890
assert_eq!(invoice.amount_pico_btc(), Some(1230));
18711891
assert_eq!(invoice.currency(), Currency::BitcoinTestnet);
18721892
assert_eq!(
@@ -1913,5 +1933,33 @@ mod test {
19131933

19141934
assert_eq!(invoice.min_final_cltv_expiry(), DEFAULT_MIN_FINAL_CLTV_EXPIRY);
19151935
assert_eq!(invoice.expiry_time(), Duration::from_secs(DEFAULT_EXPIRY_TIME));
1936+
assert!(!invoice.is_expired());
1937+
}
1938+
1939+
#[test]
1940+
fn test_expiration() {
1941+
use ::*;
1942+
use secp256k1::Secp256k1;
1943+
use secp256k1::key::SecretKey;
1944+
1945+
let timestamp = SystemTime::now()
1946+
.checked_sub(Duration::from_secs(DEFAULT_EXPIRY_TIME * 2))
1947+
.unwrap();
1948+
let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin)
1949+
.description("Test".into())
1950+
.payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
1951+
.payment_secret(PaymentSecret([0; 32]))
1952+
.timestamp(timestamp)
1953+
.build_raw()
1954+
.unwrap()
1955+
.sign::<_, ()>(|hash| {
1956+
let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
1957+
let secp_ctx = Secp256k1::new();
1958+
Ok(secp_ctx.sign_recoverable(hash, &privkey))
1959+
})
1960+
.unwrap();
1961+
let invoice = Invoice::from_signed(signed_invoice).unwrap();
1962+
1963+
assert!(invoice.is_expired());
19161964
}
19171965
}

0 commit comments

Comments
 (0)