Skip to content

Commit bb45736

Browse files
committed
ln+events: add HTLCDestinationFailure to NextHopChannel
Surface the reason for HTLC failure for forwards. Additional information is unlikely to be useful for InvalidOnion and UnknownNextHop, and adding information to FailedPayment is left for future PRs to keep the scope of this PR down.
1 parent e7ce43e commit bb45736

14 files changed

+427
-124
lines changed

lightning/src/events/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, Paym
2323
use crate::chain::transaction;
2424
use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields};
2525
use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS;
26+
use crate::ln::onion_utils::LocalHTLCFailureReason;
2627
use crate::types::features::ChannelTypeFeatures;
2728
use crate::ln::msgs;
2829
use crate::ln::types::ChannelId;
@@ -465,6 +466,25 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
465466
},
466467
);
467468

469+
/// The reason for HTLC failures in [`HTLCDestination`].
470+
#[derive(Clone, Debug, PartialEq, Eq)]
471+
pub enum HTLCDestinationFailure {
472+
/// The forwarded HTLC was failed back by the downstream node with an encrypted error reason.
473+
Downstream,
474+
/// The HTLC was failed locally by our node.
475+
Local{
476+
/// The reason that our node chose to fail the HTLC.
477+
reason: LocalHTLCFailureReason
478+
},
479+
}
480+
481+
impl_writeable_tlv_based_enum!(HTLCDestinationFailure,
482+
(0, Downstream) => {},
483+
(1, Local) => {
484+
(0, reason, required),
485+
},
486+
);
487+
468488
/// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`].
469489
#[derive(Clone, Debug, PartialEq, Eq)]
470490
pub enum HTLCDestination {
@@ -477,6 +497,9 @@ pub enum HTLCDestination {
477497
node_id: Option<PublicKey>,
478498
/// The outgoing `channel_id` between us and the next node.
479499
channel_id: ChannelId,
500+
/// The reason that the HTLC forward was failed. For backwards compatibility, this field is
501+
/// marked as optional, versions prior to 0.1.1 will set this value to None.
502+
reason: Option<HTLCDestinationFailure>
480503
},
481504
/// Scenario where we are unsure of the next node to forward the HTLC to.
482505
UnknownNextHop {
@@ -510,6 +533,7 @@ pub enum HTLCDestination {
510533
impl_writeable_tlv_based_enum_upgradable!(HTLCDestination,
511534
(0, NextHopChannel) => {
512535
(0, node_id, required),
536+
(1, reason, option),
513537
(2, channel_id, required),
514538
},
515539
(1, InvalidForward) => {

lightning/src/ln/blinded_payment_tests.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,11 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
427427
ForwardCheckFail::InboundOnionCheck => HTLCDestination::InvalidOnion,
428428
ForwardCheckFail::ForwardPayloadEncodedAsReceive => HTLCDestination::InvalidOnion,
429429
ForwardCheckFail::OutboundChannelCheck =>
430-
HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_1_2.2 },
430+
HTLCDestination::NextHopChannel {
431+
node_id: Some(nodes[2].node.get_our_node_id()),
432+
channel_id: chan_1_2.2,
433+
reason: Some(LocalHTLCFailureReason::ChannelNotReady.into()),
434+
},
431435
};
432436
expect_htlc_handling_failed_destinations!(
433437
nodes[1].node.get_and_clear_pending_events(), &[failed_destination.clone()]
@@ -458,7 +462,11 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
458462
let failed_destination = match check {
459463
ForwardCheckFail::InboundOnionCheck|ForwardCheckFail::ForwardPayloadEncodedAsReceive => HTLCDestination::InvalidOnion,
460464
ForwardCheckFail::OutboundChannelCheck =>
461-
HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 },
465+
HTLCDestination::NextHopChannel {
466+
node_id: Some(nodes[3].node.get_our_node_id()),
467+
channel_id: chan_2_3.2,
468+
reason: Some(LocalHTLCFailureReason::ChannelNotReady.into()),
469+
},
462470
};
463471
expect_htlc_handling_failed_destinations!(
464472
nodes[2].node.get_and_clear_pending_events(), &[failed_destination.clone()]
@@ -474,7 +482,7 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
474482
update_malformed.sha256_of_onion = [1; 32];
475483
update_malformed.failure_code = LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() ^ 1;
476484
nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed);
477-
do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, Some(FailureType::Blinded), false);
485+
do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, Some(FailureType::Custom(update_malformed.failure_code.into())), false);
478486

479487
let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
480488
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
@@ -605,7 +613,11 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck,
605613
$curr_node.node.peer_disconnected($next_node.node.get_our_node_id());
606614
expect_pending_htlcs_forwardable!($curr_node);
607615
expect_htlc_handling_failed_destinations!($curr_node.node.get_and_clear_pending_events(),
608-
vec![HTLCDestination::NextHopChannel { node_id: Some($next_node.node.get_our_node_id()), channel_id: $failed_chan_id }]);
616+
vec![HTLCDestination::NextHopChannel {
617+
node_id: Some($next_node.node.get_our_node_id()),
618+
channel_id: $failed_chan_id,
619+
reason: Some(LocalHTLCFailureReason::ChannelNotReady.into()),
620+
}]);
609621
},
610622
ProcessPendingHTLCsCheck::FwdChannelClosed => {
611623
// Force close the next-hop channel so when we go to forward in process_pending_htlc_forwards,
@@ -660,7 +672,7 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck,
660672
update_malformed.sha256_of_onion = [1; 32];
661673
update_malformed.failure_code = LocalHTLCFailureReason::InvalidOnionBlinding.failure_code() ^ 1;
662674
nodes[1].node.handle_update_fail_malformed_htlc(nodes[2].node.get_our_node_id(), update_malformed);
663-
do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, Some(FailureType::Blinded), false);
675+
do_commitment_signed_dance(&nodes[1], &nodes[2], &updates.commitment_signed, Some(FailureType::Custom(update_malformed.failure_code.into())), false);
664676

