Correctly fail back downstream-failed blinded HTLCs as intro
[rust-lightning] / lightning / src / ln / channelmanager.rs
index d56d1349231acffca4143ede3c00f16c458bb77e..4247d57cbb6ad199ba99842c8dae506ee08f2e25 100644 (file)
@@ -53,7 +53,7 @@ use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParame
 use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, InboundOnionErr, NextPacketDetails};
 use crate::ln::msgs;
 use crate::ln::onion_utils;
-use crate::ln::onion_utils::HTLCFailReason;
+use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING};
 use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
 #[cfg(test)]
 use crate::ln::outbound_payment;
@@ -2977,14 +2977,24 @@ where
                        msg, &self.node_signer, &self.logger, &self.secp_ctx
                )?;
 
+               let is_blinded = match next_hop {
+                       onion_utils::Hop::Forward {
+                               next_hop_data: msgs::InboundOnionPayload::BlindedForward { .. }, ..
+                       } => true,
+                       _ => false, // TODO: update this when we support receiving to multi-hop blinded paths
+               };
+
                macro_rules! return_err {
                        ($msg: expr, $err_code: expr, $data: expr) => {
                                {
                                        log_info!(self.logger, "Failed to accept/forward incoming HTLC: {}", $msg);
+                                       let (err_code, err_data) = if is_blinded {
+                                               (INVALID_ONION_BLINDING, &[0; 32][..])
+                                       } else { ($err_code, $data) };
                                        return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
                                                channel_id: msg.channel_id,
                                                htlc_id: msg.htlc_id,
-                                               reason: HTLCFailReason::reason($err_code, $data.to_vec())
+                                               reason: HTLCFailReason::reason(err_code, err_data.to_vec())
                                                        .get_encrypted_failure_packet(&shared_secret, &None),
                                        }));
                                }
@@ -5148,9 +5158,23 @@ where
                                        &self.pending_events, &self.logger)
                                { self.push_pending_forwards_ev(); }
                        },
-                       HTLCSource::PreviousHopData(HTLCPreviousHopData { ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret, ref phantom_shared_secret, ref outpoint, .. }) => {
-                               log_trace!(self.logger, "Failing HTLC with payment_hash {} backwards from us with {:?}", &payment_hash, onion_error);
-                               let err_packet = onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret);
+                       HTLCSource::PreviousHopData(HTLCPreviousHopData {
+                               ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret,
+                               ref phantom_shared_secret, ref outpoint, ref blinded_failure, ..
+                       }) => {
+                               log_trace!(self.logger, "Failing {}HTLC with payment_hash {} backwards from us: {:?}",
+                                       if blinded_failure.is_some() { "blinded " } else { "" }, &payment_hash, onion_error);
+                               let err_packet = match blinded_failure {
+                                       Some(BlindedFailure::FromIntroductionNode) => {
+                                               let blinded_onion_error = HTLCFailReason::reason(INVALID_ONION_BLINDING, vec![0; 32]);
+                                               blinded_onion_error.get_encrypted_failure_packet(
+                                                       incoming_packet_shared_secret, phantom_shared_secret
+                                               )
+                                       },
+                                       None => {
+                                               onion_error.get_encrypted_failure_packet(incoming_packet_shared_secret, phantom_shared_secret)
+                                       }
+                               };
 
                                let mut push_forward_ev = false;
                                let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
@@ -6431,8 +6455,12 @@ where
                                                // but if we've sent a shutdown and they haven't acknowledged it yet, we just
                                                // want to reject the new HTLC and fail it backwards instead of forwarding.
                                                match pending_forward_info {
-                                                       PendingHTLCStatus::Forward(PendingHTLCInfo { ref incoming_shared_secret, .. }) => {
-                                                               let reason = if (error_code & 0x1000) != 0 {
+                                                       PendingHTLCStatus::Forward(PendingHTLCInfo {
+                                                               ref incoming_shared_secret, ref routing, ..
+                                                       }) => {
+                                                               let reason = if routing.blinded_failure().is_some() {
+                                                                       HTLCFailReason::reason(INVALID_ONION_BLINDING, vec![0; 32])
+                                                               } else if (error_code & 0x1000) != 0 {
                                                                        let (real_code, error_data) = self.get_htlc_inbound_temp_fail_err_and_data(error_code, chan);
                                                                        HTLCFailReason::reason(real_code, error_data)
                                                                } else {