Skip to content

Commit

Permalink
Merge pull request #1059 from jkczyz/2021-08-payment-retry
Browse files Browse the repository at this point in the history
Payment Retries
  • Loading branch information
TheBlueMatt committed Oct 27, 2021
2 parents 2ed1ba6 + 010436d commit 59659d3
Show file tree
Hide file tree
Showing 18 changed files with 1,332 additions and 147 deletions.
20 changes: 15 additions & 5 deletions fuzz/src/full_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,Ig
use lightning::ln::msgs::DecodeError;
use lightning::ln::script::ShutdownScript;
use lightning::routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
use lightning::routing::router::{get_route, Payee};
use lightning::routing::router::{find_route, Payee, RouteParameters};
use lightning::routing::scorer::Scorer;
use lightning::util::config::UserConfig;
use lightning::util::errors::APIError;
Expand Down Expand Up @@ -437,9 +437,14 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
}
},
4 => {
let value = slice_to_be24(get_slice!(3)) as u64;
let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
let payee = Payee::new(get_pubkey!());
let route = match get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, value, 42, Arc::clone(&logger), &scorer) {
let params = RouteParameters {
payee,
final_value_msat,
final_cltv_expiry_delta: 42,
};
let route = match find_route(&our_id, &params, &net_graph_msg_handler.network_graph, None, Arc::clone(&logger), &scorer) {
Ok(route) => route,
Err(_) => return,
};
Expand All @@ -455,9 +460,14 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
}
},
15 => {
let value = slice_to_be24(get_slice!(3)) as u64;
let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
let payee = Payee::new(get_pubkey!());
let mut route = match get_route(&our_id, &payee, &net_graph_msg_handler.network_graph, None, value, 42, Arc::clone(&logger), &scorer) {
let params = RouteParameters {
payee,
final_value_msat,
final_cltv_expiry_delta: 42,
};
let mut route = match find_route(&our_id, &params, &net_graph_msg_handler.network_graph, None, Arc::clone(&logger), &scorer) {
Ok(route) => route,
Err(_) => return,
};
Expand Down
12 changes: 8 additions & 4 deletions fuzz/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use lightning::chain::transaction::OutPoint;
use lightning::ln::channelmanager::{ChannelDetails, ChannelCounterparty};
use lightning::ln::features::InitFeatures;
use lightning::ln::msgs;
use lightning::routing::router::{get_route, Payee, RouteHint, RouteHintHop};
use lightning::routing::router::{find_route, Payee, RouteHint, RouteHintHop, RouteParameters};
use lightning::routing::scorer::Scorer;
use lightning::util::logger::Logger;
use lightning::util::ser::Readable;
Expand Down Expand Up @@ -250,10 +250,14 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
}
let scorer = Scorer::new(0);
for target in node_pks.iter() {
let payee = Payee::new(*target).with_route_hints(last_hops.clone());
let _ = get_route(&our_pubkey, &payee, &net_graph,
let params = RouteParameters {
payee: Payee::new(*target).with_route_hints(last_hops.clone()),
final_value_msat: slice_to_be64(get_slice!(8)),
final_cltv_expiry_delta: slice_to_be32(get_slice!(4)),
};
let _ = find_route(&our_pubkey, &params, &net_graph,
first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
slice_to_be64(get_slice!(8)), slice_to_be32(get_slice!(4)), Arc::clone(&logger), &scorer);
Arc::clone(&logger), &scorer);
}
},
}
Expand Down
52 changes: 50 additions & 2 deletions lightning-invoice/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
//! * For parsing use `str::parse::<Invoice>(&self)` (see the docs of `impl FromStr for Invoice`)
//! * For constructing invoices use the `InvoiceBuilder`
//! * For serializing invoices use the `Display`/`ToString` traits
pub mod payment;
pub mod utils;

extern crate bech32;
extern crate bitcoin_hashes;
extern crate lightning;
#[macro_use] extern crate lightning;
extern crate num_traits;
extern crate secp256k1;

Expand Down Expand Up @@ -1187,6 +1188,19 @@ impl Invoice {
.unwrap_or(Duration::from_secs(DEFAULT_EXPIRY_TIME))
}

/// Returns whether the invoice has expired.
pub fn is_expired(&self) -> bool {
Self::is_expired_from_epoch(self.timestamp(), self.expiry_time())
}

/// Returns whether the expiry time from the given epoch has passed.
pub(crate) fn is_expired_from_epoch(epoch: &SystemTime, expiry_time: Duration) -> bool {
match epoch.elapsed() {
Ok(elapsed) => elapsed > expiry_time,
Err(_) => false,
}
}

/// Returns the invoice's `min_final_cltv_expiry` time, if present, otherwise
/// [`DEFAULT_MIN_FINAL_CLTV_EXPIRY`].
pub fn min_final_cltv_expiry(&self) -> u64 {
Expand Down Expand Up @@ -1219,8 +1233,13 @@ impl Invoice {
self.signed_invoice.currency()
}

/// Returns the amount if specified in the invoice as millisatoshis.
pub fn amount_milli_satoshis(&self) -> Option<u64> {
self.signed_invoice.amount_pico_btc().map(|v| v / 10)
}

/// Returns the amount if specified in the invoice as pico <currency>.
pub fn amount_pico_btc(&self) -> Option<u64> {
fn amount_pico_btc(&self) -> Option<u64> {
self.signed_invoice.amount_pico_btc()
}
}
Expand Down Expand Up @@ -1867,6 +1886,7 @@ mod test {
assert!(invoice.check_signature().is_ok());
assert_eq!(invoice.tagged_fields().count(), 10);

assert_eq!(invoice.amount_milli_satoshis(), Some(123));
assert_eq!(invoice.amount_pico_btc(), Some(1230));
assert_eq!(invoice.currency(), Currency::BitcoinTestnet);
assert_eq!(
Expand Down Expand Up @@ -1913,5 +1933,33 @@ mod test {

assert_eq!(invoice.min_final_cltv_expiry(), DEFAULT_MIN_FINAL_CLTV_EXPIRY);
assert_eq!(invoice.expiry_time(), Duration::from_secs(DEFAULT_EXPIRY_TIME));
assert!(!invoice.is_expired());
}

#[test]
fn test_expiration() {
use ::*;
use secp256k1::Secp256k1;
use secp256k1::key::SecretKey;

let timestamp = SystemTime::now()
.checked_sub(Duration::from_secs(DEFAULT_EXPIRY_TIME * 2))
.unwrap();
let signed_invoice = InvoiceBuilder::new(Currency::Bitcoin)
.description("Test".into())
.payment_hash(sha256::Hash::from_slice(&[0;32][..]).unwrap())
.payment_secret(PaymentSecret([0; 32]))
.timestamp(timestamp)
.build_raw()
.unwrap()
.sign::<_, ()>(|hash| {
let privkey = SecretKey::from_slice(&[41; 32]).unwrap();
let secp_ctx = Secp256k1::new();
Ok(secp_ctx.sign_recoverable(hash, &privkey))
})
.unwrap();
let invoice = Invoice::from_signed(signed_invoice).unwrap();

assert!(invoice.is_expired());
}
}

0 comments on commit 59659d3

Please sign in to comment.