665677
let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
666678
nodes[0].node.handle_update_fail_htlc(nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
@@ -1242,7 +1254,11 @@ fn min_htlc() {
12421254
expect_pending_htlcs_forwardable!(nodes[1]);
12431255
expect_htlc_handling_failed_destinations!(
12441256
nodes[1].node.get_and_clear_pending_events(),
1245-
&[HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_1_2.2 }]
1257+
&[HTLCDestination::NextHopChannel {
1258+
node_id: Some(nodes[2].node.get_our_node_id()),
1259+
channel_id: chan_1_2.2,
1260+
reason: Some(LocalHTLCFailureReason::AmountBelowMinimum.into()),
1261+
}]
12461262
);
12471263
check_added_monitors(&nodes[1], 1);
12481264
let mut updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());

lightning/src/ln/chanmon_update_fail_tests.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ use bitcoin::hash_types::BlockHash;
1717
use bitcoin::network::Network;
1818
use crate::chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor};
1919
use crate::chain::{ChannelMonitorUpdateStatus, Listen, Watch};
20-
use crate::events::{Event, PaymentPurpose, ClosureReason, HTLCDestination};
20+
use crate::events::{Event, PaymentPurpose, ClosureReason, HTLCDestination, HTLCDestinationFailure};
2121
use crate::ln::channelmanager::{PaymentId, RAACommitmentOrder, RecipientOnionFields};
2222
use crate::ln::channel::AnnouncementSigsState;
2323
use crate::ln::msgs;
24+
use crate::ln::onion_utils::LocalHTLCFailureReason;
2425
use crate::ln::types::ChannelId;
2526
use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, RoutingMessageHandler, MessageSendEvent};
2627
use crate::util::test_channel_signer::TestChannelSigner;
@@ -905,7 +906,11 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
905906
let (latest_update, _) = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2.2).unwrap().clone();
906907
nodes[1].chain_monitor.chain_monitor.force_channel_monitor_updated(chan_2.2, latest_update);
907908
check_added_monitors!(nodes[1], 0);
908-
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]);
909+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel {
910+
node_id: Some(nodes[2].node.get_our_node_id()),
911+
channel_id: chan_2.2,
912+
reason: Some(HTLCDestinationFailure::Downstream{}),
913+
}]);
909914
check_added_monitors!(nodes[1], 1);
910915

