@@ -394,6 +394,9 @@ pub(crate) struct HTLCPreviousHopData {
394
394
// channel with a preimage provided by the forward channel.
395
395
outpoint: OutPoint,
396
396
counterparty_node_id: Option<PublicKey>,
397
+ /// Used to preserve our backwards channel by failing back in case an HTLC claim in the forward
398
+ /// channel remains unconfirmed for too long.
399
+ cltv_expiry: Option<u32>,
397
400
}
398
401
399
402
#[derive(PartialEq, Eq)]
@@ -696,6 +699,15 @@ impl HTLCSource {
696
699
true
697
700
}
698
701
}
702
+
703
+ /// Returns the CLTV expiry of the inbound HTLC (i.e. the source referred to by this object),
704
+ /// if the source was a forwarded HTLC and the HTLC was first forwarded on LDK 0.1.1 or later.
705
+ pub(crate) fn inbound_htlc_expiry(&self) -> Option<u32> {
706
+ match self {
707
+ Self::PreviousHopData(HTLCPreviousHopData { cltv_expiry, .. }) => *cltv_expiry,
708
+ _ => None,
709
+ }
710
+ }
699
711
}
700
712
701
713
/// This enum is used to specify which error data to send to peers when failing back an HTLC
@@ -5592,7 +5604,7 @@ where
5592
5604
err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0))
5593
5605
})?;
5594
5606
5595
- if let PendingHTLCRouting::Forward { short_channel_id, .. } = payment.forward_info.routing {
5607
+ if let PendingHTLCRouting::Forward { short_channel_id, incoming_cltv_expiry, .. } = payment.forward_info.routing {
5596
5608
let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData {
5597
5609
short_channel_id: payment.prev_short_channel_id,
5598
5610
user_channel_id: Some(payment.prev_user_channel_id),
@@ -5603,6 +5615,7 @@ where
5603
5615
incoming_packet_shared_secret: payment.forward_info.incoming_shared_secret,
5604
5616
phantom_shared_secret: None,
5605
5617
blinded_failure: payment.forward_info.routing.blinded_failure(),
5618
+ cltv_expiry: incoming_cltv_expiry,
5606
5619
});
5607
5620
5608
5621
let failure_reason = HTLCFailReason::from_failure_code(0x4000 | 10);
@@ -5777,6 +5790,7 @@ where
5777
5790
outgoing_cltv_value, ..
5778
5791
}
5779
5792
}) => {
5793
+ let cltv_expiry = routing.incoming_cltv_expiry();
5780
5794
macro_rules! failure_handler {
5781
5795
($msg: expr, $err_code: expr, $err_data: expr, $phantom_ss: expr, $next_hop_unknown: expr) => {
5782
5796
let logger = WithContext::from(&self.logger, forwarding_counterparty, Some(prev_channel_id), Some(payment_hash));
@@ -5792,6 +5806,7 @@ where
5792
5806
incoming_packet_shared_secret: incoming_shared_secret,
5793
5807
phantom_shared_secret: $phantom_ss,
5794
5808
blinded_failure: routing.blinded_failure(),
5809
+ cltv_expiry,
5795
5810
});
5796
5811
5797
5812
let reason = if $next_hop_unknown {
@@ -5901,7 +5916,7 @@ where
5901
5916
prev_user_channel_id, prev_counterparty_node_id, forward_info: PendingHTLCInfo {
5902
5917
incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value,
5903
5918
routing: PendingHTLCRouting::Forward {
5904
- ref onion_packet, blinded, ..
5919
+ ref onion_packet, blinded, incoming_cltv_expiry, ..
5905
5920
}, skimmed_fee_msat, ..
5906
5921
},
5907
5922
}) => {
@@ -5916,6 +5931,7 @@ where
5916
5931
// Phantom payments are only PendingHTLCRouting::Receive.
5917
5932
phantom_shared_secret: None,
5918
5933
blinded_failure: blinded.map(|b| b.failure),
5934
+ cltv_expiry: incoming_cltv_expiry,
5919
5935
});
5920
5936
let next_blinding_point = blinded.and_then(|b| {
5921
5937
b.next_blinding_override.or_else(|| {
@@ -6090,6 +6106,7 @@ where
6090
6106
incoming_packet_shared_secret: incoming_shared_secret,
6091
6107
phantom_shared_secret,
6092
6108
blinded_failure,
6109
+ cltv_expiry: Some(cltv_expiry),
6093
6110
},
6094
6111
// We differentiate the received value from the sender intended value
6095
6112
// if possible so that we don't prematurely mark MPP payments complete
@@ -6123,6 +6140,7 @@ where
6123
6140
incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret,
6124
6141
phantom_shared_secret,
6125
6142
blinded_failure,
6143
+ cltv_expiry: Some(cltv_expiry),
6126
6144
}), payment_hash,
6127
6145
HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data),
6128
6146
HTLCDestination::FailedPayment { payment_hash: $payment_hash },
@@ -8998,6 +9016,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
8998
9016
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
8999
9017
phantom_shared_secret: None,
9000
9018
blinded_failure: forward_info.routing.blinded_failure(),
9019
+ cltv_expiry: forward_info.routing.incoming_cltv_expiry(),
9001
9020
});
9002
9021
9003
9022
failed_intercept_forwards.push((htlc_source, forward_info.payment_hash,
@@ -11161,6 +11180,7 @@ where
11161
11180
outpoint: htlc.prev_funding_outpoint,
11162
11181
channel_id: htlc.prev_channel_id,
11163
11182
blinded_failure: htlc.forward_info.routing.blinded_failure(),
11183
+ cltv_expiry: htlc.forward_info.routing.incoming_cltv_expiry(),
11164
11184
});
11165
11185
11166
11186
let requested_forward_scid /* intercept scid */ = match htlc.forward_info.routing {
@@ -12504,6 +12524,7 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, {
12504
12524
(2, outpoint, required),
12505
12525
(3, blinded_failure, option),
12506
12526
(4, htlc_id, required),
12527
+ (5, cltv_expiry, option),
12507
12528
(6, incoming_packet_shared_secret, required),
12508
12529
(7, user_channel_id, option),
12509
12530
// Note that by the time we get past the required read for type 2 above, outpoint will be
0 commit comments