From: Matt Corallo Date: Fri, 24 Mar 2023 05:32:56 +0000 (+0000) Subject: Pipe the new `RecipientOnionFields` through send pipeline X-Git-Tag: v0.0.115~33^2~1 X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=36235c38f16dd99f62d1b3eb458d69211e4fdef6;p=rust-lightning Pipe the new `RecipientOnionFields` through send pipeline This passes the new `RecipientOnionFields` through the internal sending APIs, ensuring we have access to the full struct when we go to construct the sending onion so that we can include any new fields added there. --- diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 3ae634a2d..7c84df75e 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -2510,12 +2510,12 @@ where } #[cfg(test)] - pub(crate) fn test_send_payment_along_path(&self, path: &Vec, payment_hash: &PaymentHash, payment_secret: &Option, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option, session_priv_bytes: [u8; 32]) -> Result<(), APIError> { + pub(crate) fn test_send_payment_along_path(&self, path: &Vec, payment_hash: &PaymentHash, recipient_onion: RecipientOnionFields, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option, session_priv_bytes: [u8; 32]) -> Result<(), APIError> { let _lck = self.total_consistency_lock.read().unwrap(); - self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv_bytes) + self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv_bytes) } - fn send_payment_along_path(&self, path: &Vec, payment_hash: &PaymentHash, payment_secret: &Option, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option, session_priv_bytes: [u8; 32]) -> Result<(), APIError> { + fn send_payment_along_path(&self, path: &Vec, payment_hash: &PaymentHash, recipient_onion: RecipientOnionFields, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option, session_priv_bytes: [u8; 32]) -> Result<(), APIError> { // The top-level caller should hold the total_consistency_lock read lock. debug_assert!(self.total_consistency_lock.try_write().is_err()); @@ -2525,7 +2525,7 @@ where let onion_keys = onion_utils::construct_onion_keys(&self.secp_ctx, &path, &session_priv) .map_err(|_| APIError::InvalidRoute{err: "Pubkey along hop was maliciously selected".to_owned()})?; - let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, payment_secret, cur_height, keysend_preimage)?; + let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, recipient_onion, cur_height, keysend_preimage)?; if onion_utils::route_size_insane(&onion_payloads) { return Err(APIError::InvalidRoute{err: "Route size too large considering onion data".to_owned()}); } @@ -2646,9 +2646,9 @@ where let best_block_height = self.best_block.read().unwrap().height(); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); self.pending_outbound_payments - .send_payment_with_route(route, payment_hash, &recipient_onion.payment_secret, payment_id, &self.entropy_source, &self.node_signer, best_block_height, - |path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv| - self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv)) + .send_payment_with_route(route, payment_hash, recipient_onion, payment_id, &self.entropy_source, &self.node_signer, best_block_height, + |path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv| + self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv)) } /// Similar to [`ChannelManager::send_payment`], but will automatically find a route based on @@ -2657,27 +2657,27 @@ where let best_block_height = self.best_block.read().unwrap().height(); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); self.pending_outbound_payments - .send_payment(payment_hash, &recipient_onion.payment_secret, payment_id, retry_strategy, route_params, + .send_payment(payment_hash, recipient_onion, payment_id, retry_strategy, route_params, &self.router, self.list_usable_channels(), || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height, &self.logger, &self.pending_events, - |path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv| - self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv)) + |path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv| + self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv)) } #[cfg(test)] - pub(super) fn test_send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option, keysend_preimage: Option, payment_id: PaymentId, recv_value_msat: Option, onion_session_privs: Vec<[u8; 32]>) -> Result<(), PaymentSendFailure> { + pub(super) fn test_send_payment_internal(&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]>) -> Result<(), PaymentSendFailure> { let best_block_height = self.best_block.read().unwrap().height(); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); - self.pending_outbound_payments.test_send_payment_internal(route, payment_hash, payment_secret, keysend_preimage, payment_id, recv_value_msat, onion_session_privs, &self.node_signer, best_block_height, - |path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv| - self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv)) + self.pending_outbound_payments.test_send_payment_internal(route, payment_hash, recipient_onion, keysend_preimage, payment_id, recv_value_msat, onion_session_privs, &self.node_signer, best_block_height, + |path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv| + self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv)) } #[cfg(test)] - pub(crate) fn test_add_new_pending_payment(&self, payment_hash: PaymentHash, payment_secret: Option, payment_id: PaymentId, route: &Route) -> Result, PaymentSendFailure> { + pub(crate) fn test_add_new_pending_payment(&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route: &Route) -> Result, PaymentSendFailure> { let best_block_height = self.best_block.read().unwrap().height(); - self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, payment_secret, payment_id, route, None, &self.entropy_source, best_block_height) + self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, recipient_onion, payment_id, route, None, &self.entropy_source, best_block_height) } @@ -2721,10 +2721,10 @@ where let best_block_height = self.best_block.read().unwrap().height(); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); self.pending_outbound_payments.send_spontaneous_payment_with_route( - route, payment_preimage, payment_id, &self.entropy_source, &self.node_signer, - best_block_height, - |path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv| - self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv)) + route, payment_preimage, recipient_onion, payment_id, &self.entropy_source, + &self.node_signer, best_block_height, + |path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv| + self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv)) } /// Similar to [`ChannelManager::send_spontaneous_payment`], but will automatically find a route @@ -2737,12 +2737,12 @@ where pub fn send_spontaneous_payment_with_retry(&self, payment_preimage: Option, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result { let best_block_height = self.best_block.read().unwrap().height(); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); - self.pending_outbound_payments.send_spontaneous_payment(payment_preimage, payment_id, - retry_strategy, route_params, &self.router, self.list_usable_channels(), + self.pending_outbound_payments.send_spontaneous_payment(payment_preimage, recipient_onion, + payment_id, retry_strategy, route_params, &self.router, self.list_usable_channels(), || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height, &self.logger, &self.pending_events, - |path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv| - self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv)) + |path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv| + self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv)) } /// Send a payment that is probing the given route for liquidity. We calculate the @@ -2752,8 +2752,8 @@ where let best_block_height = self.best_block.read().unwrap().height(); let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier); self.pending_outbound_payments.send_probe(hops, self.probing_cookie_secret, &self.entropy_source, &self.node_signer, best_block_height, - |path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv| - self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv)) + |path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv| + self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv)) } /// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a @@ -3490,8 +3490,8 @@ where self.pending_outbound_payments.check_retry_payments(&self.router, || self.list_usable_channels(), || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height, &self.pending_events, &self.logger, - |path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv| - self.send_payment_along_path(path, payment_hash, payment_secret, total_value, cur_height, payment_id, keysend_preimage, session_priv)); + |path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv| + self.send_payment_along_path(path, payment_hash, recipient_onion, total_value, cur_height, payment_id, keysend_preimage, session_priv)); for (htlc_source, payment_hash, failure_reason, destination) in failed_forwards.drain(..) { self.fail_htlc_backwards_internal(&htlc_source, &payment_hash, &failure_reason, destination); @@ -8024,8 +8024,10 @@ mod tests { // Use the utility function send_payment_along_path to send the payment with MPP data which // indicates there are more HTLCs coming. let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match. - let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, Some(payment_secret), payment_id, &mpp_route).unwrap(); - nodes[0].node.test_send_payment_along_path(&mpp_route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[0]).unwrap(); + let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), payment_id, &mpp_route).unwrap(); + nodes[0].node.test_send_payment_along_path(&mpp_route.paths[0], &our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[0]).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -8056,7 +8058,8 @@ mod tests { expect_payment_failed!(nodes[0], our_payment_hash, true); // Send the second half of the original MPP payment. - nodes[0].node.test_send_payment_along_path(&mpp_route.paths[1], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[1]).unwrap(); + nodes[0].node.test_send_payment_along_path(&mpp_route.paths[1], &our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[1]).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -8253,8 +8256,10 @@ mod tests { let test_preimage = PaymentPreimage([42; 32]); let mismatch_payment_hash = PaymentHash([43; 32]); - let session_privs = nodes[0].node.test_add_new_pending_payment(mismatch_payment_hash, None, PaymentId(mismatch_payment_hash.0), &route).unwrap(); - nodes[0].node.test_send_payment_internal(&route, mismatch_payment_hash, &None, Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap(); + let session_privs = nodes[0].node.test_add_new_pending_payment(mismatch_payment_hash, + RecipientOnionFields::spontaneous_empty(), PaymentId(mismatch_payment_hash.0), &route).unwrap(); + nodes[0].node.test_send_payment_internal(&route, mismatch_payment_hash, + RecipientOnionFields::spontaneous_empty(), Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); @@ -8296,8 +8301,11 @@ mod tests { let test_preimage = PaymentPreimage([42; 32]); let test_secret = PaymentSecret([43; 32]); let payment_hash = PaymentHash(Sha256::hash(&test_preimage.0).into_inner()); - let session_privs = nodes[0].node.test_add_new_pending_payment(payment_hash, Some(test_secret), PaymentId(payment_hash.0), &route).unwrap(); - nodes[0].node.test_send_payment_internal(&route, payment_hash, &Some(test_secret), Some(test_preimage), PaymentId(payment_hash.0), None, session_privs).unwrap(); + let session_privs = nodes[0].node.test_add_new_pending_payment(payment_hash, + RecipientOnionFields::secret_only(test_secret), PaymentId(payment_hash.0), &route).unwrap(); + nodes[0].node.test_send_payment_internal(&route, payment_hash, + RecipientOnionFields::secret_only(test_secret), Some(test_preimage), + PaymentId(payment_hash.0), None, session_privs).unwrap(); check_added_monitors!(nodes[0], 1); let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index fd9bd7a76..a37ad2ff1 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -1379,7 +1379,8 @@ fn test_fee_spike_violation_fails_htlc() { let cur_height = nodes[1].node.best_block.read().unwrap().height() + 1; let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); - let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3460001, &Some(payment_secret), cur_height, &None).unwrap(); + let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], + 3460001, RecipientOnionFields::secret_only(payment_secret), cur_height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, @@ -1562,7 +1563,8 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() { let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let cur_height = nodes[1].node.best_block.read().unwrap().height() + 1; let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); - let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 700_000, &Some(payment_secret), cur_height, &None).unwrap(); + let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], + 700_000, RecipientOnionFields::secret_only(payment_secret), cur_height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, @@ -1735,7 +1737,8 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let cur_height = nodes[0].node.best_block.read().unwrap().height() + 1; let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route_2.paths[0], &session_priv).unwrap(); - let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route_2.paths[0], recv_value_2, &None, cur_height, &None).unwrap(); + let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( + &route_2.paths[0], recv_value_2, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash_1); let msg = msgs::UpdateAddHTLC { channel_id: chan.2, @@ -3378,7 +3381,8 @@ fn fail_backward_pending_htlc_upon_channel_failure() { let secp_ctx = Secp256k1::new(); let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let current_height = nodes[1].node.best_block.read().unwrap().height() + 1; - let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &Some(payment_secret), current_height, &None).unwrap(); + let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads( + &route.paths[0], 50_000, RecipientOnionFields::secret_only(payment_secret), current_height, &None).unwrap(); let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap(); let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash); @@ -4118,8 +4122,11 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) { // indicates there are more HTLCs coming. let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match. let payment_id = PaymentId([42; 32]); - let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, Some(payment_secret), payment_id, &route).unwrap(); - nodes[0].node.test_send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[0]).unwrap(); + let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), payment_id, &route).unwrap(); + nodes[0].node.test_send_payment_along_path(&route.paths[0], &our_payment_hash, + RecipientOnionFields::secret_only(payment_secret), 200_000, cur_height, payment_id, + &None, session_privs[0]).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -6252,7 +6259,8 @@ fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() { let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); let cur_height = nodes[0].node.best_block.read().unwrap().height() + 1; let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route.paths[0], &session_priv).unwrap(); - let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &Some(our_payment_secret), cur_height, &None).unwrap(); + let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], 3999999, RecipientOnionFields::secret_only(our_payment_secret), cur_height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash); let mut msg = msgs::UpdateAddHTLC { @@ -8033,8 +8041,10 @@ fn test_onion_value_mpp_set_calculation() { // Send payment let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); - let onion_session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, Some(our_payment_secret), payment_id, &route).unwrap(); - nodes[0].node.test_send_payment_internal(&route, our_payment_hash, &Some(our_payment_secret), None, payment_id, Some(total_msat), onion_session_privs).unwrap(); + let onion_session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), payment_id, &route).unwrap(); + nodes[0].node.test_send_payment_internal(&route, our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), None, payment_id, Some(total_msat), onion_session_privs).unwrap(); check_added_monitors!(nodes[0], expected_paths.len()); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -8053,7 +8063,8 @@ fn test_onion_value_mpp_set_calculation() { let height = nodes[0].best_block_info().1; let session_priv = SecretKey::from_slice(&session_priv).unwrap(); let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); - let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], 100_000, &Some(our_payment_secret), height + 1, &None).unwrap(); + let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], 100_000, + RecipientOnionFields::secret_only(our_payment_secret), height + 1, &None).unwrap(); // Edit amt_to_forward to simulate the sender having set // the final amount and the routing node taking less fee onion_payloads[1].amt_to_forward = 99_000; @@ -8132,8 +8143,10 @@ fn do_test_overshoot_mpp(msat_amounts: &[u64], total_msat: u64) { // Send payment with manually set total_msat let payment_id = PaymentId(nodes[src_idx].keys_manager.backing.get_secure_random_bytes()); - let onion_session_privs = nodes[src_idx].node.test_add_new_pending_payment(our_payment_hash, Some(our_payment_secret), payment_id, &route).unwrap(); - nodes[src_idx].node.test_send_payment_internal(&route, our_payment_hash, &Some(our_payment_secret), None, payment_id, Some(total_msat), onion_session_privs).unwrap(); + let onion_session_privs = nodes[src_idx].node.test_add_new_pending_payment(our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), payment_id, &route).unwrap(); + nodes[src_idx].node.test_send_payment_internal(&route, our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), None, payment_id, Some(total_msat), onion_session_privs).unwrap(); check_added_monitors!(nodes[src_idx], expected_paths.len()); let mut events = nodes[src_idx].node.get_and_clear_pending_msg_events(); @@ -9384,9 +9397,12 @@ fn test_inconsistent_mpp_params() { // ultimately have, just not right away. let mut dup_route = route.clone(); dup_route.paths.push(route.paths[1].clone()); - nodes[0].node.test_add_new_pending_payment(our_payment_hash, Some(our_payment_secret), payment_id, &dup_route).unwrap() + nodes[0].node.test_add_new_pending_payment(our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), payment_id, &dup_route).unwrap() }; - nodes[0].node.test_send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(our_payment_secret), 15_000_000, cur_height, payment_id, &None, session_privs[0]).unwrap(); + nodes[0].node.test_send_payment_along_path(&route.paths[0], &our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), 15_000_000, cur_height, payment_id, + &None, session_privs[0]).unwrap(); check_added_monitors!(nodes[0], 1); { @@ -9396,7 +9412,8 @@ fn test_inconsistent_mpp_params() { } assert!(nodes[3].node.get_and_clear_pending_events().is_empty()); - nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash, &Some(our_payment_secret), 14_000_000, cur_height, payment_id, &None, session_privs[1]).unwrap(); + nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), 14_000_000, cur_height, payment_id, &None, session_privs[1]).unwrap(); check_added_monitors!(nodes[0], 1); { @@ -9442,7 +9459,9 @@ fn test_inconsistent_mpp_params() { expect_payment_failed_conditions(&nodes[0], our_payment_hash, true, PaymentFailedConditions::new().mpp_parts_remain()); - nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash, &Some(our_payment_secret), 15_000_000, cur_height, payment_id, &None, session_privs[2]).unwrap(); + nodes[0].node.test_send_payment_along_path(&route.paths[1], &our_payment_hash, + RecipientOnionFields::secret_only(our_payment_secret), 15_000_000, cur_height, payment_id, + &None, session_privs[2]).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); diff --git a/lightning/src/ln/onion_route_tests.rs b/lightning/src/ln/onion_route_tests.rs index 7fbab5df8..fd181da39 100644 --- a/lightning/src/ln/onion_route_tests.rs +++ b/lightning/src/ln/onion_route_tests.rs @@ -345,7 +345,8 @@ fn test_onion_failure() { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); let cur_height = nodes[0].best_block_info().1 + 1; let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); - let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height, &None).unwrap(); + let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); let mut new_payloads = Vec::new(); for payload in onion_payloads.drain(..) { new_payloads.push(BogusOnionHopData::new(payload)); @@ -362,7 +363,8 @@ fn test_onion_failure() { let session_priv = SecretKey::from_slice(&[3; 32]).unwrap(); let cur_height = nodes[0].best_block_info().1 + 1; let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); - let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height, &None).unwrap(); + let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); let mut new_payloads = Vec::new(); for payload in onion_payloads.drain(..) { new_payloads.push(BogusOnionHopData::new(payload)); @@ -589,7 +591,8 @@ fn test_onion_failure() { let height = nodes[2].best_block_info().1; route.paths[0][1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.paths[0][0].cltv_expiry_delta + 1; let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); - let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, height, &None).unwrap(); + let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), height, &None).unwrap(); let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash); msg.cltv_expiry = htlc_cltv; msg.onion_routing_packet = onion_packet; @@ -854,7 +857,8 @@ fn test_always_create_tlv_format_onion_payloads() { assert!(!hops[1].node_features.supports_variable_length_onion()); let cur_height = nodes[0].best_block_info().1 + 1; - let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height, &None).unwrap(); + let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads( + &route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap(); match onion_payloads[0].format { msgs::OnionHopDataFormat::NonFinalNode {..} => {}, @@ -1080,7 +1084,9 @@ fn test_phantom_invalid_onion_payload() { let height = nodes[0].best_block_info().1; let session_priv = SecretKey::from_slice(&session_priv).unwrap(); let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); - let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], msgs::MAX_VALUE_MSAT + 1, &Some(payment_secret), height + 1, &None).unwrap(); + let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads( + &route.paths[0], msgs::MAX_VALUE_MSAT + 1, + RecipientOnionFields::secret_only(payment_secret), height + 1, &None).unwrap(); // We only want to construct the onion packet for the last hop, not the entire route, so // remove the first hop's payload and its keys. onion_keys.remove(0); diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 2916829f2..2c20fb177 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -7,8 +7,8 @@ // You may not use this file except in accordance with one or both of these // licenses. -use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; -use crate::ln::channelmanager::HTLCSource; +use crate::ln::{PaymentHash, PaymentPreimage}; +use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields}; use crate::ln::msgs; use crate::ln::wire::Encode; use crate::routing::gossip::NetworkUpdate; @@ -149,7 +149,7 @@ pub(super) fn construct_onion_keys(secp_ctx: &Secp256k1, total_msat: u64, payment_secret_option: &Option, starting_htlc_offset: u32, keysend_preimage: &Option) -> Result<(Vec, u64, u32), APIError> { +pub(super) fn build_onion_payloads(path: &Vec, total_msat: u64, mut recipient_onion: RecipientOnionFields, starting_htlc_offset: u32, keysend_preimage: &Option) -> Result<(Vec, u64, u32), APIError> { let mut cur_value_msat = 0u64; let mut cur_cltv = starting_htlc_offset; let mut last_short_channel_id = 0; @@ -164,9 +164,9 @@ pub(super) fn build_onion_payloads(path: &Vec, total_msat: u64, paymen res.insert(0, msgs::OnionHopData { format: if idx == 0 { msgs::OnionHopDataFormat::FinalNode { - payment_data: if let &Some(ref payment_secret) = payment_secret_option { + payment_data: if let Some(secret) = recipient_onion.payment_secret.take() { Some(msgs::FinalOnionHopData { - payment_secret: payment_secret.clone(), + payment_secret: secret, total_msat, }) } else { None }, diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index cc511f7b4..3dde7f243 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -456,7 +456,7 @@ impl OutboundPayments { } pub(super) fn send_payment( - &self, payment_hash: PaymentHash, payment_secret: &Option, payment_id: PaymentId, + &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, retry_strategy: Retry, route_params: RouteParameters, router: &R, first_hops: Vec, compute_inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, @@ -468,34 +468,34 @@ impl OutboundPayments { NS::Target: NodeSigner, L::Target: Logger, IH: Fn() -> InFlightHtlcs, - SP: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + SP: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError>, { - self.send_payment_internal(payment_id, payment_hash, payment_secret, None, retry_strategy, + self.send_payment_internal(payment_id, payment_hash, recipient_onion, None, retry_strategy, route_params, router, first_hops, &compute_inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, &send_payment_along_path) } pub(super) fn send_payment_with_route( - &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option, + &self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, entropy_source: &ES, node_signer: &NS, best_block_height: u32, send_payment_along_path: F ) -> Result<(), PaymentSendFailure> where ES::Target: EntropySource, NS::Target: NodeSigner, - F: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + F: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { - let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, payment_id, None, route, None, None, entropy_source, best_block_height)?; - self.pay_route_internal(route, payment_hash, payment_secret, None, payment_id, None, + 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, 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 }) } pub(super) fn send_spontaneous_payment( - &self, payment_preimage: Option, payment_id: PaymentId, - retry_strategy: Retry, route_params: RouteParameters, router: &R, + &self, payment_preimage: Option, recipient_onion: RecipientOnionFields, + payment_id: PaymentId, retry_strategy: Retry, 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 @@ -506,34 +506,38 @@ impl OutboundPayments { NS::Target: NodeSigner, L::Target: Logger, IH: Fn() -> InFlightHtlcs, - SP: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + SP: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError>, { let preimage = payment_preimage .unwrap_or_else(|| PaymentPreimage(entropy_source.get_secure_random_bytes())); let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner()); - self.send_payment_internal(payment_id, payment_hash, &None, Some(preimage), retry_strategy, - route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, - best_block_height, logger, pending_events, send_payment_along_path) + self.send_payment_internal(payment_id, payment_hash, recipient_onion, Some(preimage), + retry_strategy, route_params, router, first_hops, inflight_htlcs, entropy_source, + node_signer, best_block_height, logger, pending_events, send_payment_along_path) .map(|()| payment_hash) } pub(super) fn send_spontaneous_payment_with_route( - &self, route: &Route, payment_preimage: Option, payment_id: PaymentId, - entropy_source: &ES, node_signer: &NS, best_block_height: u32, send_payment_along_path: F + &self, route: &Route, payment_preimage: Option, + recipient_onion: RecipientOnionFields, payment_id: PaymentId, entropy_source: &ES, + node_signer: &NS, best_block_height: u32, send_payment_along_path: F ) -> Result where ES::Target: EntropySource, NS::Target: NodeSigner, - F: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + F: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { let preimage = payment_preimage .unwrap_or_else(|| PaymentPreimage(entropy_source.get_secure_random_bytes())); let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner()); - let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, Some(preimage), &route, None, None, entropy_source, best_block_height)?; + 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, &None, Some(preimage), payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path) { + 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), Err(e) => { self.remove_outbound_if_all_failed(payment_id, &e); @@ -551,7 +555,7 @@ impl OutboundPayments { R::Target: Router, ES::Target: EntropySource, NS::Target: NodeSigner, - SP: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + SP: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError>, IH: Fn() -> InFlightHtlcs, FH: Fn() -> Vec, @@ -608,7 +612,7 @@ impl OutboundPayments { /// [`Event::PaymentPathFailed`]: crate::events::Event::PaymentPathFailed /// [`Event::PaymentFailed`]: crate::events::Event::PaymentFailed fn send_payment_internal( - &self, payment_id: PaymentId, payment_hash: PaymentHash, payment_secret: &Option, + &self, payment_id: PaymentId, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, keysend_preimage: Option, retry_strategy: Retry, route_params: RouteParameters, router: &R, first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, @@ -620,7 +624,7 @@ impl OutboundPayments { NS::Target: NodeSigner, L::Target: Logger, IH: Fn() -> InFlightHtlcs, - SP: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + SP: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { #[cfg(feature = "std")] { @@ -635,12 +639,12 @@ impl OutboundPayments { payment_hash, payment_id, ).map_err(|_| RetryableSendFailure::RouteNotFound)?; - let onion_session_privs = self.add_new_pending_payment(payment_hash, *payment_secret, - payment_id, keysend_preimage, &route, Some(retry_strategy), + let onion_session_privs = self.add_new_pending_payment(payment_hash, + recipient_onion.clone(), payment_id, keysend_preimage, &route, Some(retry_strategy), Some(route_params.payment_params.clone()), entropy_source, best_block_height) .map_err(|_| RetryableSendFailure::DuplicatePayment)?; - let res = self.pay_route_internal(&route, payment_hash, payment_secret, None, payment_id, None, + let res = 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); log_info!(logger, "Result sending payment with id {}: {:?}", log_bytes!(payment_id.0), res); if let Err(e) = res { @@ -661,7 +665,7 @@ impl OutboundPayments { NS::Target: NodeSigner, L::Target: Logger, IH: Fn() -> InFlightHtlcs, - SP: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + SP: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { #[cfg(feature = "std")] { @@ -709,7 +713,7 @@ impl OutboundPayments { } } } - let (total_msat, payment_secret, keysend_preimage) = { + let (total_msat, recipient_onion, keysend_preimage) = { let mut outbounds = self.pending_outbound_payments.lock().unwrap(); match outbounds.entry(payment_id) { hash_map::Entry::Occupied(mut payment) => { @@ -723,7 +727,9 @@ impl OutboundPayments { abandon_with_entry!(payment); return } - (*total_msat, *payment_secret, *keysend_preimage) + (*total_msat, RecipientOnionFields { + payment_secret: *payment_secret, + }, *keysend_preimage) }, PendingOutboundPayment::Legacy { .. } => { log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102"); @@ -755,7 +761,7 @@ impl OutboundPayments { } } }; - let res = self.pay_route_internal(&route, payment_hash, &payment_secret, 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 {}: {:?}", log_bytes!(payment_id.0), res); @@ -776,7 +782,7 @@ impl OutboundPayments { NS::Target: NodeSigner, L::Target: Logger, IH: Fn() -> InFlightHtlcs, - SP: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + SP: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { match err { @@ -846,7 +852,7 @@ impl OutboundPayments { where ES::Target: EntropySource, NS::Target: NodeSigner, - F: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + F: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { let payment_id = PaymentId(entropy_source.get_secure_random_bytes()); @@ -860,9 +866,13 @@ impl OutboundPayments { } let route = Route { paths: vec![hops], payment_params: None }; - let onion_session_privs = self.add_new_pending_payment(payment_hash, None, payment_id, None, &route, None, None, entropy_source, best_block_height)?; + let onion_session_privs = self.add_new_pending_payment(payment_hash, + RecipientOnionFields::spontaneous_empty(), payment_id, None, &route, None, None, + entropy_source, best_block_height)?; - match self.pay_route_internal(&route, payment_hash, &None, None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path) { + match self.pay_route_internal(&route, payment_hash, RecipientOnionFields::spontaneous_empty(), + None, payment_id, None, onion_session_privs, node_signer, best_block_height, &send_payment_along_path + ) { Ok(()) => Ok((payment_hash, payment_id)), Err(e) => { self.remove_outbound_if_all_failed(payment_id, &e); @@ -873,14 +883,14 @@ impl OutboundPayments { #[cfg(test)] pub(super) fn test_add_new_pending_payment( - &self, payment_hash: PaymentHash, payment_secret: Option, payment_id: PaymentId, + &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route: &Route, retry_strategy: Option, entropy_source: &ES, best_block_height: u32 ) -> Result, PaymentSendFailure> where ES::Target: EntropySource { - self.add_new_pending_payment(payment_hash, payment_secret, payment_id, None, route, retry_strategy, None, entropy_source, best_block_height) + self.add_new_pending_payment(payment_hash, recipient_onion, payment_id, None, route, retry_strategy, None, entropy_source, best_block_height) } pub(super) fn add_new_pending_payment( - &self, payment_hash: PaymentHash, payment_secret: Option, payment_id: PaymentId, + &self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, keysend_preimage: Option, route: &Route, retry_strategy: Option, payment_params: Option, entropy_source: &ES, best_block_height: u32 ) -> Result, PaymentSendFailure> where ES::Target: EntropySource { @@ -901,7 +911,7 @@ impl OutboundPayments { pending_amt_msat: 0, pending_fee_msat: Some(0), payment_hash, - payment_secret, + payment_secret: recipient_onion.payment_secret, keysend_preimage, starting_block_height: best_block_height, total_msat: route.get_total_amount(), @@ -917,20 +927,20 @@ impl OutboundPayments { } fn pay_route_internal( - &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option, + &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 ) -> Result<(), PaymentSendFailure> where NS::Target: NodeSigner, - F: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + F: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { if route.paths.len() < 1 { return Err(PaymentSendFailure::ParameterError(APIError::InvalidRoute{err: "There must be at least one path to send over".to_owned()})); } - if payment_secret.is_none() && route.paths.len() > 1 { + if recipient_onion.payment_secret.is_none() && route.paths.len() > 1 { return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError{err: "Payment secret is required for multi-path payments".to_owned()})); } let mut total_value = 0; @@ -961,7 +971,8 @@ impl OutboundPayments { let mut results = Vec::new(); debug_assert_eq!(route.paths.len(), onion_session_privs.len()); for (path, session_priv) in route.paths.iter().zip(onion_session_privs.into_iter()) { - let mut path_res = send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage, session_priv); + let mut path_res = send_payment_along_path(&path, &payment_hash, recipient_onion.clone(), + total_value, cur_height, payment_id, &keysend_preimage, session_priv); match path_res { Ok(_) => {}, Err(APIError::MonitorUpdateInProgress) => { @@ -1021,17 +1032,17 @@ impl OutboundPayments { #[cfg(test)] pub(super) fn test_send_payment_internal( - &self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option, + &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 ) -> Result<(), PaymentSendFailure> where NS::Target: NodeSigner, - F: Fn(&Vec, &PaymentHash, &Option, u64, u32, PaymentId, + F: Fn(&Vec, &PaymentHash, RecipientOnionFields, u64, u32, PaymentId, &Option, [u8; 32]) -> Result<(), APIError> { - self.pay_route_internal(route, payment_hash, payment_secret, keysend_preimage, payment_id, + 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 }) @@ -1352,7 +1363,7 @@ mod tests { use crate::events::{Event, PathFailure}; use crate::ln::PaymentHash; - use crate::ln::channelmanager::PaymentId; + use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; use crate::ln::features::{ChannelFeatures, NodeFeatures}; use crate::ln::msgs::{ErrorAction, LightningError}; use crate::ln::outbound_payment::{OutboundPayments, Retry, RetryableSendFailure}; @@ -1389,9 +1400,10 @@ mod tests { }; let pending_events = Mutex::new(Vec::new()); if on_retry { - outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]), None, - &Route { paths: vec![], payment_params: None }, Some(Retry::Attempts(1)), - Some(expired_route_params.payment_params.clone()), &&keys_manager, 0).unwrap(); + outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), None, &Route { paths: vec![], payment_params: None }, + Some(Retry::Attempts(1)), Some(expired_route_params.payment_params.clone()), + &&keys_manager, 0).unwrap(); outbound_payments.retry_payment_internal( PaymentHash([0; 32]), PaymentId([0; 32]), expired_route_params, &&router, vec![], &|| InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, @@ -1401,8 +1413,9 @@ mod tests { if let Event::PaymentFailed { .. } = events[0] { } else { panic!("Unexpected event"); } } else { let err = outbound_payments.send_payment( - PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), expired_route_params, - &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, + PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), + Retry::Attempts(0), expired_route_params, &&router, vec![], || InFlightHtlcs::new(), + &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, |_, _, _, _, _, _, _, _| Ok(())).unwrap_err(); if let RetryableSendFailure::PaymentExpired = err { } else { panic!("Unexpected error"); } } @@ -1433,9 +1446,10 @@ mod tests { let pending_events = Mutex::new(Vec::new()); if on_retry { - outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), None, PaymentId([0; 32]), None, - &Route { paths: vec![], payment_params: None }, Some(Retry::Attempts(1)), - Some(route_params.payment_params.clone()), &&keys_manager, 0).unwrap(); + outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), + PaymentId([0; 32]), None, &Route { paths: vec![], payment_params: None }, + Some(Retry::Attempts(1)), Some(route_params.payment_params.clone()), + &&keys_manager, 0).unwrap(); outbound_payments.retry_payment_internal( PaymentHash([0; 32]), PaymentId([0; 32]), route_params, &&router, vec![], &|| InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, @@ -1445,8 +1459,9 @@ mod tests { if let Event::PaymentFailed { .. } = events[0] { } else { panic!("Unexpected event"); } } else { let err = outbound_payments.send_payment( - PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), route_params, - &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, + PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), + Retry::Attempts(0), route_params, &&router, vec![], || InFlightHtlcs::new(), + &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, |_, _, _, _, _, _, _, _| Ok(())).unwrap_err(); if let RetryableSendFailure::RouteNotFound = err { } else { panic!("Unexpected error"); } @@ -1493,9 +1508,9 @@ mod tests { // PaymentPathFailed event. let pending_events = Mutex::new(Vec::new()); outbound_payments.send_payment( - PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), route_params.clone(), - &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, - &pending_events, + PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), + Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(), + &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, |_, _, _, _, _, _, _, _| Err(APIError::ChannelUnavailable { err: "test".to_owned() })) .unwrap(); let mut events = pending_events.lock().unwrap(); @@ -1512,20 +1527,17 @@ mod tests { // Ensure that a MonitorUpdateInProgress "error" will not result in a PaymentPathFailed event. outbound_payments.send_payment( - PaymentHash([0; 32]), &None, PaymentId([0; 32]), Retry::Attempts(0), route_params.clone(), - &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, - &pending_events, |_, _, _, _, _, _, _, _| Err(APIError::MonitorUpdateInProgress)) - .unwrap(); - { - let events = pending_events.lock().unwrap(); - assert_eq!(events.len(), 0); - } + PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), + Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(), + &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, + |_, _, _, _, _, _, _, _| Err(APIError::MonitorUpdateInProgress)).unwrap(); + assert_eq!(pending_events.lock().unwrap().len(), 0); // Ensure that any other error will result in a PaymentPathFailed event but no blamed scid. outbound_payments.send_payment( - PaymentHash([0; 32]), &None, PaymentId([1; 32]), Retry::Attempts(0), route_params.clone(), - &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, &&keys_manager, 0, &&logger, - &pending_events, + PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([1; 32]), + Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(), + &&keys_manager, &&keys_manager, 0, &&logger, &pending_events, |_, _, _, _, _, _, _, _| Err(APIError::APIMisuseError { err: "test".to_owned() })) .unwrap(); let events = pending_events.lock().unwrap();