X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-invoice%2Fsrc%2Futils.rs;h=8da9994a3f7729ea1df9c407dd567fc811782d6a;hb=61341df39e90de9d650851a624c0644f5c9dd055;hp=3b97a8bb81a8c97d7058cf2027b8a06620cbe453;hpb=7297e138716ec34147e591e125a96aa8a2cb2903;p=rust-lightning diff --git a/lightning-invoice/src/utils.rs b/lightning-invoice/src/utils.rs index 3b97a8bb..8da9994a 100644 --- a/lightning-invoice/src/utils.rs +++ b/lightning-invoice/src/utils.rs @@ -1,14 +1,22 @@ //! Convenient utilities to create an invoice. -use {Currency, Invoice, InvoiceBuilder, SignOrCreationError, RawInvoice}; + +use {Currency, DEFAULT_EXPIRY_TIME, Invoice, InvoiceBuilder, SignOrCreationError, RawInvoice}; +use payment::{Payer, Router}; + use bech32::ToBase32; use bitcoin_hashes::Hash; use lightning::chain; use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use lightning::chain::keysinterface::{Sign, KeysInterface}; -use lightning::ln::channelmanager::{ChannelManager, MIN_FINAL_CLTV_EXPIRY}; -use lightning::routing::network_graph::RoutingFees; -use lightning::routing::router::RouteHintHop; +use lightning::ln::{PaymentHash, PaymentSecret}; +use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, PaymentId, PaymentSendFailure, MIN_FINAL_CLTV_EXPIRY}; +use lightning::ln::msgs::LightningError; +use lightning::routing; +use lightning::routing::network_graph::{NetworkGraph, RoutingFees}; +use lightning::routing::router::{Route, RouteHint, RouteHintHop, RouteParameters, find_route}; use lightning::util::logger::Logger; +use secp256k1::key::PublicKey; +use std::convert::TryInto; use std::ops::Deref; /// Utility to construct an invoice. Generally, unless you want to do something like a custom @@ -35,12 +43,12 @@ where Some(id) => id, None => continue, }; - let forwarding_info = match channel.counterparty_forwarding_info { + let forwarding_info = match channel.counterparty.forwarding_info { Some(info) => info, None => continue, }; - route_hints.push(vec![RouteHintHop { - src_node_id: channel.remote_network_id, + route_hints.push(RouteHint(vec![RouteHintHop { + src_node_id: channel.counterparty.node_id, short_channel_id, fees: RoutingFees { base_msat: forwarding_info.fee_base_msat, @@ -49,12 +57,12 @@ where cltv_expiry_delta: forwarding_info.cltv_expiry_delta, htlc_minimum_msat: None, htlc_maximum_msat: None, - }]); + }])); } let (payment_hash, payment_secret) = channelmanager.create_inbound_payment( amt_msat, - 7200, // default invoice expiry is 2 hours + DEFAULT_EXPIRY_TIME.try_into().unwrap(), 0, ); let our_node_pubkey = channelmanager.get_our_node_id(); @@ -67,10 +75,10 @@ where .basic_mpp() .min_final_cltv_expiry(MIN_FINAL_CLTV_EXPIRY.into()); if let Some(amt) = amt_msat { - invoice = invoice.amount_pico_btc(amt * 10); + invoice = invoice.amount_milli_satoshis(amt); } - for hint in route_hints.drain(..) { - invoice = invoice.route(hint); + for hint in route_hints { + invoice = invoice.private_route(hint); } let raw_invoice = match invoice.build_raw() { @@ -88,6 +96,58 @@ where } } +/// A [`Router`] implemented using [`find_route`]. +pub struct DefaultRouter where G: Deref, L::Target: Logger { + network_graph: G, + logger: L, +} + +impl DefaultRouter where G: Deref, L::Target: Logger { + /// Creates a new router using the given [`NetworkGraph`] and [`Logger`]. + pub fn new(network_graph: G, logger: L) -> Self { + Self { network_graph, logger } + } +} + +impl Router for DefaultRouter +where G: Deref, L::Target: Logger { + fn find_route( + &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, + scorer: &S + ) -> Result { + find_route(payer, params, &*self.network_graph, first_hops, &*self.logger, scorer) + } +} + +impl Payer for ChannelManager +where + M::Target: chain::Watch, + T::Target: BroadcasterInterface, + K::Target: KeysInterface, + F::Target: FeeEstimator, + L::Target: Logger, +{ + fn node_id(&self) -> PublicKey { + self.get_our_node_id() + } + + fn first_hops(&self) -> Vec { + self.list_usable_channels() + } + + fn send_payment( + &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option + ) -> Result { + self.send_payment(route, payment_hash, payment_secret) + } + + fn retry_payment( + &self, route: &Route, payment_id: PaymentId + ) -> Result<(), PaymentSendFailure> { + self.retry_payment(route, payment_id) + } +} + #[cfg(test)] mod test { use {Currency, Description, InvoiceDescription}; @@ -96,7 +156,8 @@ mod test { use lightning::ln::functional_test_utils::*; use lightning::ln::features::InitFeatures; use lightning::ln::msgs::ChannelMessageHandler; - use lightning::routing::router; + use lightning::routing::router::{Payee, RouteParameters, find_route}; + use lightning::routing::scorer::Scorer; use lightning::util::events::MessageSendEventsProvider; use lightning::util::test_utils; #[test] @@ -111,32 +172,27 @@ mod test { assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64); assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string()))); - let mut route_hints = invoice.routes().clone(); - let mut last_hops = Vec::new(); - for hint in route_hints.drain(..) { - last_hops.push(hint[hint.len() - 1].clone()); - } - let amt_msat = invoice.amount_pico_btc().unwrap() / 10; - + let payee = Payee::new(invoice.recover_payee_pub_key()) + .with_features(invoice.features().unwrap().clone()) + .with_route_hints(invoice.route_hints()); + let params = RouteParameters { + payee, + final_value_msat: invoice.amount_milli_satoshis().unwrap(), + final_cltv_expiry_delta: invoice.min_final_cltv_expiry() as u32, + }; let first_hops = nodes[0].node.list_usable_channels(); - let network_graph = nodes[0].net_graph_msg_handler.network_graph.read().unwrap(); + let network_graph = &nodes[0].net_graph_msg_handler.network_graph; let logger = test_utils::TestLogger::new(); - let route = router::get_route( - &nodes[0].node.get_our_node_id(), - &network_graph, - &invoice.recover_payee_pub_key(), - Some(invoice.features().unwrap().clone()), - Some(&first_hops.iter().collect::>()), - &last_hops.iter().collect::>(), - amt_msat, - invoice.min_final_cltv_expiry() as u32, - &logger, + let scorer = Scorer::with_fixed_penalty(0); + let route = find_route( + &nodes[0].node.get_our_node_id(), ¶ms, network_graph, + Some(&first_hops.iter().collect::>()), &logger, &scorer, ).unwrap(); let payment_event = { let mut payment_hash = PaymentHash([0; 32]); payment_hash.0.copy_from_slice(&invoice.payment_hash().as_ref()[0..32]); - nodes[0].node.send_payment(&route, payment_hash, &Some(invoice.payment_secret().unwrap().clone())).unwrap(); + nodes[0].node.send_payment(&route, payment_hash, &Some(invoice.payment_secret().clone())).unwrap(); let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); assert_eq!(added_monitors.len(), 1); added_monitors.clear();