911916
let mut events_3 = nodes[1].node.get_and_clear_pending_msg_events();
@@ -1752,7 +1757,11 @@ fn test_monitor_update_on_pending_forwards() {
17521757
commitment_signed_dance!(nodes[1], nodes[2], payment_event.commitment_msg, false);
17531758

17541759
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
1755-
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]);
1760+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel {
1761+
node_id: Some(nodes[2].node.get_our_node_id()),
1762+
channel_id: chan_2.2,
1763+
reason: Some(HTLCDestinationFailure::Downstream{}),
1764+
}]);
17561765
check_added_monitors!(nodes[1], 1);
17571766

17581767
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
@@ -2159,7 +2168,11 @@ fn test_fail_htlc_on_broadcast_after_claim() {
21592168
check_closed_broadcast!(nodes[1], true);
21602169
connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1);
21612170
check_added_monitors!(nodes[1], 1);
2162-
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]);
2171+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel {
2172+
node_id: Some(nodes[2].node.get_our_node_id()),
2173+
channel_id: chan_id_2,
2174+
reason: Some(LocalHTLCFailureReason::ChannelClosed.into()),
2175+
}]);
21632176

21642177
nodes[0].node.handle_update_fulfill_htlc(nodes[1].node.get_our_node_id(), &bs_updates.update_fulfill_htlcs[0]);
21652178
expect_payment_sent(&nodes[0], payment_preimage, None, false, false);
@@ -2549,7 +2562,11 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
25492562
let mut reconnect_args = ReconnectArgs::new(&nodes[1], &nodes[2]);
25502563
reconnect_args.pending_htlc_fails.0 = 1;
25512564
reconnect_nodes(reconnect_args);
2552-
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]);
2565+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], vec![HTLCDestination::NextHopChannel {
2566+
node_id: Some(nodes[2].node.get_our_node_id()),
2567+
channel_id: chan_id_2,
2568+
reason: Some(HTLCDestinationFailure::Downstream{}),
2569+
}]);
25532570
} else {
25542571
let mut reconnect_args = ReconnectArgs::new(&nodes[1], &nodes[2]);
25552572
reconnect_args.pending_htlc_claims.0 = 1;

lightning/src/ln/channelmanager.rs

+41-16
Original file line numberDiff line numberDiff line change
@@ -3293,7 +3293,8 @@ macro_rules! handle_monitor_update_completion {
32933293
}
32943294
$self.finalize_claims(updates.finalized_claimed_htlcs);
32953295
for failure in updates.failed_htlcs.drain(..) {
3296-
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id };
3296+
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id),
3297+
channel_id, reason: Some(failure.2.clone().into()) };
32973298
$self.fail_htlc_backwards_internal(&failure.0, &failure.1, &failure.2, receiver);
32983299
}
32993300
} }
@@ -3913,7 +3914,8 @@ where
39133914
for htlc_source in failed_htlcs.drain(..) {
39143915
let failure_reason = LocalHTLCFailureReason::DroppedPending;
39153916
let reason = HTLCFailReason::from_failure_code(failure_reason);
3916-
let receiver = HTLCDestination::NextHopChannel { node_id: Some(*counterparty_node_id), channel_id: *channel_id };
3917+
let receiver = HTLCDestination::NextHopChannel { node_id: Some(*counterparty_node_id),
3918+
channel_id: *channel_id, reason: Some(failure_reason.into()) };
39173919
self.fail_htlc_backwards_internal(&htlc_source.0, &htlc_source.1, &reason, receiver);
39183920
}
39193921

