@@ -3133,6 +3133,66 @@ where
31333133 Ok(chan_update_opt)
31343134 }
31353135
3136+ fn can_forward_htlc(
3137+ &self, msg: &msgs::UpdateAddHTLC, next_packet_details: &NextPacketDetails
3138+ ) -> Result<Option<msgs::ChannelUpdate>, (&'static str, u16, Option<msgs::ChannelUpdate>)> {
3139+ let id_option = self.short_to_chan_info.read().unwrap().get(&next_packet_details.outgoing_scid).cloned();
3140+ let forwarding_chan_info_opt = match id_option {
3141+ None => { // unknown_next_peer
3142+ // Note that this is likely a timing oracle for detecting whether an scid is a
3143+ // phantom or an intercept.
3144+ if (self.default_configuration.accept_intercept_htlcs &&
3145+ fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)) ||
3146+ fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)
3147+ {
3148+ None
3149+ } else {
3150+ return Err(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3151+ }
3152+ },
3153+ Some((cp_id, id)) => Some((cp_id.clone(), id.clone())),
3154+ };
3155+
3156+ let chan_update_opt = if let Some((counterparty_node_id, forwarding_id)) = forwarding_chan_info_opt {
3157+ let per_peer_state = self.per_peer_state.read().unwrap();
3158+ let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
3159+ if peer_state_mutex_opt.is_none() {
3160+ return Err(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3161+ }
3162+ let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
3163+ let peer_state = &mut *peer_state_lock;
3164+ let chan = match peer_state.channel_by_id.get_mut(&forwarding_id).map(
3165+ |chan_phase| if let ChannelPhase::Funded(chan) = chan_phase { Some(chan) } else { None }
3166+ ).flatten() {
3167+ None => {
3168+ // Channel was removed. The short_to_chan_info and channel_by_id maps
3169+ // have no consistency guarantees.
3170+ return Err(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3171+ },
3172+ Some(chan) => chan,
3173+ };
3174+ self.can_forward_htlc_to_outgoing_channel(chan, msg, next_packet_details)?
3175+ } else {
3176+ None
3177+ };
3178+
3179+ let cur_height = self.best_block.read().unwrap().height + 1;
3180+ if let Err((err_msg, err_code)) = check_incoming_htlc_cltv(
3181+ cur_height, next_packet_details.outgoing_cltv_value, msg.cltv_expiry
3182+ ) {
3183+ if err_code & 0x1000 != 0 && chan_update_opt.is_none() {
3184+ // We really should set `incorrect_cltv_expiry` here but as we're not
3185+ // forwarding over a real channel we can't generate a channel_update
3186+ // for it. Instead we just return a generic temporary_node_failure.
3187+ return Err((err_msg, 0x2000 | 2, None));
3188+ }
3189+ let chan_update_opt = if err_code & 0x1000 != 0 { chan_update_opt } else { None };
3190+ return Err((err_msg, err_code, chan_update_opt));
3191+ }
3192+
3193+ Ok(chan_update_opt)
3194+ }
3195+
31363196 fn htlc_failure_from_update_add_err(
31373197 &self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, err_msg: &'static str,
31383198 mut err_code: u16, chan_update: Option<msgs::ChannelUpdate>, is_intro_node_blinded_forward: bool,
@@ -3205,71 +3265,14 @@ where
32053265
32063266 // Perform outbound checks here instead of in [`Self::construct_pending_htlc_info`] because we
32073267 // can't hold the outbound peer state lock at the same time as the inbound peer state lock.
3208- if let Some((err, code, chan_update)) = loop {
3209- let id_option = self.short_to_chan_info.read().unwrap().get(&next_packet_details.outgoing_scid).cloned();
3210- let forwarding_chan_info_opt = match id_option {
3211- None => { // unknown_next_peer
3212- // Note that this is likely a timing oracle for detecting whether an scid is a
3213- // phantom or an intercept.
3214- if (self.default_configuration.accept_intercept_htlcs &&
3215- fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)) ||
3216- fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)
3217- {
3218- None
3219- } else {
3220- break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3221- }
3222- },
3223- Some((cp_id, id)) => Some((cp_id.clone(), id.clone())),
3224- };
3225- let chan_update_opt = if let Some((counterparty_node_id, forwarding_id)) = forwarding_chan_info_opt {
3226- let per_peer_state = self.per_peer_state.read().unwrap();
3227- let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
3228- if peer_state_mutex_opt.is_none() {
3229- break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3230- }
3231- let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
3232- let peer_state = &mut *peer_state_lock;
3233- let chan = match peer_state.channel_by_id.get_mut(&forwarding_id).map(
3234- |chan_phase| if let ChannelPhase::Funded(chan) = chan_phase { Some(chan) } else { None }
3235- ).flatten() {
3236- None => {
3237- // Channel was removed. The short_to_chan_info and channel_by_id maps
3238- // have no consistency guarantees.
3239- break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3240- },
3241- Some(chan) => chan
3242- };
3243- match self.can_forward_htlc_to_outgoing_channel(chan, msg, &next_packet_details) {
3244- Ok(chan_update_opt) => chan_update_opt,
3245- Err(e) => break Some(e),
3246- }
3247- } else {
3248- None
3249- };
3250-
3251- let cur_height = self.best_block.read().unwrap().height + 1;
3252-
3253- if let Err((err_msg, code)) = check_incoming_htlc_cltv(
3254- cur_height, next_packet_details.outgoing_cltv_value, msg.cltv_expiry
3255- ) {
3256- if code & 0x1000 != 0 && chan_update_opt.is_none() {
3257- // We really should set `incorrect_cltv_expiry` here but as we're not
3258- // forwarding over a real channel we can't generate a channel_update
3259- // for it. Instead we just return a generic temporary_node_failure.
3260- break Some((err_msg, 0x2000 | 2, None))
3261- }
3262- let chan_update_opt = if code & 0x1000 != 0 { chan_update_opt } else { None };
3263- break Some((err_msg, code, chan_update_opt));
3264- }
3268+ let _ = self.can_forward_htlc(&msg, &next_packet_details).map_err(|e| {
3269+ let (err_msg, err_code, chan_update_opt) = e;
3270+ self.htlc_failure_from_update_add_err(
3271+ msg, counterparty_node_id, err_msg, err_code, chan_update_opt,
3272+ next_hop.is_intro_node_blinded_forward(), &shared_secret
3273+ )
3274+ })?;
32653275
3266- break None;
3267- }
3268- {
3269- return Err(self.htlc_failure_from_update_add_err(
3270- msg, counterparty_node_id, err, code, chan_update, next_hop.is_intro_node_blinded_forward(), &shared_secret
3271- ));
3272- }
32733276 Ok((next_hop, shared_secret, Some(next_packet_details.next_packet_pubkey)))
32743277 }
32753278
0 commit comments