Skip to content

Commit dabae73

Browse files
committed
Move HTLCFailReason to onion_utils
Now that it's entirely abstracted, there's no reason for `HTLCFailReason` to be in `channelmanager`, it's really an onion-level abstraction.
1 parent 4ba8338 commit dabae73

File tree

3 files changed

+89
-87
lines changed

3 files changed

+89
-87
lines changed

lightning/src/ln/channel.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ use crate::ln::features::{ChannelTypeFeatures, InitFeatures};
2727
use crate::ln::msgs;
2828
use crate::ln::msgs::{DecodeError, OptionalField, DataLossProtect};
2929
use crate::ln::script::{self, ShutdownScript};
30-
use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
30+
use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
3131
use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
3232
use crate::ln::chan_utils;
33+
use crate::ln::onion_utils::HTLCFailReason;
3334
use crate::chain::BestBlock;
3435
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
3536
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use crate::ln::features::InvoiceFeatures;
4949
use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteHop, RoutePath, RouteParameters};
5050
use crate::ln::msgs;
5151
use crate::ln::onion_utils;
52+
use crate::ln::onion_utils::HTLCFailReason;
5253
use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT};
5354
use crate::ln::wire::Encode;
5455
use crate::chain::keysinterface::{Sign, KeysInterface, KeysManager, Recipient};
@@ -276,82 +277,6 @@ impl HTLCSource {
276277
}
277278
}
278279

279-
#[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
280-
pub(super) enum HTLCFailReason {
281-
LightningError {
282-
err: msgs::OnionErrorPacket,
283-
},
284-
Reason {
285-
failure_code: u16,
286-
data: Vec<u8>,
287-
}
288-
}
289-
290-
impl core::fmt::Debug for HTLCFailReason {
291-
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
292-
match self {
293-
HTLCFailReason::Reason { ref failure_code, .. } => {
294-
write!(f, "HTLC error code {}", failure_code)
295-
},
296-
HTLCFailReason::LightningError { .. } => {
297-
write!(f, "pre-built LightningError")
298-
}
299-
}
300-
}
301-
}
302-
303-
impl HTLCFailReason {
304-
pub(super) fn reason(failure_code: u16, data: Vec<u8>) -> Self {
305-
Self::Reason { failure_code, data }
306-
}
307-
308-
pub(super) fn from_failure_code(failure_code: u16) -> Self {
309-
Self::Reason { failure_code, data: Vec::new() }
310-
}
311-
312-
pub(super) fn from_msg(msg: &msgs::UpdateFailHTLC) -> Self {
313-
Self::LightningError { err: msg.reason.clone() }
314-
}
315-
316-
fn get_encrypted_failure_packet(&self, incoming_packet_shared_secret: &[u8; 32], phantom_shared_secret: &Option<[u8; 32]>) -> msgs::OnionErrorPacket {
317-
match self {
318-
HTLCFailReason::Reason { ref failure_code, ref data } => {
319-
if let Some(phantom_ss) = phantom_shared_secret {
320-
let phantom_packet = onion_utils::build_failure_packet(phantom_ss, *failure_code, &data[..]).encode();
321-
let encrypted_phantom_packet = onion_utils::encrypt_failure_packet(phantom_ss, &phantom_packet);
322-
onion_utils::encrypt_failure_packet(incoming_packet_shared_secret, &encrypted_phantom_packet.data[..])
323-
} else {
324-
let packet = onion_utils::build_failure_packet(incoming_packet_shared_secret, *failure_code, &data[..]).encode();
325-
onion_utils::encrypt_failure_packet(incoming_packet_shared_secret, &packet)
326-
}
327-
},
328-
HTLCFailReason::LightningError { err } => {
329-
onion_utils::encrypt_failure_packet(incoming_packet_shared_secret, &err.data)
330-
}
331-
}
332-
}
333-
334-
fn decode_onion_failure<T: secp256k1::Signing, L: Deref>(&self, secp_ctx: &Secp256k1<T>, logger: &L, htlc_source: &HTLCSource) -> (Option<crate::routing::gossip::NetworkUpdate>, Option<u64>, bool, Option<u16>, Option<Vec<u8>>) where L::Target: Logger {
335-
match self {
336-
HTLCFailReason::LightningError { ref err } => {
337-
onion_utils::process_onion_failure(secp_ctx, logger, &htlc_source, err.data.clone())
338-
},
339-
HTLCFailReason::Reason { ref failure_code, ref data, .. } => {
340-
// we get a fail_malformed_htlc from the first hop
341-
// TODO: We'd like to generate a NetworkUpdate for temporary
342-
// failures here, but that would be insufficient as find_route
343-
// generally ignores its view of our own channels as we provide them via
344-
// ChannelDetails.
345-
// TODO: For non-temporary failures, we really should be closing the
346-
// channel here as we apparently can't relay through them anyway.
347-
if let &HTLCSource::OutboundRoute { ref path, .. } = htlc_source {
348-
(None, Some(path.first().unwrap().short_channel_id), true, Some(*failure_code), Some(data.clone()))
349-
} else { unreachable!(); }
350-
}
351-
}
352-
}
353-
}
354-
355280
struct ReceiveError {
356281
err_code: u16,
357282
err_data: Vec<u8>,
@@ -7031,16 +6956,6 @@ impl Writeable for HTLCSource {
70316956
}
70326957
}
70336958