@@ -4037,7 +4039,8 @@ where
40374039
let (source, payment_hash, counterparty_node_id, channel_id) = htlc_source;
40384040
let failure_reason = LocalHTLCFailureReason::DroppedPending;
40394041
let reason = HTLCFailReason::from_failure_code(failure_reason);
4040-
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id };
4042+
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id),
4043+
channel_id, reason: Some(failure_reason.into()) };
40414044
self.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver);
40424045
}
40434046
if let Some((_, funding_txo, _channel_id, monitor_update)) = shutdown_res.monitor_update {
@@ -5751,13 +5754,14 @@ where
57515754
let mut decode_update_add_htlcs = new_hash_map();
57525755
mem::swap(&mut decode_update_add_htlcs, &mut self.decode_update_add_htlcs.lock().unwrap());
57535756

5754-
let get_failed_htlc_destination = |outgoing_scid_opt: Option<u64>, payment_hash: PaymentHash| {
5757+
let get_failed_htlc_destination = |outgoing_scid_opt: Option<u64>, payment_hash: PaymentHash, reason: LocalHTLCFailureReason| {
57555758
if let Some(outgoing_scid) = outgoing_scid_opt {
57565759
match self.short_to_chan_info.read().unwrap().get(&outgoing_scid) {
57575760
Some((outgoing_counterparty_node_id, outgoing_channel_id)) =>
57585761
HTLCDestination::NextHopChannel {
57595762
node_id: Some(*outgoing_counterparty_node_id),
57605763
channel_id: *outgoing_channel_id,
5764+
reason: Some(reason.into()),
57615765
},
57625766
None => HTLCDestination::UnknownNextHop {
57635767
requested_forward_scid: outgoing_scid,
@@ -5819,10 +5823,10 @@ where
58195823
Some(Ok(_)) => {},
58205824
Some(Err((err, reason))) => {
58215825
let htlc_fail = self.htlc_failure_from_update_add_err(
5822-
&update_add_htlc, &incoming_counterparty_node_id, err, reason,
5826+
&update_add_htlc, &incoming_counterparty_node_id, err, reason.clone(),
58235827
is_intro_node_blinded_forward, &shared_secret,
58245828
);
5825-
let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash);
5829+
let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash, reason);
58265830
htlc_fails.push((htlc_fail, htlc_destination));
58275831
continue;
58285832
},
@@ -5839,7 +5843,7 @@ where
58395843
&update_add_htlc, &incoming_counterparty_node_id, err, reason,
58405844
is_intro_node_blinded_forward, &shared_secret,
58415845
);
5842-
let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash);
5846+
let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash, reason);
58435847
htlc_fails.push((htlc_fail, htlc_destination));
58445848
continue;
58455849
}
@@ -5851,7 +5855,7 @@ where
58515855
) {
58525856
Ok(info) => htlc_forwards.push((info, update_add_htlc.htlc_id)),
58535857
Err(inbound_err) => {
5854-
let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash);
5858+
let htlc_destination = get_failed_htlc_destination(outgoing_scid_opt, update_add_htlc.payment_hash, inbound_err.reason);
58555859
htlc_fails.push((self.construct_pending_htlc_fail_msg(&update_add_htlc, &incoming_counterparty_node_id, shared_secret, inbound_err), htlc_destination));
58565860
},
58575861
}
@@ -6127,7 +6131,11 @@ where
61276131
let data = self.get_htlc_inbound_temp_fail_data(reason);
61286132
failed_forwards.push((htlc_source, payment_hash,
61296133
HTLCFailReason::reason(reason, data),
6130-
HTLCDestination::NextHopChannel { node_id: Some(chan.context.get_counterparty_node_id()), channel_id: forward_chan_id }
6134+
HTLCDestination::NextHopChannel {
6135+
node_id: Some(chan.context.get_counterparty_node_id()),
6136+
channel_id: forward_chan_id,
6137+
reason: Some(reason.into()),
6138+
}
61316139
));
61326140
} else {
61336141
forwarding_channel_not_found!(core::iter::once(forward_info).chain(draining_pending_forwards));
@@ -6982,8 +6990,12 @@ where
69826990
};
69836991

