@@ -3096,7 +3096,7 @@ where
3096
3096
3097
3097
fn can_forward_htlc_to_outgoing_channel(
3098
3098
&self, chan: &mut Channel<SP>, msg: &msgs::UpdateAddHTLC, next_packet: &NextPacketDetails
3099
- ) -> Result<Option<msgs::ChannelUpdate> , (&'static str, u16, Option<msgs::ChannelUpdate>)> {
3099
+ ) -> Result<() , (&'static str, u16, Option<msgs::ChannelUpdate>)> {
3100
3100
if !chan.context.should_announce() && !self.default_configuration.accept_forwards_to_priv_channels {
3101
3101
// Note that the behavior here should be identical to the above block - we
3102
3102
// should NOT reveal the existence or non-existence of a private channel if
@@ -3109,7 +3109,6 @@ where
3109
3109
// we don't have the channel here.
3110
3110
return Err(("Refusing to forward over real channel SCID as our counterparty requested.", 0x4000 | 10, None));
3111
3111
}
3112
- let chan_update_opt = self.get_channel_update_for_onion(next_packet.outgoing_scid, chan).ok();
3113
3112
3114
3113
// Note that we could technically not return an error yet here and just hope
3115
3114
// that the connection is reestablished or monitor updated by the time we get
@@ -3120,20 +3119,87 @@ where
3120
3119
// If the channel_update we're going to return is disabled (i.e. the
3121
3120
// peer has been disabled for some time), return `channel_disabled`,
3122
3121
// otherwise return `temporary_channel_failure`.
3122
+ let chan_update_opt = self.get_channel_update_for_onion(next_packet.outgoing_scid, chan).ok();
3123
3123
if chan_update_opt.as_ref().map(|u| u.contents.flags & 2 == 2).unwrap_or(false) {
3124
3124
return Err(("Forwarding channel has been disconnected for some time.", 0x1000 | 20, chan_update_opt));
3125
3125
} else {
3126
3126
return Err(("Forwarding channel is not in a ready state.", 0x1000 | 7, chan_update_opt));
3127
3127
}
3128
3128
}
3129
3129
if next_packet.outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { // amount_below_minimum
3130
+ let chan_update_opt = self.get_channel_update_for_onion(next_packet.outgoing_scid, chan).ok();
3130
3131
return Err(("HTLC amount was below the htlc_minimum_msat", 0x1000 | 11, chan_update_opt));
3131
3132
}
3132
3133
if let Err((err, code)) = chan.htlc_satisfies_config(msg, next_packet.outgoing_amt_msat, next_packet.outgoing_cltv_value) {
3134
+ let chan_update_opt = self.get_channel_update_for_onion(next_packet.outgoing_scid, chan).ok();
3133
3135
return Err((err, code, chan_update_opt));
3134
3136
}
3135
3137
3136
- Ok(chan_update_opt)
3138
+ Ok(())
3139
+ }
3140
+
3141
+ /// Executes a callback `C` that returns some value `X` on the channel found with the given
3142
+ /// `scid`. `None` is returned when the channel is not found.
3143
+ fn do_channel_callback<X, C: Fn(&mut Channel<SP>) -> X>(
3144
+ &self, scid: u64, callback: C,
3145
+ ) -> Option<X> {
3146
+ let (counterparty_node_id, channel_id) = match self.short_to_chan_info.read().unwrap().get(&scid).cloned() {
3147
+ None => return None,
3148
+ Some((cp_id, id)) => (cp_id, id),
3149
+ };
3150
+ let per_peer_state = self.per_peer_state.read().unwrap();
3151
+ let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
3152
+ if peer_state_mutex_opt.is_none() {
3153
+ return None;
3154
+ }
3155
+ let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
3156
+ let peer_state = &mut *peer_state_lock;
3157
+ match peer_state.channel_by_id.get_mut(&channel_id).and_then(
3158
+ |chan_phase| if let ChannelPhase::Funded(chan) = chan_phase { Some(chan) } else { None }
3159
+ ) {
3160
+ None => None,
3161
+ Some(chan) => Some(callback(chan)),
3162
+ }
3163
+ }
3164
+
3165
+ fn can_forward_htlc(
3166
+ &self, msg: &msgs::UpdateAddHTLC, next_packet_details: &NextPacketDetails
3167
+ ) -> Result<(), (&'static str, u16, Option<msgs::ChannelUpdate>)> {
3168
+ match self.do_channel_callback(next_packet_details.outgoing_scid, |chan: &mut Channel<SP>| {
3169
+ self.can_forward_htlc_to_outgoing_channel(chan, msg, next_packet_details)
3170
+ }) {
3171
+ Some(Ok(())) => {},
3172
+ Some(Err(e)) => return Err(e),
3173
+ None => {
3174
+ // If we couldn't find the channel info for the scid, it may be a phantom or
3175
+ // intercept forward.
3176
+ if (self.default_configuration.accept_intercept_htlcs &&
3177
+ fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)) ||
3178
+ fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)
3179
+ {} else {
3180
+ return Err(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3181
+ }
3182
+ }
3183
+ }
3184
+
3185
+ let cur_height = self.best_block.read().unwrap().height + 1;
3186
+ if let Err((err_msg, err_code)) = check_incoming_htlc_cltv(
3187
+ cur_height, next_packet_details.outgoing_cltv_value, msg.cltv_expiry
3188
+ ) {
3189
+ let chan_update_opt = self.do_channel_callback(next_packet_details.outgoing_scid, |chan: &mut Channel<SP>| {
3190
+ self.get_channel_update_for_onion(next_packet_details.outgoing_scid, chan).ok()
3191
+ }).flatten();
3192
+ if err_code & 0x1000 != 0 && chan_update_opt.is_none() {
3193
+ // We really should set `incorrect_cltv_expiry` here but as we're not
3194
+ // forwarding over a real channel we can't generate a channel_update
3195
+ // for it. Instead we just return a generic temporary_node_failure.
3196
+ return Err((err_msg, 0x2000 | 2, None));
3197
+ }
3198
+ let chan_update_opt = if err_code & 0x1000 != 0 { chan_update_opt } else { None };
3199
+ return Err((err_msg, err_code, chan_update_opt));
3200
+ }
3201
+
3202
+ Ok(())
3137
3203
}
3138
3204
3139
3205
fn htlc_failure_from_update_add_err(
@@ -3208,71 +3274,14 @@ where
3208
3274
3209
3275
// Perform outbound checks here instead of in [`Self::construct_pending_htlc_info`] because we
3210
3276
// can't hold the outbound peer state lock at the same time as the inbound peer state lock.
3211
- if let Some((err, code, chan_update)) = loop {
3212
- let id_option = self.short_to_chan_info.read().unwrap().get(&next_packet_details.outgoing_scid).cloned();
3213
- let forwarding_chan_info_opt = match id_option {
3214
- None => { // unknown_next_peer
3215
- // Note that this is likely a timing oracle for detecting whether an scid is a
3216
- // phantom or an intercept.
3217
- if (self.default_configuration.accept_intercept_htlcs &&
3218
- fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)) ||
3219
- fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)
3220
- {
3221
- None
3222
- } else {
3223
- break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3224
- }
3225
- },
3226
- Some((cp_id, id)) => Some((cp_id.clone(), id.clone())),
3227
- };
3228
- let chan_update_opt = if let Some((counterparty_node_id, forwarding_id)) = forwarding_chan_info_opt {
3229
- let per_peer_state = self.per_peer_state.read().unwrap();
3230
- let peer_state_mutex_opt = per_peer_state.get(&counterparty_node_id);
3231
- if peer_state_mutex_opt.is_none() {
3232
- break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3233
- }
3234
- let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
3235
- let peer_state = &mut *peer_state_lock;
3236
- let chan = match peer_state.channel_by_id.get_mut(&forwarding_id).map(
3237
- |chan_phase| if let ChannelPhase::Funded(chan) = chan_phase { Some(chan) } else { None }
3238
- ).flatten() {
3239
- None => {
3240
- // Channel was removed. The short_to_chan_info and channel_by_id maps
3241
- // have no consistency guarantees.
3242
- break Some(("Don't have available channel for forwarding as requested.", 0x4000 | 10, None));
3243
- },
3244
- Some(chan) => chan
3245
- };
3246
- match self.can_forward_htlc_to_outgoing_channel(chan, msg, &next_packet_details) {
3247
- Ok(chan_update_opt) => chan_update_opt,
3248
- Err(e) => break Some(e),
3249
- }
3250
- } else {
3251
- None
3252
- };
3253
-
3254
- let cur_height = self.best_block.read().unwrap().height + 1;
3255
-
3256
- if let Err((err_msg, code)) = check_incoming_htlc_cltv(
3257
- cur_height, next_packet_details.outgoing_cltv_value, msg.cltv_expiry
3258
- ) {
3259
- if code & 0x1000 != 0 && chan_update_opt.is_none() {
3260
- // We really should set `incorrect_cltv_expiry` here but as we're not
3261
- // forwarding over a real channel we can't generate a channel_update
3262
- // for it. Instead we just return a generic temporary_node_failure.
3263
- break Some((err_msg, 0x2000 | 2, None))
3264
- }
3265
- let chan_update_opt = if code & 0x1000 != 0 { chan_update_opt } else { None };
3266
- break Some((err_msg, code, chan_update_opt));
3267
- }
3277
+ let _ = self.can_forward_htlc(&msg, &next_packet_details).map_err(|e| {
3278
+ let (err_msg, err_code, chan_update_opt) = e;
3279
+ self.htlc_failure_from_update_add_err(
3280
+ msg, counterparty_node_id, err_msg, err_code, chan_update_opt,
3281
+ next_hop.is_intro_node_blinded_forward(), &shared_secret
3282
+ )
3283
+ })?;
3268
3284
3269
- break None;
3270
- }
3271
- {
3272
- return Err(self.htlc_failure_from_update_add_err(
3273
- msg, counterparty_node_id, err, code, chan_update, next_hop.is_intro_node_blinded_forward(), &shared_secret
3274
- ));
3275
- }
3276
3285
Ok((next_hop, shared_secret, Some(next_packet_details.next_packet_pubkey)))
3277
3286
}
3278
3287
0 commit comments