Skip to content

Commit d718096

Browse files
committed
Refactor HTLC acceptance checks out from decode_update_add_htlc_onion
This refactor improves its readability, it does not feature any functional changes.
1 parent fafea19 commit d718096

File tree

1 file changed

+51
-43
lines changed

1 file changed

+51
-43
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3020,6 +3020,48 @@ where
30203020
}
30213021
}
30223022

3023+
fn can_accept_htlc(
3024+
&self, chan: &mut Channel<SP>, msg: &msgs::UpdateAddHTLC, next_packet: &NextPacketDetails
3025+
) -> Result<Option<msgs::ChannelUpdate>, (&'static str, u16, Option<msgs::ChannelUpdate>)> {
3026+
if !chan.context.should_announce() && !self.default_configuration.accept_forwards_to_priv_channels {
3027+
// Note that the behavior here should be identical to the above block - we
3028+
// should NOT reveal the existence or non-existence of a private channel if
3029+
// we don't allow forwards outbound over them.
3030+
return Err(("Refusing to forward to a private channel based on our config.", 0x4000 | 10, None));
3031+
}
3032+
if chan.context.get_channel_type().supports_scid_privacy() && next_packet.outgoing_scid != chan.context.outbound_scid_alias() {
3033+
// `option_scid_alias` (referred to in LDK as `scid_privacy`) means
3034+
// "refuse to forward unless the SCID alias was used", so we pretend
3035+
// we don't have the channel here.
3036+
return Err(("Refusing to forward over real channel SCID as our counterparty requested.", 0x4000 | 10, None));
3037+
}
3038+
let chan_update_opt = self.get_channel_update_for_onion(next_packet.outgoing_scid, chan).ok();
3039+
3040+
// Note that we could technically not return an error yet here and just hope
3041+
// that the connection is reestablished or monitor updated by the time we get
3042+
// around to doing the actual forward, but better to fail early if we can and
3043+
// hopefully an attacker trying to path-trace payments cannot make this occur
3044+
// on a small/per-node/per-channel scale.
3045+
if !chan.context.is_live() { // channel_disabled
3046+
// If the channel_update we're going to return is disabled (i.e. the
3047+
// peer has been disabled for some time), return `channel_disabled`,
3048+
// otherwise return `temporary_channel_failure`.
3049+
if chan_update_opt.as_ref().map(|u| u.contents.flags & 2 == 2).unwrap_or(false) {
3050+
return Err(("Forwarding channel has been disconnected for some time.", 0x1000 | 20, chan_update_opt));
3051+
} else {
3052+
return Err(("Forwarding channel is not in a ready state.", 0x1000 | 7, chan_update_opt));
3053+
}
3054+
}
3055+
if next_packet.outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { // amount_below_minimum
3056+
return Err(("HTLC amount was below the htlc_minimum_msat", 0x1000 | 11, chan_update_opt));
3057+
}
3058+
if let Err((err, code)) = chan.htlc_satisfies_config(msg, next_packet.outgoing_amt_msat, next_packet.outgoing_cltv_value) {
3059+
return Err((err, code, chan_update_opt));
3060+
}
3061+
3062+
Ok(chan_update_opt)
3063+
}
3064+
30233065
fn process_failed_accept_err(
30243066
&self, msg: &msgs::UpdateAddHTLC, counterparty_node_id: &PublicKey, err_msg: &'static str,
30253067
mut err_code: u16, chan_update: Option<msgs::ChannelUpdate>, is_intro_node_forward: bool,
@@ -3093,9 +3135,7 @@ where
30933135
_ => false,
30943136
};
30953137

