Skip to content

Commit d1289ce

Browse files
committed
ln+events: add htlc failure reason to HTLCHandlingFailed
1 parent 99bcd69 commit d1289ce

File tree

3 files changed

+57
-8
lines changed

3 files changed

+57
-8
lines changed

lightning/src/events/mod.rs

Lines changed: 35 additions & 2 deletions
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!(HTLCHandlingFailureType,
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 handling that failed.
14641489
failure_type: HTLCHandlingFailureType,
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+
failure_reason: 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 failure_type } => {
1798+
&Event::HTLCHandlingFailed { ref prev_channel_id, ref failure_type, ref failure_reason } => {
17701799
25u8.write(writer)?;
17711800
write_tlv_fields!(writer, {
17721801
(0, prev_channel_id, required),
1802+
(1, failure_reason, option),
17731803
(2, failure_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 failure_reason = None;
22212252
let mut failure_type_opt = UpgradableRequired(None);
22222253
read_tlv_fields!(reader, {
22232254
(0, prev_channel_id, required),
2255+
(1, failure_reason, option),
22242256
(2, failure_type_opt, upgradable_required),
22252257
});
22262258
Ok(Some(Event::HTLCHandlingFailed {
22272259
prev_channel_id,
22282260
failure_type: _init_tlv_based_struct_field!(failure_type_opt, upgradable_required),
2261+
failure_reason,
22292262
}))
22302263
};
22312264
f()

lightning/src/ln/channelmanager.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5787,8 +5787,9 @@ 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, HTLCHandlingFailureType::InvalidOnion));
5790+
5791+
Err((htlc_fail, reason)) => {
5792+
htlc_fails.push((htlc_fail, HTLCHandlingFailureType::InvalidOnion, reason.into()));
57925793
continue;
57935794
},
57945795
};
@@ -5816,7 +5817,7 @@ where
58165817
is_intro_node_blinded_forward, &shared_secret,
58175818
);
58185819
let failure_type = get_htlc_failure_type(outgoing_scid_opt, update_add_htlc.payment_hash);
5819-
htlc_fails.push((htlc_fail, failure_type));
5820+
htlc_fails.push((htlc_fail, failure_type, reason.into()));
58205821
continue;
58215822
},
58225823
// The incoming channel no longer exists, HTLCs should be resolved onchain instead.
@@ -5833,7 +5834,7 @@ where
58335834
is_intro_node_blinded_forward, &shared_secret,
58345835
);
58355836
let failure_type = get_htlc_failure_type(outgoing_scid_opt, update_add_htlc.payment_hash);
5836-
htlc_fails.push((htlc_fail, failure_type));
5837+
htlc_fails.push((htlc_fail, failure_type, reason.into()));
58375838
continue;
58385839
}
58395840
}
@@ -5845,8 +5846,9 @@ where
58455846
Ok(info) => htlc_forwards.push((info, update_add_htlc.htlc_id)),
58465847
Err(inbound_err) => {
58475848
let failure_type = get_htlc_failure_type(outgoing_scid_opt, update_add_htlc.payment_hash);
5849+
let htlc_failure = inbound_err.reason.into();
58485850
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, failure_type));
5851+
htlc_fails.push((htlc_fail, failure_type, htlc_failure));
58505852
},
58515853
}
58525854
}
@@ -5858,7 +5860,7 @@ where
58585860
incoming_channel_id, incoming_user_channel_id, htlc_forwards.drain(..).collect()
58595861
);
58605862
self.forward_htlcs_without_forward_event(&mut [pending_forwards]);
5861-
for (htlc_fail, failure_type) in htlc_fails.drain(..) {
5863+
for (htlc_fail, failure_type, failure_reason) in htlc_fails.drain(..) {
58625864
let failure = match htlc_fail {
58635865
HTLCFailureMsg::Relay(fail_htlc) => HTLCForwardInfo::FailHTLC {
58645866
htlc_id: fail_htlc.htlc_id,
@@ -5874,6 +5876,7 @@ where
58745876
self.pending_events.lock().unwrap().push_back((events::Event::HTLCHandlingFailed {
58755877
prev_channel_id: incoming_channel_id,
58765878
failure_type,
5879+
failure_reason: Some(failure_reason),
58775880
}, None));
58785881
}
58795882
}
@@ -7054,6 +7057,7 @@ where
70547057
pending_events.push_back((events::Event::HTLCHandlingFailed {
70557058
prev_channel_id: *channel_id,
70567059
failure_type,
7060+
failure_reason: Some(onion_error.into()),
70577061
}, None));
70587062
},
70597063
}

lightning/src/ln/onion_utils.rs

Lines changed: 12 additions & 0 deletions
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)