7034-
impl_writeable_tlv_based_enum!(HTLCFailReason,
7035-
(0, LightningError) => {
7036-
(0, err, required),
7037-
},
7038-
(1, Reason) => {
7039-
(0, failure_code, required),
7040-
(2, data, vec_type),
7041-
},
7042-
;);
7043-
70446959
impl_writeable_tlv_based!(PendingAddHTLCInfo, {
70456960
(0, forward_info, required),
70466961
(1, prev_user_channel_id, (default_value, 0)),

lightning/src/ln/onion_utils.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,92 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
592592
} else { unreachable!(); }
593593
}
594594

595+
#[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
596+
pub(super) enum HTLCFailReason {
597+
LightningError {
598+
err: msgs::OnionErrorPacket,
599+
},
600+
Reason {
601+
failure_code: u16,
602+
data: Vec<u8>,
603+
}
604+
}
605+
606+
impl core::fmt::Debug for HTLCFailReason {
607+
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
608+
match self {
609+
HTLCFailReason::Reason { ref failure_code, .. } => {
610+
write!(f, "HTLC error code {}", failure_code)
611+
},
612+
HTLCFailReason::LightningError { .. } => {
613+
write!(f, "pre-built LightningError")
614+
}
615+
}
616+
}
617+
}
618+
619+
impl_writeable_tlv_based_enum!(HTLCFailReason,
620+
(0, LightningError) => {
621+
(0, err, required),
622+
},
623+
(1, Reason) => {
624+
(0, failure_code, required),
625+
(2, data, vec_type),
626+
},
627+
;);
628+
629+
impl HTLCFailReason {
630+
pub(super) fn reason(failure_code: u16, data: Vec<u8>) -> Self {
631+
Self::Reason { failure_code, data }
632+
}
633+
634+
pub(super) fn from_failure_code(failure_code: u16) -> Self {
635+
Self::Reason { failure_code, data: Vec::new() }
636+
}
637+
638+
pub(super) fn from_msg(msg: &msgs::UpdateFailHTLC) -> Self {
639+
Self::LightningError { err: msg.reason.clone() }
640+
}
641+
642+
pub(super) fn get_encrypted_failure_packet(&self, incoming_packet_shared_secret: &[u8; 32], phantom_shared_secret: &Option<[u8; 32]>) -> msgs::OnionErrorPacket {
643+
match self {
644+
HTLCFailReason::Reason { ref failure_code, ref data } => {
645+
if let Some(phantom_ss) = phantom_shared_secret {
646+
let phantom_packet = build_failure_packet(phantom_ss, *failure_code, &data[..]).encode();
647+
let encrypted_phantom_packet = encrypt_failure_packet(phantom_ss, &phantom_packet);
648+
encrypt_failure_packet(incoming_packet_shared_secret, &encrypted_phantom_packet.data[..])
649+
} else {
650+
let packet = build_failure_packet(incoming_packet_shared_secret, *failure_code, &data[..]).encode();
651+
encrypt_failure_packet(incoming_packet_shared_secret, &packet)
652+
}
653+
},
654+
HTLCFailReason::LightningError { err } => {
655+
encrypt_failure_packet(incoming_packet_shared_secret, &err.data)
656+
}
657+
}
658+
}
659+
660+
pub(super) fn decode_onion_failure<T: secp256k1::Signing, L: Deref>(&self, secp_ctx: &Secp256k1<T>, logger: &L, htlc_source: &HTLCSource) -> (Option<crate::routing::gossip::NetworkUpdate>, Option<u64>, bool, Option<u16>, Option<Vec<u8>>) where L::Target: Logger {
661+
match self {
662+
HTLCFailReason::LightningError { ref err } => {
663+
process_onion_failure(secp_ctx, logger, &htlc_source, err.data.clone())
664+
},
665+
HTLCFailReason::Reason { ref failure_code, ref data, .. } => {
666+
// we get a fail_malformed_htlc from the first hop
667+
// TODO: We'd like to generate a NetworkUpdate for temporary
668+
// failures here, but that would be insufficient as find_route
669+
// generally ignores its view of our own channels as we provide them via
670+
// ChannelDetails.
671+
// TODO: For non-temporary failures, we really should be closing the
672+
// channel here as we apparently can't relay through them anyway.
673+
if let &HTLCSource::OutboundRoute { ref path, .. } = htlc_source {
674+
(None, Some(path.first().unwrap().short_channel_id), true, Some(*failure_code), Some(data.clone()))
675+
} else { unreachable!(); }
676+
}
677+
}
678+
}
679+
}
680+
595681
/// Allows `decode_next_hop` to return the next hop packet bytes for either payments or onion
596682
/// message forwards.
597683
pub(crate) trait NextPacketBytes: AsMut<[u8]> {

0 commit comments

Comments
 (0)