X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Foutbound_payment.rs;h=d615c447e65295d4fe9e678b32ad007f1b46036c;hb=a8bd4c097f7ae6620eee66c1cb49144e38568439;hp=79b743f167568a15e633536589c151b8a06a050a;hpb=e818c4b13fcfc125dd3f3f1e86b49ddf299a85b4;p=rust-lightning diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 79b743f1..d615c447 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -17,6 +17,7 @@ use crate::sign::{EntropySource, NodeSigner, Recipient}; use crate::events::{self, PaymentFailureReason}; use crate::ln::types::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::ln::channelmanager::{ChannelDetails, 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}; @@ -421,6 +422,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 @@ -659,7 +666,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, @@ -711,7 +718,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 +763,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), @@ -886,7 +893,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 +914,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 +948,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 +1107,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 +1218,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)), @@ -1309,7 +1327,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 +1382,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 +1467,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,7 +1850,7 @@ 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; @@ -2194,7 +2213,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() @@ -2237,7 +2256,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() @@ -2296,7 +2315,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()