@@ -3094,6 +3094,61 @@ where
30943094 }
30953095 }
30963096
3097+ fn htlc_failure_from_update_add_err(
3098+ &self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, err_msg: &'static str,
3099+ mut err_code: u16, chan_update: Option<msgs::ChannelUpdate>, is_intro_node_blinded_forward: bool,
3100+ shared_secret: &[u8; 32]
3101+ ) -> HTLCFailureMsg {
3102+ let mut res = VecWriter(Vec::with_capacity(chan_update.serialized_length() + 2 + 8 + 2));
3103+ if let Some(chan_update) = chan_update {
3104+ if err_code == 0x1000 | 11 || err_code == 0x1000 | 12 {
3105+ msg.amount_msat.write(&mut res).expect("Writes cannot fail");
3106+ }
3107+ else if err_code == 0x1000 | 13 {
3108+ msg.cltv_expiry.write(&mut res).expect("Writes cannot fail");
3109+ }
3110+ else if err_code == 0x1000 | 20 {
3111+ // TODO: underspecified, follow https://github.com/lightning/bolts/issues/791
3112+ 0u16.write(&mut res).expect("Writes cannot fail");
3113+ }
3114+ (chan_update.serialized_length() as u16 + 2).write(&mut res).expect("Writes cannot fail");
3115+ msgs::ChannelUpdate::TYPE.write(&mut res).expect("Writes cannot fail");
3116+ chan_update.write(&mut res).expect("Writes cannot fail");
3117+ } else if err_code & 0x1000 == 0x1000 {
3118+ // If we're trying to return an error that requires a `channel_update` but
3119+ // we're forwarding to a phantom or intercept "channel" (i.e. cannot
3120+ // generate an update), just use the generic "temporary_node_failure"
3121+ // instead.
3122+ err_code = 0x2000 | 2;
3123+ }
3124+
3125+ log_info!(
3126+ WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id)),
3127+ "Failed to accept/forward incoming HTLC: {}", err_msg
3128+ );
3129+ // If `msg.blinding_point` is set, we must always fail with malformed.
3130+ if msg.blinding_point.is_some() {
3131+ return HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
3132+ channel_id: msg.channel_id,
3133+ htlc_id: msg.htlc_id,
3134+ sha256_of_onion: [0; 32],
3135+ failure_code: INVALID_ONION_BLINDING,
3136+ });
3137+ }
3138+
3139+ let (err_code, err_data) = if is_intro_node_blinded_forward {
3140+ (INVALID_ONION_BLINDING, &[0; 32][..])
3141+ } else {
3142+ (err_code, &res.0[..])
3143+ };
3144+ HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
3145+ channel_id: msg.channel_id,
3146+ htlc_id: msg.htlc_id,
3147+ reason: HTLCFailReason::reason(err_code, err_data.to_vec())
3148+ .get_encrypted_failure_packet(shared_secret, &None),
3149+ })
3150+ }
3151+
30973152 fn decode_update_add_htlc_onion(
30983153 &self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey,
30993154 ) -> Result<
@@ -3103,36 +3158,6 @@ where
31033158 msg, &self.node_signer, &self.logger, &self.secp_ctx
31043159 )?;
31053160
3106- macro_rules! return_err {
3107- ($msg: expr, $err_code: expr, $data: expr) => {
3108- {
3109- log_info!(
3110- WithContext::from(&self.logger, Some(*counterparty_node_id), Some(msg.channel_id)),
3111- "Failed to accept/forward incoming HTLC: {}", $msg
3112- );
3113- // If `msg.blinding_point` is set, we must always fail with malformed.
3114- if msg.blinding_point.is_some() {
3115- return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
3116- channel_id: msg.channel_id,
3117- htlc_id: msg.htlc_id,
3118- sha256_of_onion: [0; 32],
3119- failure_code: INVALID_ONION_BLINDING,
3120- }));
3121- }
3122-
3123- let (err_code, err_data) = if next_hop.is_intro_node_blinded_forward() {
3124- (INVALID_ONION_BLINDING, &[0; 32][..])
3125- } else { ($err_code, $data) };
3126- return Err(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
3127- channel_id: msg.channel_id,
3128- htlc_id: msg.htlc_id,
3129- reason: HTLCFailReason::reason(err_code, err_data.to_vec())
3130- .get_encrypted_failure_packet(&shared_secret, &None),
3131- }));
3132- }
3133- }
3134- }
3135-
31363161 let NextPacketDetails {
31373162 next_packet_pubkey, outgoing_amt_msat, outgoing_scid, outgoing_cltv_value
31383163 } = match next_packet_details_opt {
@@ -3143,7 +3168,7 @@ where
31433168
31443169 // Perform outbound checks here instead of in [`Self::construct_pending_htlc_info`] because we
31453170 // can't hold the outbound peer state lock at the same time as the inbound peer state lock.
3146- if let Some((err, mut code, chan_update)) = loop {
3171+ if let Some((err, code, chan_update)) = loop {
31473172 let id_option = self.short_to_chan_info.read().unwrap().get(&outgoing_scid).cloned();
31483173 let forwarding_chan_info_opt = match id_option {
31493174 None => { // unknown_next_peer
@@ -3236,29 +3261,9 @@ where
32363261 break None;
32373262 }
32383263 {
3239- let mut res = VecWriter(Vec::with_capacity(chan_update.serialized_length() + 2 + 8 + 2));
3240- if let Some(chan_update) = chan_update {
3241- if code == 0x1000 | 11 || code == 0x1000 | 12 {
3242- msg.amount_msat.write(&mut res).expect("Writes cannot fail");
3243- }
3244- else if code == 0x1000 | 13 {
3245- msg.cltv_expiry.write(&mut res).expect("Writes cannot fail");
3246- }
3247- else if code == 0x1000 | 20 {
3248- // TODO: underspecified, follow https://github.com/lightning/bolts/issues/791
3249- 0u16.write(&mut res).expect("Writes cannot fail");
3250- }
3251- (chan_update.serialized_length() as u16 + 2).write(&mut res).expect("Writes cannot fail");
3252- msgs::ChannelUpdate::TYPE.write(&mut res).expect("Writes cannot fail");
3253- chan_update.write(&mut res).expect("Writes cannot fail");
3254- } else if code & 0x1000 == 0x1000 {
3255- // If we're trying to return an error that requires a `channel_update` but
3256- // we're forwarding to a phantom or intercept "channel" (i.e. cannot
3257- // generate an update), just use the generic "temporary_node_failure"
3258- // instead.
3259- code = 0x2000 | 2;
3260- }
3261- return_err!(err, code, &res.0[..]);
3264+ return Err(self.htlc_failure_from_update_add_err(
3265+ msg, counterparty_node_id, err, code, chan_update, next_hop.is_intro_node_blinded_forward(), &shared_secret
3266+ ));
32623267 }
32633268 Ok((next_hop, shared_secret, Some(next_packet_pubkey)))
32643269 }
0 commit comments