Skip to content

Commit 09cf15e

Browse files
committed
ln+events: add htlc failure reason to HTLCHandlingFailed
1 parent 9f81f1f commit 09cf15e

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

lightning/src/events/mod.rs

+35-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS;
2626
use crate::offers::invoice::Bolt12Invoice;
2727
use crate::offers::static_invoice::StaticInvoice;
2828
use crate::types::features::ChannelTypeFeatures;
29-
use crate::ln::msgs;
29+
use crate::ln::{msgs, LocalHTLCFailureReason};
3030
use crate::ln::types::ChannelId;
3131
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
3232
use crate::onion_message::messenger::Responder;
@@ -525,6 +525,31 @@ impl_writeable_tlv_based_enum_upgradable!(HTLCHandlingType,
525525
},
526526
);
527527

528+
/// The reason for HTLC failures in [`Event::HTLCHandlingFailed`].
529+
#[derive(Clone, Debug, PartialEq, Eq)]
530+
pub enum HTLCHandlingFailureReason {
531+
/// The forwarded HTLC was failed back by the downstream node with an encrypted error reason.
532+
Downstream,
533+
/// The HTLC was failed locally by our node.
534+
Local {
535+
/// The reason that our node chose to fail the HTLC.
536+
reason: LocalHTLCFailureReason,
537+
},
538+
}
539+
540+
impl_writeable_tlv_based_enum!(HTLCHandlingFailureReason,
541+
(1, Downstream) => {},
542+
(3, Local) => {
543+
(0, reason, required),
544+
},
545+
);
546+
547+
impl From<LocalHTLCFailureReason> for HTLCHandlingFailureReason {
548+
fn from(value: LocalHTLCFailureReason) -> Self {
549+
HTLCHandlingFailureReason::Local { reason: value }
550+
}
551+
}
552+
528553
/// Will be used in [`Event::HTLCIntercepted`] to identify the next hop in the HTLC's path.
529554
/// Currently only used in serialization for the sake of maintaining compatibility. More variants
530555
/// will be added for general-purpose HTLC forward intercepts as well as trampoline forward
@@ -1462,6 +1487,10 @@ pub enum Event {
14621487
prev_channel_id: ChannelId,
14631488
/// The type of HTLC that was handled.
14641489
handling_type: HTLCHandlingType,
1490+
/// The reason that the HTLC failed.
1491+
///
1492+
/// This field will be `None` only for objects serialized prior to LDK 0.2.0.
1493+
handling_failure: Option<HTLCHandlingFailureReason>
14651494
},
14661495
/// Indicates that a transaction originating from LDK needs to have its fee bumped. This event
14671496
/// requires confirmed external funds to be readily available to spend.
@@ -1766,10 +1795,11 @@ impl Writeable for Event {
17661795
(8, path.blinded_tail, option),
17671796
})
17681797
},
1769-
&Event::HTLCHandlingFailed { ref prev_channel_id, ref handling_type } => {
1798+
&Event::HTLCHandlingFailed { ref prev_channel_id, ref handling_type, ref handling_failure } => {
17701799
25u8.write(writer)?;
17711800
write_tlv_fields!(writer, {
17721801
(0, prev_channel_id, required),
1802+
(1, handling_failure, option),
17731803
(2, handling_type, required),
17741804
})
17751805
},
@@ -2218,14 +2248,17 @@ impl MaybeReadable for Event {
22182248
25u8 => {
22192249
let mut f = || {
22202250
let mut prev_channel_id = ChannelId::new_zero();
2251+
let mut handling_failure = None;
22212252
let mut handling_type_opt = UpgradableRequired(None);
22222253
read_tlv_fields!(reader, {
22232254
(0, prev_channel_id, required),
2255+
(1, handling_failure, option),
22242256
(2, handling_type_opt, upgradable_required),
22252257
});
22262258
Ok(Some(Event::HTLCHandlingFailed {
22272259
prev_channel_id,
22282260
handling_type: _init_tlv_based_struct_field!(handling_type_opt, upgradable_required),
2261+
handling_failure,
22292262
}))
22302263
};
22312264
f()

lightning/src/ln/channelmanager.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -5787,8 +5787,8 @@ where
57875787
&update_add_htlc, &*self.node_signer, &*self.logger, &self.secp_ctx
57885788
) {
57895789
Ok(decoded_onion) => decoded_onion,
5790-
Err((htlc_fail, _)) => {
5791-
htlc_fails.push((htlc_fail, HTLCHandlingType::InvalidOnion));
5790+
Err((htlc_fail, reason)) => {
5791+
htlc_fails.push((htlc_fail, HTLCHandlingType::InvalidOnion, reason.into()));
57925792
continue;
57935793
},
57945794
};
@@ -5816,7 +5816,7 @@ where
58165816
is_intro_node_blinded_forward, &shared_secret,
58175817
);
58185818
let handling_type = get_failed_htlc_type(outgoing_scid_opt, update_add_htlc.payment_hash);
5819-
htlc_fails.push((htlc_fail, handling_type));
5819+
htlc_fails.push((htlc_fail, handling_type, reason.into()));
58205820
continue;
58215821
},
58225822
// The incoming channel no longer exists, HTLCs should be resolved onchain instead.
@@ -5833,7 +5833,7 @@ where
58335833
is_intro_node_blinded_forward, &shared_secret,
58345834
);
58355835
let handling_type = get_failed_htlc_type(outgoing_scid_opt, update_add_htlc.payment_hash);
5836-
htlc_fails.push((htlc_fail, handling_type));
5836+
htlc_fails.push((htlc_fail, handling_type, reason.into()));
58375837
continue;
58385838
}
58395839
}
@@ -5845,8 +5845,9 @@ where
58455845
Ok(info) => htlc_forwards.push((info, update_add_htlc.htlc_id)),
58465846
Err(inbound_err) => {
58475847
let handling_type = get_failed_htlc_type(outgoing_scid_opt, update_add_htlc.payment_hash);
5848+
let htlc_failure = inbound_err.reason.into();
58485849
let htlc_fail = self.construct_pending_htlc_fail_msg(&update_add_htlc, &incoming_counterparty_node_id, shared_secret, inbound_err);
5849-
htlc_fails.push((htlc_fail, handling_type));
5850+
htlc_fails.push((htlc_fail, handling_type, htlc_failure));
58505851
},
58515852
}
58525853
}
@@ -5858,7 +5859,7 @@ where
58585859
incoming_channel_id, incoming_user_channel_id, htlc_forwards.drain(..).collect()
58595860
);
58605861
self.forward_htlcs_without_forward_event(&mut [pending_forwards]);
5861-
for (htlc_fail, handling_type) in htlc_fails.drain(..) {
5862+
for (htlc_fail, handling_type, handling_failure) in htlc_fails.drain(..) {
58625863
let failure = match htlc_fail {
58635864
HTLCFailureMsg::Relay(fail_htlc) => HTLCForwardInfo::FailHTLC {
58645865
htlc_id: fail_htlc.htlc_id,
@@ -5874,6 +5875,7 @@ where
58745875
self.pending_events.lock().unwrap().push_back((events::Event::HTLCHandlingFailed {
58755876
prev_channel_id: incoming_channel_id,
58765877
handling_type,
5878+
handling_failure: Some(handling_failure),
58775879
}, None));
58785880
}
58795881
}
@@ -7054,6 +7056,7 @@ where
70547056
pending_events.push_back((events::Event::HTLCHandlingFailed {
70557057
prev_channel_id: *channel_id,
70567058
handling_type,
7059+
handling_failure: Some(onion_error.into()),
70577060
}, None));
70587061
},
70597062
}