69846992
for (htlc_src, payment_hash) in htlcs_to_fail.drain(..) {
6985-
let reason = HTLCFailReason::reason(failure_reason, onion_failure_data.clone());
6986-
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id.clone()), channel_id };
6993+
let reason = HTLCFailReason::reason(failure_reason.clone(), onion_failure_data.clone());
6994+
let receiver = HTLCDestination::NextHopChannel {
6995+
node_id: Some(counterparty_node_id.clone()),
6996+
channel_id,
6997+
reason: Some(failure_reason.into()),
6998+
};
69876999
self.fail_htlc_backwards_internal(&htlc_src, &payment_hash, &reason, receiver);
69887000
}
69897001
}
@@ -8768,8 +8780,13 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
87688780
}
87698781
}
87708782
for htlc_source in dropped_htlcs.drain(..) {
8771-
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id.clone()), channel_id: msg.channel_id };
8772-
let reason = HTLCFailReason::from_failure_code(LocalHTLCFailureReason::DroppedPending);
8783+
let failure_reason = LocalHTLCFailureReason::DroppedPending;
8784+
let reason = HTLCFailReason::from_failure_code(failure_reason);
8785+
let receiver = HTLCDestination::NextHopChannel {
8786+
node_id: Some(counterparty_node_id.clone()),
8787+
channel_id: msg.channel_id,
8788+
reason: Some(failure_reason.into()),
8789+
};
87738790
self.fail_htlc_backwards_internal(&htlc_source.0, &htlc_source.1, &reason, receiver);
87748791
}
87758792
if let Some(shutdown_res) = finish_shutdown {
@@ -9595,7 +9612,11 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
95959612
} else {
95969613
log_trace!(logger, "Failing HTLC with hash {} from our monitor", &htlc_update.payment_hash);
95979614
let failure_reason = LocalHTLCFailureReason::ChannelClosed;
9598-
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id };
9615+
let receiver = HTLCDestination::NextHopChannel {
9616+
node_id: Some(counterparty_node_id),
9617+
channel_id,
9618+
reason: Some(failure_reason.into()),
9619+
};
95999620
let reason = HTLCFailReason::from_failure_code(failure_reason);
96009621
self.fail_htlc_backwards_internal(&htlc_update.source, &htlc_update.payment_hash, &reason, receiver);
96019622
}
@@ -11689,7 +11710,11 @@ where
1168911710
let reason = LocalHTLCFailureReason::CLTVExpiryTooSoon;
1169011711
let data = self.get_htlc_inbound_temp_fail_data(reason);
1169111712
timed_out_htlcs.push((source, payment_hash, HTLCFailReason::reason(reason, data),
11692-
HTLCDestination::NextHopChannel { node_id: Some(funded_channel.context.get_counterparty_node_id()), channel_id: funded_channel.context.channel_id() }));
11713+
HTLCDestination::NextHopChannel {
11714+
node_id: Some(funded_channel.context.get_counterparty_node_id()),
11715+
channel_id: funded_channel.context.channel_id(),
11716+
reason: Some(reason.into()),
11717+
}));
1169311718
}
1169411719
let logger = WithChannelContext::from(&self.logger, &funded_channel.context, None);
1169511720
if let Some(channel_ready) = channel_ready_opt {
@@ -14916,7 +14941,7 @@ where
1491614941
for htlc_source in failed_htlcs.drain(..) {
1491714942
let (source, payment_hash, counterparty_node_id, channel_id) = htlc_source;
1491814943
let failure_reason = LocalHTLCFailureReason::DroppedPending;
14919-
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id };
14944+
let receiver = HTLCDestination::NextHopChannel { node_id: Some(counterparty_node_id), channel_id, reason: Some(failure_reason.into()) };
1492014945
let reason = HTLCFailReason::from_failure_code(failure_reason);
1492114946
channel_manager.fail_htlc_backwards_internal(&source, &payment_hash, &reason, receiver);
1492214947
}

0 commit comments

Comments
 (0)