@@ -3094,6 +3094,48 @@ where
3094
3094
}
3095
3095
}
3096
3096
3097
+ fn can_forward_htlc_to_outgoing_channel(
3098
+ &self, chan: &mut Channel<SP>, msg: &msgs::UpdateAddHTLC, next_packet: &NextPacketDetails
3099
+ ) -> Result<Option<msgs::ChannelUpdate>, (&'static str, u16, Option<msgs::ChannelUpdate>)> {
3100
+ if !chan.context.should_announce() && !self.default_configuration.accept_forwards_to_priv_channels {
3101
+ // Note that the behavior here should be identical to the above block - we
3102
+ // should NOT reveal the existence or non-existence of a private channel if
3103
+ // we don't allow forwards outbound over them.
3104
+ return Err(("Refusing to forward to a private channel based on our config.", 0x4000 | 10, None));
3105
+ }
3106
+ if chan.context.get_channel_type().supports_scid_privacy() && next_packet.outgoing_scid != chan.context.outbound_scid_alias() {
3107
+ // `option_scid_alias` (referred to in LDK as `scid_privacy`) means
3108
+ // "refuse to forward unless the SCID alias was used", so we pretend
3109
+ // we don't have the channel here.
3110
+ return Err(("Refusing to forward over real channel SCID as our counterparty requested.", 0x4000 | 10, None));
3111
+ }
3112
+ let chan_update_opt = self.get_channel_update_for_onion(next_packet.outgoing_scid, chan).ok();
3113
+
3114
+ // Note that we could technically not return an error yet here and just hope
3115
+ // that the connection is reestablished or monitor updated by the time we get
3116
+ // around to doing the actual forward, but better to fail early if we can and
3117
+ // hopefully an attacker trying to path-trace payments cannot make this occur
3118
+ // on a small/per-node/per-channel scale.
3119
+ if !chan.context.is_live() { // channel_disabled
3120
+ // If the channel_update we're going to return is disabled (i.e. the
3121
+ // peer has been disabled for some time), return `channel_disabled`,
3122
+ // otherwise return `temporary_channel_failure`.
3123
+ if chan_update_opt.as_ref().map(|u| u.contents.flags & 2 == 2).unwrap_or(false) {
3124
+ return Err(("Forwarding channel has been disconnected for some time.", 0x1000 | 20, chan_update_opt));
3125
+ } else {
3126
+ return Err(("Forwarding channel is not in a ready state.", 0x1000 | 7, chan_update_opt));
3127
+ }
3128
+ }
3129
+ if next_packet.outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { // amount_below_minimum
3130
+ return Err(("HTLC amount was below the htlc_minimum_msat", 0x1000 | 11, chan_update_opt));
3131
+ }
3132
+ if let Err((err, code)) = chan.htlc_satisfies_config(msg, next_packet.outgoing_amt_msat, next_packet.outgoing_cltv_value) {
3133
+ return Err((err, code, chan_update_opt));
3134
+ }
3135
+
3136
+ Ok(chan_update_opt)
3137
+ }
3138
+
3097
3139
fn htlc_failure_from_update_add_err(
3098
3140
&self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, err_msg: &'static str,
3099
3141
mut err_code: u16, chan_update: Option<msgs::ChannelUpdate>, is_intro_node_blinded_forward: bool,
@@ -3158,9 +3200,7 @@ where
3158
3200
msg, &self.node_signer, &self.logger, &self.secp_ctx
3159
3201
)?;
3160
3202
3161
- let NextPacketDetails {
3162
- next_packet_pubkey, outgoing_amt_msat, outgoing_scid, outgoing_cltv_value
3163
- } = match next_packet_details_opt {
3203
+ let next_packet_details = match next_packet_details_opt {
3164
3204
Some(next_packet_details) => next_packet_details,
3165
3205
// it is a receive, so no need for outbound checks
3166
3206
None => return Ok((next_hop, shared_secret, None)),
@@ -3169,14 +3209,14 @@ where
3169
3209
// Perform outbound checks here instead of in [`Self::construct_pending_htlc_info`] because we
3170
3210
// can't hold the outbound peer state lock at the same time as the inbound peer state lock.
3171
3211
if let Some((err, code, chan_update)) = loop {
3172
- let id_option = self.short_to_chan_info.read().unwrap().get(&outgoing_scid).cloned();
3212
+ let id_option = self.short_to_chan_info.read().unwrap().get(&next_packet_details. outgoing_scid).cloned();
3173
3213
let forwarding_chan_info_opt = match id_option {
3174
3214
None => { // unknown_next_peer
3175
3215
// Note that this is likely a timing oracle for detecting whether an scid is a
3176
3216
// phantom or an intercept.
3177
3217
if (self.default_configuration.accept_intercept_htlcs &&
3178
- fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, outgoing_scid, &self.chain_hash)) ||
3179
- fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, outgoing_scid, &self.chain_hash)
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)
3180
3220
{
3181
3221
None
3182
3222
} else {
@@ -3203,50 +3243,18 @@ where
3203
3243
},
3204
3244
Some(chan) => chan
3205
3245
};
3206
- if !chan.context.should_announce() && !self.default_configuration.accept_forwards_to_priv_channels {
3207
- // Note that the behavior here should be identical to the above block - we
3208
- // should NOT reveal the existence or non-existence of a private channel if
3209
- // we don't allow forwards outbound over them.
3210
- break Some(("Refusing to forward to a private channel based on our config.", 0x4000 | 10, None));
3211
- }
3212
- if chan.context.get_channel_type().supports_scid_privacy() && outgoing_scid != chan.context.outbound_scid_alias() {
3213
- // `option_scid_alias` (referred to in LDK as `scid_privacy`) means
3214
- // "refuse to forward unless the SCID alias was used", so we pretend
3215
- // we don't have the channel here.
3216
- break Some(("Refusing to forward over real channel SCID as our counterparty requested.", 0x4000 | 10, None));
3217
- }
3218
- let chan_update_opt = self.get_channel_update_for_onion(outgoing_scid, chan).ok();
3219
-
3220
- // Note that we could technically not return an error yet here and just hope
3221
- // that the connection is reestablished or monitor updated by the time we get
3222
- // around to doing the actual forward, but better to fail early if we can and
3223
- // hopefully an attacker trying to path-trace payments cannot make this occur
3224
- // on a small/per-node/per-channel scale.
3225
- if !chan.context.is_live() { // channel_disabled
3226
- // If the channel_update we're going to return is disabled (i.e. the
3227
- // peer has been disabled for some time), return `channel_disabled`,
3228
- // otherwise return `temporary_channel_failure`.
3229
- if chan_update_opt.as_ref().map(|u| u.contents.flags & 2 == 2).unwrap_or(false) {
3230
- break Some(("Forwarding channel has been disconnected for some time.", 0x1000 | 20, chan_update_opt));
3231
- } else {
3232
- break Some(("Forwarding channel is not in a ready state.", 0x1000 | 7, chan_update_opt));
3233
- }
3234
- }
3235
- if outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { // amount_below_minimum
3236
- break Some(("HTLC amount was below the htlc_minimum_msat", 0x1000 | 11, chan_update_opt));
3237
- }
3238
- if let Err((err, code)) = chan.htlc_satisfies_config(&msg, outgoing_amt_msat, outgoing_cltv_value) {
3239
- break Some((err, code, chan_update_opt));
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),
3240
3249
}
3241
- chan_update_opt
3242
3250
} else {
3243
3251
None
3244
3252
};
3245
3253
3246
3254
let cur_height = self.best_block.read().unwrap().height + 1;
3247
3255
3248
3256
if let Err((err_msg, code)) = check_incoming_htlc_cltv(
3249
- cur_height, outgoing_cltv_value, msg.cltv_expiry
3257
+ cur_height, next_packet_details. outgoing_cltv_value, msg.cltv_expiry
3250
3258
) {
3251
3259
if code & 0x1000 != 0 && chan_update_opt.is_none() {
3252
3260
// We really should set `incorrect_cltv_expiry` here but as we're not
@@ -3265,7 +3273,7 @@ where
3265
3273
msg, counterparty_node_id, err, code, chan_update, next_hop.is_intro_node_blinded_forward(), &shared_secret
3266
3274
));
3267
3275
}
3268
- Ok((next_hop, shared_secret, Some(next_packet_pubkey)))
3276
+ Ok((next_hop, shared_secret, Some(next_packet_details. next_packet_pubkey)))
3269
3277
}
3270
3278
3271
3279
fn construct_pending_htlc_status<'a>(
0 commit comments