X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-invoice%2Fsrc%2Futils.rs;h=ef95b3e355b5abd1c91303e3e708b2014041482a;hb=d29ae1826e1d3fe39f65474532f8788413ce8737;hp=1aa3a8923d24c41841b3a2685b1d8bd5ae4dfc82;hpb=3086bd8c8e3f4c1d2c5fa99279f516817ce05587;p=rust-lightning diff --git a/lightning-invoice/src/utils.rs b/lightning-invoice/src/utils.rs index 1aa3a892..ef95b3e3 100644 --- a/lightning-invoice/src/utils.rs +++ b/lightning-invoice/src/utils.rs @@ -1,10 +1,11 @@ //! Convenient utilities to create an invoice. -use {Currency, DEFAULT_EXPIRY_TIME, Invoice, InvoiceBuilder, SignOrCreationError, RawInvoice}; +use {CreationError, Currency, DEFAULT_EXPIRY_TIME, Invoice, InvoiceBuilder, SignOrCreationError}; use payment::{Payer, Router}; use bech32::ToBase32; use bitcoin_hashes::Hash; +use crate::prelude::*; use lightning::chain; use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use lightning::chain::keysinterface::{Sign, KeysInterface}; @@ -16,9 +17,11 @@ 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; +use core::convert::TryInto; +use core::ops::Deref; +use core::time::Duration; +#[cfg(feature = "std")] /// Utility to construct an invoice. Generally, unless you want to do something like a custom /// cltv_expiry, this is what you should be using to create an invoice. The reason being, this /// method stores the invoice's payment secret and preimage in `ChannelManager`, so (a) the user @@ -28,6 +31,33 @@ pub fn create_invoice_from_channelmanager, keys_manager: K, network: Currency, amt_msat: Option, description: String ) -> Result> +where + M::Target: chain::Watch, + T::Target: BroadcasterInterface, + K::Target: KeysInterface, + F::Target: FeeEstimator, + L::Target: Logger, +{ + use std::time::SystemTime; + let duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) + .expect("for the foreseeable future this shouldn't happen"); + create_invoice_from_channelmanager_and_duration_since_epoch( + channelmanager, + keys_manager, + network, + amt_msat, + description, + duration + ) +} + +/// See [`create_invoice_from_channelmanager`] +/// This version can be used in a `no_std` environment, where [`std::time::SystemTime`] is not +/// available and the current time is supplied by the caller. +pub fn create_invoice_from_channelmanager_and_duration_since_epoch( + channelmanager: &ChannelManager, keys_manager: K, network: Currency, + amt_msat: Option, description: String, duration_since_epoch: Duration, +) -> Result> where M::Target: chain::Watch, T::Target: BroadcasterInterface, @@ -60,14 +90,15 @@ where }])); } + // `create_inbound_payment` only returns an error if the amount is greater than the total bitcoin + // supply. let (payment_hash, payment_secret) = channelmanager.create_inbound_payment( - amt_msat, - DEFAULT_EXPIRY_TIME.try_into().unwrap(), - ); + amt_msat, DEFAULT_EXPIRY_TIME.try_into().unwrap()) + .map_err(|()| SignOrCreationError::CreationError(CreationError::InvalidAmount))?; let our_node_pubkey = channelmanager.get_our_node_id(); let mut invoice = InvoiceBuilder::new(network) .description(description) - .current_timestamp() + .duration_since_epoch(duration_since_epoch) .payee_pub_key(our_node_pubkey) .payment_hash(Hash::from_slice(&payment_hash.0).unwrap()) .payment_secret(payment_secret) @@ -87,8 +118,7 @@ where let hrp_str = raw_invoice.hrp.to_string(); let hrp_bytes = hrp_str.as_bytes(); let data_without_signature = raw_invoice.data.to_base32(); - let invoice_preimage = RawInvoice::construct_invoice_preimage(hrp_bytes, &data_without_signature); - let signed_raw_invoice = raw_invoice.sign(|_| keys_manager.sign_invoice(invoice_preimage)); + let signed_raw_invoice = raw_invoice.sign(|_| keys_manager.sign_invoice(hrp_bytes, &data_without_signature)); match signed_raw_invoice { Ok(inv) => Ok(Invoice::from_signed(inv).unwrap()), Err(e) => Err(SignOrCreationError::SignError(e)) @@ -96,20 +126,20 @@ where } /// A [`Router`] implemented using [`find_route`]. -pub struct DefaultRouter where G: Deref, L::Target: Logger { +pub struct DefaultRouter, L: Deref> where L::Target: Logger { network_graph: G, logger: L, } -impl DefaultRouter where G: Deref, L::Target: Logger { +impl, L: Deref> DefaultRouter where 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 { +impl, L: Deref, S: Score> Router for DefaultRouter +where L::Target: Logger { fn find_route( &self, payer: &PublicKey, params: &RouteParameters, _payment_hash: &PaymentHash, first_hops: Option<&[&ChannelDetails]>, scorer: &S @@ -160,15 +190,18 @@ where #[cfg(test)] mod test { + use core::time::Duration; use {Currency, Description, InvoiceDescription}; use lightning::ln::PaymentHash; use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY; use lightning::ln::functional_test_utils::*; use lightning::ln::features::InitFeatures; use lightning::ln::msgs::ChannelMessageHandler; - use lightning::routing::router::{Payee, RouteParameters, find_route}; + use lightning::routing::router::{PaymentParameters, RouteParameters, find_route}; use lightning::util::events::MessageSendEventsProvider; use lightning::util::test_utils; + use utils::create_invoice_from_channelmanager_and_duration_since_epoch; + #[test] fn test_from_channelmanager() { let chanmon_cfgs = create_chanmon_cfgs(2); @@ -176,25 +209,27 @@ mod test { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let _chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); - let invoice = ::utils::create_invoice_from_channelmanager(&nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000), "test".to_string()).unwrap(); + let invoice = create_invoice_from_channelmanager_and_duration_since_epoch( + &nodes[1].node, nodes[1].keys_manager, Currency::BitcoinTestnet, Some(10_000), "test".to_string(), + Duration::from_secs(1234567)).unwrap(); assert_eq!(invoice.amount_pico_btc(), Some(100_000)); assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64); assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string()))); - let payee = Payee::from_node_id(invoice.recover_payee_pub_key()) + let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key()) .with_features(invoice.features().unwrap().clone()) .with_route_hints(invoice.route_hints()); - let params = RouteParameters { - payee, + let route_params = RouteParameters { + payment_params, 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 = node_cfgs[0].network_graph; let logger = test_utils::TestLogger::new(); - let scorer = test_utils::TestScorer::with_fixed_penalty(0); + let scorer = test_utils::TestScorer::with_penalty(0); let route = find_route( - &nodes[0].node.get_our_node_id(), ¶ms, network_graph, + &nodes[0].node.get_our_node_id(), &route_params, network_graph, Some(&first_hops.iter().collect::>()), &logger, &scorer, ).unwrap();