Skip to content

Commit 6f065ba

Browse files
Merge pull request #3700 from carlaKC/3541-api-changes
(3/3) Add Failure Reason to HTLCHandlingFailed
2 parents 559a784 + af301f4 commit 6f065ba

19 files changed

+320
-251
lines changed

lightning-liquidity/src/lsps2/service.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::prelude::hash_map::Entry;
3131
use crate::prelude::{new_hash_map, HashMap};
3232
use crate::sync::{Arc, Mutex, MutexGuard, RwLock};
3333

34-
use lightning::events::HTLCDestination;
34+
use lightning::events::HTLCHandlingFailureType;
3535
use lightning::ln::channelmanager::{AChannelManager, InterceptId};
3636
use lightning::ln::msgs::{ErrorAction, LightningError};
3737
use lightning::ln::types::ChannelId;
@@ -863,9 +863,9 @@ where
863863
///
864864
/// [`Event::HTLCHandlingFailed`]: lightning::events::Event::HTLCHandlingFailed
865865
pub fn htlc_handling_failed(
866-
&self, failed_next_destination: HTLCDestination,
866+
&self, failure_type: HTLCHandlingFailureType,
867867
) -> Result<(), APIError> {
868-
if let HTLCDestination::NextHopChannel { channel_id, .. } = failed_next_destination {
868+
if let HTLCHandlingFailureType::Forward { channel_id, .. } = failure_type {
869869
let peer_by_channel_id = self.peer_by_channel_id.read().unwrap();
870870
if let Some(counterparty_node_id) = peer_by_channel_id.get(&channel_id) {
871871
let outer_state_lock = self.per_peer_state.read().unwrap();

lightning/src/events/mod.rs

+60-15
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;
@@ -466,12 +466,12 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
466466
},
467467
);
468468

469-
/// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`].
469+
/// The type of HTLC handling performed in [`Event::HTLCHandlingFailed`].
470470
#[derive(Clone, Debug, PartialEq, Eq)]
471-
pub enum HTLCDestination {
471+
pub enum HTLCHandlingFailureType {
472472
/// We tried forwarding to a channel but failed to do so. An example of such an instance is when
473473
/// there is insufficient capacity in our outbound channel.
474-
NextHopChannel {
474+
Forward {
475475
/// The `node_id` of the next node. For backwards compatibility, this field is
476476
/// marked as optional, versions prior to 0.0.110 may not always be able to provide
477477
/// counterparty node information.
@@ -480,12 +480,17 @@ pub enum HTLCDestination {
480480
channel_id: ChannelId,
481481
},
482482
/// Scenario where we are unsure of the next node to forward the HTLC to.
483+
///
484+
/// Deprecated: will only be used in versions before LDK v0.2.0. Downgrades will result in
485+
/// this type being represented as [`Self::InvalidForward`].
483486
UnknownNextHop {
484487
/// Short channel id we are requesting to forward an HTLC to.
485488
requested_forward_scid: u64,
486489
},
487490
/// We couldn't forward to the outgoing scid. An example would be attempting to send a duplicate
488491
/// intercept HTLC.
492+
///
493+
/// In LDK v0.2.0 and greater, this variant replaces [`Self::UnknownNextHop`].
489494
InvalidForward {
490495
/// Short channel id we are requesting to forward an HTLC to.
491496
requested_forward_scid: u64
@@ -502,14 +507,14 @@ pub enum HTLCDestination {
502507
/// * The counterparty node modified the HTLC in transit,
503508
/// * A probing attack where an intermediary node is trying to detect if we are the ultimate
504509
/// recipient for a payment.
505-
FailedPayment {
510+
Receive {
506511
/// The payment hash of the payment we attempted to process.
507512
payment_hash: PaymentHash
508513
},
509514
}
510515

511-
impl_writeable_tlv_based_enum_upgradable!(HTLCDestination,
512-
(0, NextHopChannel) => {
516+
impl_writeable_tlv_based_enum_upgradable!(HTLCHandlingFailureType,
517+
(0, Forward) => {
513518
(0, node_id, required),
514519
(2, channel_id, required),
515520
},
@@ -520,11 +525,36 @@ impl_writeable_tlv_based_enum_upgradable!(HTLCDestination,
520525
(0, requested_forward_scid, required),
521526
},
522527
(3, InvalidOnion) => {},
523-
(4, FailedPayment) => {
528+
(4, Receive) => {
524529
(0, payment_hash, required),
525530
},
526531
);
527532

533+
/// The reason for HTLC failures in [`Event::HTLCHandlingFailed`].
534+
#[derive(Clone, Debug, PartialEq, Eq)]
535+
pub enum HTLCHandlingFailureReason {
536+
/// The forwarded HTLC was failed back by the downstream node with an encrypted error reason.
537+
Downstream,
538+
/// The HTLC was failed locally by our node.
539+
Local {
540+
/// The reason that our node chose to fail the HTLC.
541+
reason: LocalHTLCFailureReason,
542+
},
543+
}
544+
545+
impl_writeable_tlv_based_enum!(HTLCHandlingFailureReason,
546+
(1, Downstream) => {},
547+
(3, Local) => {
548+
(0, reason, required),
549+
},
550+
);
551+
552+
impl From<LocalHTLCFailureReason> for HTLCHandlingFailureReason {
553+
fn from(value: LocalHTLCFailureReason) -> Self {
554+
HTLCHandlingFailureReason::Local { reason: value }
555+
}
556+
}
557+
528558
/// Will be used in [`Event::HTLCIntercepted`] to identify the next hop in the HTLC's path.
529559
/// Currently only used in serialization for the sake of maintaining compatibility. More variants
530560
/// will be added for general-purpose HTLC forward intercepts as well as trampoline forward
@@ -1460,8 +1490,12 @@ pub enum Event {
14601490
HTLCHandlingFailed {
14611491
/// The channel over which the HTLC was received.
14621492
prev_channel_id: ChannelId,
1463-
/// Destination of the HTLC that failed to be processed.
1464-
failed_next_destination: HTLCDestination,
1493+
/// The type of HTLC handling that failed.
1494+
failure_type: HTLCHandlingFailureType,
1495+
/// The reason that the HTLC failed.
1496+
///
1497+
/// This field will be `None` only for objects serialized prior to LDK 0.2.0.
1498+
failure_reason: Option<HTLCHandlingFailureReason>
14651499
},
14661500
/// Indicates that a transaction originating from LDK needs to have its fee bumped. This event
14671501
/// requires confirmed external funds to be readily available to spend.
@@ -1766,11 +1800,12 @@ impl Writeable for Event {
17661800
(8, path.blinded_tail, option),
17671801
})
17681802
},
1769-
&Event::HTLCHandlingFailed { ref prev_channel_id, ref failed_next_destination } => {
1803+
&Event::HTLCHandlingFailed { ref prev_channel_id, ref failure_type, ref failure_reason } => {
17701804
25u8.write(writer)?;
17711805
write_tlv_fields!(writer, {
17721806
(0, prev_channel_id, required),
1773-
(2, failed_next_destination, required),
1807+
(1, failure_reason, option),
1808+
(2, failure_type, required),
17741809
})
17751810
},
17761811
&Event::BumpTransaction(ref event)=> {
@@ -2218,14 +2253,24 @@ impl MaybeReadable for Event {
22182253
25u8 => {
22192254
let mut f = || {
22202255
let mut prev_channel_id = ChannelId::new_zero();
2221-
let mut failed_next_destination_opt = UpgradableRequired(None);
2256+
let mut failure_reason = None;
2257+
let mut failure_type_opt = UpgradableRequired(None);
22222258
read_tlv_fields!(reader, {
22232259
(0, prev_channel_id, required),
2224-
(2, failed_next_destination_opt, upgradable_required),
2260+
(1, failure_reason, option),
2261+
(2, failure_type_opt, upgradable_required),
22252262
});
2263+
2264+
// If a legacy HTLCHandlingFailureType::UnknownNextHop was written, upgrade
2265+
// it to its new representation, otherwise leave unchanged.
2266+
if let Some(HTLCHandlingFailureType::UnknownNextHop { requested_forward_scid }) = failure_type_opt.0 {
2267+
failure_type_opt.0 = Some(HTLCHandlingFailureType::InvalidForward { requested_forward_scid });
2268+
failure_reason = Some(LocalHTLCFailureReason::UnknownNextPeer.into());
2269+
}
22262270
Ok(Some(Event::HTLCHandlingFailed {
22272271
prev_channel_id,
2228-
failed_next_destination: _init_tlv_based_struct_field!(failed_next_destination_opt, upgradable_required),
2272+
failure_type: _init_tlv_based_struct_field!(failure_type_opt, upgradable_required),
2273+
failure_reason
22292274
}))
22302275
};
22312276
f()

lightning/src/ln/async_payments_tests.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::blinded_path::message::{MessageContext, OffersContext};
1111
use crate::blinded_path::payment::PaymentContext;
1212
use crate::blinded_path::payment::{AsyncBolt12OfferContext, BlindedPaymentTlvs};
1313
use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
14-
use crate::events::{Event, HTLCDestination, PaidBolt12Invoice, PaymentFailureReason};
14+
use crate::events::{Event, HTLCHandlingFailureType, PaidBolt12Invoice, PaymentFailureReason};
1515
use crate::ln::blinded_payment_tests::{fail_blinded_htlc_backwards, get_blinded_route_parameters};
1616
use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
1717
use crate::ln::functional_test_utils::*;
@@ -172,7 +172,7 @@ fn invalid_keysend_payment_secret() {
172172
PassAlongPathArgs::new(&nodes[0], &expected_route[0], amt_msat, payment_hash, ev.clone())
173173
.with_payment_secret(invalid_payment_secret)
174174
.with_payment_preimage(keysend_preimage)
175-
.expect_failure(HTLCDestination::FailedPayment { payment_hash });
175+
.expect_failure(HTLCHandlingFailureType::Receive { payment_hash });
176176
do_pass_along_path(args);
177177

178178
let updates_2_1 = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
@@ -701,7 +701,7 @@ fn amount_doesnt_match_invreq() {
701701
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
702702
.with_payment_preimage(keysend_preimage)
703703
.without_claimable_event()
704-
.expect_failure(HTLCDestination::FailedPayment { payment_hash });
704+
.expect_failure(HTLCHandlingFailureType::Receive { payment_hash });
705705
do_pass_along_path(args);
706706

707707
// Modify the invoice request stored in our outbounds to be the correct one, to make sure the
@@ -917,7 +917,7 @@ fn invalid_async_receive_with_retry<F1, F2>(
917917
nodes[2].node.fail_htlc_backwards(&payment_hash);
918918
expect_pending_htlcs_forwardable_conditions(
919919
nodes[2].node.get_and_clear_pending_events(),
920-
&[HTLCDestination::FailedPayment { payment_hash }],
920+
&[HTLCHandlingFailureType::Receive { payment_hash }],
921921
);
922922
nodes[2].node.process_pending_htlc_forwards();
923923
check_added_monitors!(nodes[2], 1);
@@ -937,7 +937,7 @@ fn invalid_async_receive_with_retry<F1, F2>(
937937
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
938938
.with_payment_preimage(keysend_preimage)
939939
.without_claimable_event()
940-
.expect_failure(HTLCDestination::FailedPayment { payment_hash });
940+
.expect_failure(HTLCHandlingFailureType::Receive { payment_hash });
941941
do_pass_along_path(args);
942942
fail_blinded_htlc_backwards(payment_hash, 1, &[&nodes[0], &nodes[1], &nodes[2]], true);
943943

@@ -1103,7 +1103,7 @@ fn expired_static_invoice_payment_path() {
11031103
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev)
11041104
.with_payment_preimage(keysend_preimage)
11051105
.without_claimable_event()
1106-
.expect_failure(HTLCDestination::FailedPayment { payment_hash });
1106+
.expect_failure(HTLCHandlingFailureType::Receive { payment_hash });
11071107
do_pass_along_path(args);
11081108
fail_blinded_htlc_backwards(payment_hash, 1, &[&nodes[0], &nodes[1], &nodes[2]], false);
11091109
nodes[2].logger.assert_log_contains(

0 commit comments

Comments
 (0)