3096-
let NextPacketDetails {
3097-
next_packet_pubkey, outgoing_amt_msat, outgoing_scid, outgoing_cltv_value
3098-
} = match next_packet_details_opt {
3138+
let next_packet_details = match next_packet_details_opt {
30993139
Some(next_packet_details) => next_packet_details,
31003140
// it is a receive, so no need for outbound checks
31013141
None => return Ok((next_hop, shared_secret, None)),
@@ -3104,14 +3144,14 @@ where
31043144
// Perform outbound checks here instead of in [`Self::construct_pending_htlc_info`] because we
31053145
// can't hold the outbound peer state lock at the same time as the inbound peer state lock.
31063146
if let Some((err, code, chan_update)) = loop {
3107-
let id_option = self.short_to_chan_info.read().unwrap().get(&outgoing_scid).cloned();
3147+
let id_option = self.short_to_chan_info.read().unwrap().get(&next_packet_details.outgoing_scid).cloned();
31083148
let forwarding_chan_info_opt = match id_option {
31093149
None => { // unknown_next_peer
31103150
// Note that this is likely a timing oracle for detecting whether an scid is a
31113151
// phantom or an intercept.
31123152
if (self.default_configuration.accept_intercept_htlcs &&
3113-
fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, outgoing_scid, &self.chain_hash)) ||
3114-
fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, outgoing_scid, &self.chain_hash)
3153+
fake_scid::is_valid_intercept(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)) ||
3154+
fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, next_packet_details.outgoing_scid, &self.chain_hash)
31153155
{
31163156
None
31173157
} else {
@@ -3138,50 +3178,18 @@ where
31383178
},
31393179
Some(chan) => chan
31403180
};
3141-
if !chan.context.should_announce() && !self.default_configuration.accept_forwards_to_priv_channels {
3142-
// Note that the behavior here should be identical to the above block - we
3143-
// should NOT reveal the existence or non-existence of a private channel if
3144-
// we don't allow forwards outbound over them.
3145-
break Some(("Refusing to forward to a private channel based on our config.", 0x4000 | 10, None));
3146-
}
3147-
if chan.context.get_channel_type().supports_scid_privacy() && outgoing_scid != chan.context.outbound_scid_alias() {
3148-
// `option_scid_alias` (referred to in LDK as `scid_privacy`) means
3149-
// "refuse to forward unless the SCID alias was used", so we pretend
3150-
// we don't have the channel here.
3151-
break Some(("Refusing to forward over real channel SCID as our counterparty requested.", 0x4000 | 10, None));
3152-
}
3153-
let chan_update_opt = self.get_channel_update_for_onion(outgoing_scid, chan).ok();
3154-
3155-
// Note that we could technically not return an error yet here and just hope
3156-
// that the connection is reestablished or monitor updated by the time we get
3157-
// around to doing the actual forward, but better to fail early if we can and
3158-
// hopefully an attacker trying to path-trace payments cannot make this occur
3159-
// on a small/per-node/per-channel scale.
3160-
if !chan.context.is_live() { // channel_disabled
3161-
// If the channel_update we're going to return is disabled (i.e. the
3162-
// peer has been disabled for some time), return `channel_disabled`,
3163-
// otherwise return `temporary_channel_failure`.
3164-
if chan_update_opt.as_ref().map(|u| u.contents.flags & 2 == 2).unwrap_or(false) {
3165-
break Some(("Forwarding channel has been disconnected for some time.", 0x1000 | 20, chan_update_opt));
3166-
} else {
3167-
break Some(("Forwarding channel is not in a ready state.", 0x1000 | 7, chan_update_opt));
3168-
}
3169-
}
3170-
if outgoing_amt_msat < chan.context.get_counterparty_htlc_minimum_msat() { // amount_below_minimum
3171-
break Some(("HTLC amount was below the htlc_minimum_msat", 0x1000 | 11, chan_update_opt));
3172-
}
3173-
if let Err((err, code)) = chan.htlc_satisfies_config(&msg, outgoing_amt_msat, outgoing_cltv_value) {
3174-
break Some((err, code, chan_update_opt));
3181+
match self.can_accept_htlc(chan, msg, &next_packet_details) {
3182+
Ok(chan_update_opt) => chan_update_opt,
3183+
Err(e) => break Some(e),
31753184
}
3176-
chan_update_opt
31773185
} else {
31783186
None
31793187
};
31803188

31813189
let cur_height = self.best_block.read().unwrap().height() + 1;
31823190

31833191
if let Err((err_msg, code)) = check_incoming_htlc_cltv(
3184-
cur_height, outgoing_cltv_value, msg.cltv_expiry
3192+
cur_height, next_packet_details.outgoing_cltv_value, msg.cltv_expiry
31853193
) {
31863194
if code & 0x1000 != 0 && chan_update_opt.is_none() {
31873195
// We really should set `incorrect_cltv_expiry` here but as we're not
@@ -3200,7 +3208,7 @@ where
32003208
msg, counterparty_node_id, err, code, chan_update, is_intro_node_forward, &shared_secret
32013209
));
32023210
}
3203-
Ok((next_hop, shared_secret, Some(next_packet_pubkey)))
3211+
Ok((next_hop, shared_secret, Some(next_packet_details.next_packet_pubkey)))
32043212
}
32053213

32063214
fn construct_pending_htlc_status<'a>(

0 commit comments

Comments
 (0)