X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Foutbound_payment.rs;h=1915a4c5a14db61b4fe00c5ace6f36203f5791c2;hb=642913c586fc71b0e413532e7dedcd19cfd4815c;hp=47193bea3f197b2fcd41d261202c612c5f06526a;hpb=871db638f23867006b4b7ec941a92b6709ccab9e;p=rust-lightning diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 47193bea..1915a4c5 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -13,17 +13,21 @@ use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1::{self, Secp256k1, SecretKey}; -use crate::sign::{EntropySource, NodeSigner, Recipient}; +use crate::blinded_path::{IntroductionNode, NodeIdLookUp}; +use crate::blinded_path::payment::advance_path_by_one; use crate::events::{self, PaymentFailureReason}; -use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; -use crate::ln::channelmanager::{ChannelDetails, EventCompletionAction, HTLCSource, PaymentId}; +use crate::ln::types::{PaymentHash, PaymentPreimage, PaymentSecret}; +use crate::ln::channel_state::ChannelDetails; +use crate::ln::channelmanager::{EventCompletionAction, HTLCSource, PaymentId}; +use crate::ln::onion_utils; use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason}; use crate::offers::invoice::Bolt12Invoice; use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router}; +use crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::util::errors::APIError; use crate::util::logger::Logger; use crate::util::time::Time; -#[cfg(all(not(feature = "no-std"), test))] +#[cfg(all(feature = "std", test))] use crate::util::time::tests::SinceEpoch; use crate::util::ser::ReadableArgs; @@ -69,7 +73,7 @@ pub(crate) enum PendingOutboundPayment { keysend_preimage: Option, custom_tlvs: Vec<(u64, Vec)>, pending_amt_msat: u64, - /// Used to track the fee paid. Only present if the payment was serialized on 0.0.103+. + /// Used to track the fee paid. Present iff the payment was serialized on 0.0.103+. pending_fee_msat: Option, /// The total payment amount across all paths, used to verify that a retry is not overpaying. total_msat: u64, @@ -171,7 +175,7 @@ impl PendingOutboundPayment { } fn mark_fulfilled(&mut self) { - let mut session_privs = HashSet::new(); + let mut session_privs = new_hash_set(); core::mem::swap(&mut session_privs, match self { PendingOutboundPayment::Legacy { session_privs } | PendingOutboundPayment::Retryable { session_privs, .. } | @@ -186,7 +190,7 @@ impl PendingOutboundPayment { fn mark_abandoned(&mut self, reason: PaymentFailureReason) { if let PendingOutboundPayment::Retryable { session_privs, payment_hash, .. } = self { - let mut our_session_privs = HashSet::new(); + let mut our_session_privs = new_hash_set(); core::mem::swap(&mut our_session_privs, session_privs); *self = PendingOutboundPayment::Abandoned { session_privs: our_session_privs, @@ -195,7 +199,7 @@ impl PendingOutboundPayment { }; } else if let PendingOutboundPayment::InvoiceReceived { payment_hash, .. } = self { *self = PendingOutboundPayment::Abandoned { - session_privs: HashSet::new(), + session_privs: new_hash_set(), payment_hash: *payment_hash, reason: Some(reason) }; @@ -287,7 +291,7 @@ pub enum Retry { /// retry, and may retry multiple failed HTLCs at once if they failed around the same time and /// were retried along a route from a single call to [`Router::find_route_with_id`]. Attempts(u32), - #[cfg(not(feature = "no-std"))] + #[cfg(feature = "std")] /// Time elapsed before abandoning retries for a payment. At least one attempt at payment is made; /// see [`PaymentParameters::expiry_time`] to avoid any attempt at payment after a specific time. /// @@ -295,13 +299,13 @@ pub enum Retry { Timeout(core::time::Duration), } -#[cfg(feature = "no-std")] +#[cfg(not(feature = "std"))] impl_writeable_tlv_based_enum!(Retry, ; (0, Attempts) ); -#[cfg(not(feature = "no-std"))] +#[cfg(feature = "std")] impl_writeable_tlv_based_enum!(Retry, ; (0, Attempts), @@ -314,10 +318,10 @@ impl Retry { (Retry::Attempts(max_retry_count), PaymentAttempts { count, .. }) => { max_retry_count > count }, - #[cfg(all(not(feature = "no-std"), not(test)))] + #[cfg(all(feature = "std", not(test)))] (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => *max_duration >= crate::util::time::MonotonicTime::now().duration_since(*first_attempted_at), - #[cfg(all(not(feature = "no-std"), test))] + #[cfg(all(feature = "std", test))] (Retry::Timeout(max_duration), PaymentAttempts { first_attempted_at, .. }) => *max_duration >= SinceEpoch::now().duration_since(*first_attempted_at), } @@ -343,27 +347,27 @@ pub(crate) struct PaymentAttemptsUsingTime { /// it means the result of the first attempt is not known yet. pub(crate) count: u32, /// This field is only used when retry is `Retry::Timeout` which is only build with feature std - #[cfg(not(feature = "no-std"))] + #[cfg(feature = "std")] first_attempted_at: T, - #[cfg(feature = "no-std")] + #[cfg(not(feature = "std"))] phantom: core::marker::PhantomData, } -#[cfg(not(any(feature = "no-std", test)))] -type ConfiguredTime = crate::util::time::MonotonicTime; -#[cfg(feature = "no-std")] +#[cfg(not(feature = "std"))] type ConfiguredTime = crate::util::time::Eternity; -#[cfg(all(not(feature = "no-std"), test))] +#[cfg(all(feature = "std", not(test)))] +type ConfiguredTime = crate::util::time::MonotonicTime; +#[cfg(all(feature = "std", test))] type ConfiguredTime = SinceEpoch; impl PaymentAttemptsUsingTime { pub(crate) fn new() -> Self { PaymentAttemptsUsingTime { count: 0, - #[cfg(not(feature = "no-std"))] + #[cfg(feature = "std")] first_attempted_at: T::now(), - #[cfg(feature = "no-std")] + #[cfg(not(feature = "std"))] phantom: core::marker::PhantomData, } } @@ -371,9 +375,9 @@ impl PaymentAttemptsUsingTime { impl Display for PaymentAttemptsUsingTime { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { - #[cfg(feature = "no-std")] + #[cfg(not(feature = "std"))] return write!(f, "attempts: {}", self.count); - #[cfg(not(feature = "no-std"))] + #[cfg(feature = "std")] return write!( f, "attempts: {}, duration: {}s", @@ -421,6 +425,12 @@ pub enum RetryableSendFailure { /// [`Event::PaymentSent`]: crate::events::Event::PaymentSent /// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed DuplicatePayment, + /// The [`RecipientOnionFields::payment_metadata`], [`RecipientOnionFields::custom_tlvs`], or + /// [`BlindedPath`]s provided are too large and caused us to exceed the maximum onion packet size + /// of 1300 bytes. + /// + /// [`BlindedPath`]: crate::blinded_path::BlindedPath + OnionPacketSizeExceeded, } /// If a payment fails to send with [`ChannelManager::send_payment_with_route`], it can be in one @@ -493,9 +503,9 @@ pub enum PaymentSendFailure { }, } -/// An error when attempting to pay a BOLT 12 invoice. +/// An error when attempting to pay a [`Bolt12Invoice`]. #[derive(Clone, Debug, PartialEq, Eq)] -pub(super) enum Bolt12PaymentError { +pub enum Bolt12PaymentError { /// The invoice was not requested. UnexpectedInvoice, /// Payment for an invoice with the corresponding [`PaymentId`] was already initiated. @@ -659,7 +669,7 @@ impl RecipientOnionFields { pub(super) struct SendAlongPathArgs<'a> { pub path: &'a Path, pub payment_hash: &'a PaymentHash, - pub recipient_onion: RecipientOnionFields, + pub recipient_onion: &'a RecipientOnionFields, pub total_value: u64, pub cur_height: u32, pub payment_id: PaymentId, @@ -675,7 +685,7 @@ pub(super) struct OutboundPayments { impl OutboundPayments { pub(super) fn new() -> Self { Self { - pending_outbound_payments: Mutex::new(HashMap::new()), + pending_outbound_payments: Mutex::new(new_hash_map()), retry_lock: Mutex::new(()), } } @@ -711,7 +721,7 @@ impl OutboundPayments { F: Fn(SendAlongPathArgs) -> Result<(), APIError> { let onion_session_privs = self.add_new_pending_payment(payment_hash, recipient_onion.clone(), payment_id, None, route, None, None, entropy_source, best_block_height)?; - self.pay_route_internal(route, payment_hash, recipient_onion, None, payment_id, None, + self.pay_route_internal(route, payment_hash, &recipient_onion, None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path) .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e }) } @@ -756,7 +766,7 @@ impl OutboundPayments { let onion_session_privs = self.add_new_pending_payment(payment_hash, recipient_onion.clone(), payment_id, Some(preimage), &route, None, None, entropy_source, best_block_height)?; - match self.pay_route_internal(route, payment_hash, recipient_onion, Some(preimage), + match self.pay_route_internal(route, payment_hash, &recipient_onion, Some(preimage), payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path ) { Ok(()) => Ok(payment_hash), @@ -767,10 +777,13 @@ impl OutboundPayments { } } - pub(super) fn send_payment_for_bolt12_invoice( + pub(super) fn send_payment_for_bolt12_invoice< + R: Deref, ES: Deref, NS: Deref, NL: Deref, IH, SP, L: Deref + >( &self, invoice: &Bolt12Invoice, payment_id: PaymentId, router: &R, first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, - best_block_height: u32, logger: &L, + node_id_lookup: &NL, secp_ctx: &Secp256k1, best_block_height: u32, + logger: &L, pending_events: &Mutex)>>, send_payment_along_path: SP, ) -> Result<(), Bolt12PaymentError> @@ -778,6 +791,7 @@ impl OutboundPayments { R::Target: Router, ES::Target: EntropySource, NS::Target: NodeSigner, + NL::Target: NodeIdLookUp, L::Target: Logger, IH: Fn() -> InFlightHtlcs, SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, @@ -799,9 +813,30 @@ impl OutboundPayments { hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice), }; - let pay_params = PaymentParameters::from_bolt12_invoice(&invoice); + let mut payment_params = PaymentParameters::from_bolt12_invoice(&invoice); + + // Advance any blinded path where the introduction node is our node. + if let Ok(our_node_id) = node_signer.get_node_id(Recipient::Node) { + for (_, path) in payment_params.payee.blinded_route_hints_mut().iter_mut() { + let introduction_node_id = match path.introduction_node { + IntroductionNode::NodeId(pubkey) => pubkey, + IntroductionNode::DirectedShortChannelId(direction, scid) => { + match node_id_lookup.next_node_id(scid) { + Some(next_node_id) => *direction.select_pubkey(&our_node_id, &next_node_id), + None => continue, + } + }, + }; + if introduction_node_id == our_node_id { + let _ = advance_path_by_one(path, node_signer, node_id_lookup, secp_ctx); + } + } + } + let amount_msat = invoice.amount_msats(); - let mut route_params = RouteParameters::from_payment_params_and_value(pay_params, amount_msat); + let mut route_params = RouteParameters::from_payment_params_and_value( + payment_params, amount_msat + ); if let Some(max_fee_msat) = max_total_routing_fee_msat { route_params.max_total_routing_fee_msat = Some(max_fee_msat); } @@ -886,7 +921,7 @@ impl OutboundPayments { /// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed fn send_payment_internal( &self, payment_id: PaymentId, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, - keysend_preimage: Option, retry_strategy: Retry, route_params: RouteParameters, + keysend_preimage: Option, retry_strategy: Retry, mut route_params: RouteParameters, router: &R, first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, pending_events: &Mutex)>>, send_payment_along_path: SP, @@ -907,6 +942,15 @@ impl OutboundPayments { } } + onion_utils::set_max_path_length( + &mut route_params, &recipient_onion, keysend_preimage, best_block_height + ) + .map_err(|()| { + log_error!(logger, "Can't construct an onion packet without exceeding 1300-byte onion \ + hop_data length for payment with id {} and hash {}", payment_id, payment_hash); + RetryableSendFailure::OnionPacketSizeExceeded + })?; + let mut route = router.find_route_with_id( &node_signer.get_node_id(Recipient::Node).unwrap(), &route_params, Some(&first_hops.iter().collect::>()), inflight_htlcs(), @@ -932,8 +976,9 @@ impl OutboundPayments { RetryableSendFailure::DuplicatePayment })?; - let res = self.pay_route_internal(&route, payment_hash, recipient_onion, keysend_preimage, payment_id, None, - onion_session_privs, node_signer, best_block_height, &send_payment_along_path); + let res = self.pay_route_internal(&route, payment_hash, &recipient_onion, + keysend_preimage, payment_id, None, onion_session_privs, node_signer, + best_block_height, &send_payment_along_path); log_info!(logger, "Sending payment with id {} and hash {} returned {:?}", payment_id, payment_hash, res); if let Err(e) = res { @@ -1090,7 +1135,7 @@ impl OutboundPayments { } } }; - let res = self.pay_route_internal(&route, payment_hash, recipient_onion, keysend_preimage, + let res = self.pay_route_internal(&route, payment_hash, &recipient_onion, keysend_preimage, payment_id, Some(total_msat), onion_session_privs, node_signer, best_block_height, &send_payment_along_path); log_info!(logger, "Result retrying payment id {}: {:?}", &payment_id, res); @@ -1201,7 +1246,8 @@ impl OutboundPayments { RecipientOnionFields::secret_only(payment_secret), payment_id, None, &route, None, None, entropy_source, best_block_height)?; - match self.pay_route_internal(&route, payment_hash, RecipientOnionFields::spontaneous_empty(), + let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(); + match self.pay_route_internal(&route, payment_hash, &recipient_onion_fields, None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path ) { Ok(()) => Ok((payment_hash, payment_id)), @@ -1268,7 +1314,7 @@ impl OutboundPayments { retry_strategy, attempts: PaymentAttempts::new(), payment_params, - session_privs: HashSet::new(), + session_privs: new_hash_set(), pending_amt_msat: 0, pending_fee_msat: Some(0), payment_hash, @@ -1309,7 +1355,7 @@ impl OutboundPayments { } fn pay_route_internal( - &self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, + &self, route: &Route, payment_hash: PaymentHash, recipient_onion: &RecipientOnionFields, keysend_preimage: Option, payment_id: PaymentId, recv_value_msat: Option, onion_session_privs: Vec<[u8; 32]>, node_signer: &NS, best_block_height: u32, send_payment_along_path: &F @@ -1364,8 +1410,9 @@ impl OutboundPayments { debug_assert_eq!(route.paths.len(), onion_session_privs.len()); for (path, session_priv_bytes) in route.paths.iter().zip(onion_session_privs.into_iter()) { let mut path_res = send_payment_along_path(SendAlongPathArgs { - path: &path, payment_hash: &payment_hash, recipient_onion: recipient_onion.clone(), - total_value, cur_height, payment_id, keysend_preimage: &keysend_preimage, session_priv_bytes + path: &path, payment_hash: &payment_hash, recipient_onion, total_value, + cur_height, payment_id, keysend_preimage: &keysend_preimage, + session_priv_bytes }); match path_res { Ok(_) => {}, @@ -1448,9 +1495,9 @@ impl OutboundPayments { NS::Target: NodeSigner, F: Fn(SendAlongPathArgs) -> Result<(), APIError>, { - self.pay_route_internal(route, payment_hash, recipient_onion, keysend_preimage, payment_id, - recv_value_msat, onion_session_privs, node_signer, best_block_height, - &send_payment_along_path) + self.pay_route_internal(route, payment_hash, &recipient_onion, + keysend_preimage, payment_id, recv_value_msat, onion_session_privs, + node_signer, best_block_height, &send_payment_along_path) .map_err(|e| { self.remove_outbound_if_all_failed(payment_id, &e); e }) } @@ -1831,13 +1878,14 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment, #[cfg(test)] mod tests { - use bitcoin::network::constants::Network; + use bitcoin::network::Network; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; use core::time::Duration; + use crate::blinded_path::EmptyNodeIdLookUp; use crate::events::{Event, PathFailure, PaymentFailureReason}; - use crate::ln::PaymentHash; + use crate::ln::types::PaymentHash; use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; use crate::ln::features::{ChannelFeatures, NodeFeatures}; use crate::ln::msgs::{ErrorAction, LightningError}; @@ -1888,7 +1936,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); @@ -1932,7 +1980,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); @@ -1971,7 +2019,7 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); @@ -2178,7 +2226,8 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); + let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2194,7 +2243,7 @@ mod tests { assert!(outbound_payments.has_pending_payments()); let created_at = now() - DEFAULT_RELATIVE_EXPIRY; - let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) + let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .build().unwrap() .request_invoice(vec![1; 32], payer_pubkey()).unwrap() @@ -2207,7 +2256,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| panic!() ), Ok(()), ); @@ -2229,7 +2279,8 @@ mod tests { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); + let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2237,7 +2288,7 @@ mod tests { let payment_id = PaymentId([0; 32]); let expiration = StaleExpiration::AbsoluteTimeout(Duration::from_secs(100)); - let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) + let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .build().unwrap() .request_invoice(vec![1; 32], payer_pubkey()).unwrap() @@ -2266,7 +2317,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| panic!() ), Ok(()), ); @@ -2283,71 +2335,13 @@ mod tests { assert!(pending_events.lock().unwrap().is_empty()); } - #[test] - fn fails_paying_for_bolt12_invoice() { - let logger = test_utils::TestLogger::new(); - let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); - let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); - let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); - - let pending_events = Mutex::new(VecDeque::new()); - let outbound_payments = OutboundPayments::new(); - let payment_id = PaymentId([0; 32]); - let expiration = StaleExpiration::AbsoluteTimeout(Duration::from_secs(100)); - - let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) - .amount_msats(1000) - .build().unwrap() - .request_invoice(vec![1; 32], payer_pubkey()).unwrap() - .build().unwrap() - .sign(payer_sign).unwrap() - .respond_with_no_std(payment_paths(), payment_hash(), now()).unwrap() - .build().unwrap() - .sign(recipient_sign).unwrap(); - - assert!( - outbound_payments.add_new_awaiting_invoice( - payment_id, expiration, Retry::Attempts(0), - Some(invoice.amount_msats() / 100 + 50_000) - ).is_ok() - ); - assert!(outbound_payments.has_pending_payments()); - - let route_params = RouteParameters::from_payment_params_and_value( - PaymentParameters::from_bolt12_invoice(&invoice), - invoice.amount_msats(), - ); - router.expect_find_route( - route_params.clone(), Ok(Route { paths: vec![], route_params: Some(route_params) }) - ); - - assert_eq!( - outbound_payments.send_payment_for_bolt12_invoice( - &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() - ), - Ok(()), - ); - assert!(!outbound_payments.has_pending_payments()); - - let payment_hash = invoice.payment_hash(); - let reason = Some(PaymentFailureReason::UnexpectedError); - - assert!(!pending_events.lock().unwrap().is_empty()); - assert_eq!( - pending_events.lock().unwrap().pop_front(), - Some((Event::PaymentFailed { payment_id, payment_hash, reason }, None)), - ); - assert!(pending_events.lock().unwrap().is_empty()); - } - #[test] fn sends_payment_for_bolt12_invoice() { let logger = test_utils::TestLogger::new(); let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); - let router = test_utils::TestRouter::new(network_graph, &scorer); + let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); + let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2355,7 +2349,7 @@ mod tests { let payment_id = PaymentId([0; 32]); let expiration = StaleExpiration::AbsoluteTimeout(Duration::from_secs(100)); - let invoice = OfferBuilder::new("foo".into(), recipient_pubkey()) + let invoice = OfferBuilder::new(recipient_pubkey()) .amount_msats(1000) .build().unwrap() .request_invoice(vec![1; 32], payer_pubkey()).unwrap() @@ -2397,7 +2391,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::UnexpectedInvoice), ); @@ -2414,7 +2409,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| Ok(()) + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| Ok(()) ), Ok(()), ); @@ -2424,7 +2420,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::DuplicateInvoice), );