Upgrade rust-bitcoin to 0.31
[rust-lightning] / lightning / src / ln / outbound_payment.rs
index b05d6f3f7290110b5aed103faef370203350a8fc..d615c447e65295d4fe9e678b32ad007f1b46036c 100644 (file)
@@ -15,8 +15,9 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
 
 use crate::sign::{EntropySource, NodeSigner, Recipient};
 use crate::events::{self, PaymentFailureReason};
-use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
+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<R: Deref, NS: Deref, ES: Deref, IH, SP, L: Deref>(
                &self, payment_id: PaymentId, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
-               keysend_preimage: Option<PaymentPreimage>, retry_strategy: Retry, route_params: RouteParameters,
+               keysend_preimage: Option<PaymentPreimage>, retry_strategy: Retry, mut route_params: RouteParameters,
                router: &R, first_hops: Vec<ChannelDetails>, inflight_htlcs: IH, entropy_source: &ES,
                node_signer: &NS, best_block_height: u32, logger: &L,
                pending_events: &Mutex<VecDeque<(events::Event, Option<EventCompletionAction>)>>, 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::<Vec<_>>()), 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<NS: Deref, F>(
-               &self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
+               &self, route: &Route, payment_hash: PaymentHash, recipient_onion: &RecipientOnionFields,
                keysend_preimage: Option<PaymentPreimage>, payment_id: PaymentId, recv_value_msat: Option<u64>,
                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,13 +1850,13 @@ 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::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};
@@ -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()