lightning/src/ln/onion_utils.rs

+12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use super::msgs::OnionErrorPacket;
1111
use crate::blinded_path::BlindedHop;
1212
use crate::crypto::chacha20::ChaCha20;
1313
use crate::crypto::streams::ChaChaReader;
14+
use crate::events::HTLCHandlingFailureReason;
1415
use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS;
1516
use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields};
1617
use crate::ln::msgs;
@@ -1761,6 +1762,17 @@ impl_writeable_tlv_based_enum!(LocalHTLCFailureReason,
17611762
(85, PeerOffline) => {},
17621763
);
17631764

1765+
impl From<&HTLCFailReason> for HTLCHandlingFailureReason {
1766+
fn from(value: &HTLCFailReason) -> Self {
1767+
match value.0 {
1768+
HTLCFailReasonRepr::LightningError { .. } => HTLCHandlingFailureReason::Downstream,
1769+
HTLCFailReasonRepr::Reason { failure_reason, .. } => {
1770+
HTLCHandlingFailureReason::Local { reason: failure_reason }
1771+
},
1772+
}
1773+
}
1774+
}
1775+
17641776
#[derive(Clone)] // See Channel::revoke_and_ack for why, tl;dr: Rust bug
17651777
#[cfg_attr(test, derive(PartialEq))]
17661778
pub(super) struct HTLCFailReason(HTLCFailReasonRepr);

0 commit comments

Comments
 (0)