@@ -399,6 +399,9 @@ pub(crate) struct HTLCPreviousHopData {
399
399
// channel with a preimage provided by the forward channel.
400
400
outpoint: OutPoint,
401
401
counterparty_node_id: Option<PublicKey>,
402
+ /// Used to preserve our backwards channel by failing back in case an HTLC claim in the forward
403
+ /// channel remains unconfirmed for too long.
404
+ cltv_expiry: Option<u32>,
402
405
}
403
406
404
407
#[derive(PartialEq, Eq)]
@@ -701,6 +704,15 @@ impl HTLCSource {
701
704
true
702
705
}
703
706
}
707
+
708
+ /// Returns the CLTV expiry of the inbound HTLC (i.e. the source referred to by this object),
709
+ /// if the source was a forwarded HTLC and the HTLC was first forwarded on LDK 0.1.1 or later.
710
+ pub(crate) fn inbound_htlc_expiry(&self) -> Option<u32> {
711
+ match self {
712
+ Self::PreviousHopData(HTLCPreviousHopData { cltv_expiry, .. }) => *cltv_expiry,
713
+ _ => None,
714
+ }
715
+ }
704
716
}
705
717
706
718
/// This enum is used to specify which error data to send to peers when failing back an HTLC
@@ -5573,7 +5585,7 @@ where
5573
5585
err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0))
5574
5586
})?;
5575
5587
5576
- if let PendingHTLCRouting::Forward { short_channel_id, .. } = payment.forward_info.routing {
5588
+ if let PendingHTLCRouting::Forward { short_channel_id, incoming_cltv_expiry, .. } = payment.forward_info.routing {
5577
5589
let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData {
5578
5590
short_channel_id: payment.prev_short_channel_id,
5579
5591
user_channel_id: Some(payment.prev_user_channel_id),
@@ -5584,6 +5596,7 @@ where
5584
5596
incoming_packet_shared_secret: payment.forward_info.incoming_shared_secret,
5585
5597
phantom_shared_secret: None,
5586
5598
blinded_failure: payment.forward_info.routing.blinded_failure(),
5599
+ cltv_expiry: incoming_cltv_expiry,
5587
5600
});
5588
5601
5589
5602
let failure_reason = HTLCFailReason::from_failure_code(0x4000 | 10);
@@ -5758,6 +5771,7 @@ where
5758
5771
outgoing_cltv_value, ..
5759
5772
}
5760
5773
}) => {
5774
+ let cltv_expiry = routing.incoming_cltv_expiry();
5761
5775
macro_rules! failure_handler {
5762
5776
($msg: expr, $err_code: expr, $err_data: expr, $phantom_ss: expr, $next_hop_unknown: expr) => {
5763
5777
let logger = WithContext::from(&self.logger, forwarding_counterparty, Some(prev_channel_id), Some(payment_hash));
@@ -5773,6 +5787,7 @@ where
5773
5787
incoming_packet_shared_secret: incoming_shared_secret,
5774
5788
phantom_shared_secret: $phantom_ss,
5775
5789
blinded_failure: routing.blinded_failure(),
5790
+ cltv_expiry,
5776
5791
});
5777
5792
5778
5793
let reason = if $next_hop_unknown {
@@ -5882,7 +5897,7 @@ where
5882
5897
prev_user_channel_id, prev_counterparty_node_id, forward_info: PendingHTLCInfo {
5883
5898
incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value,
5884
5899
routing: PendingHTLCRouting::Forward {
5885
- ref onion_packet, blinded, ..
5900
+ ref onion_packet, blinded, incoming_cltv_expiry, ..
5886
5901
}, skimmed_fee_msat, ..
5887
5902
},
5888
5903
}) => {
@@ -5897,6 +5912,7 @@ where
5897
5912
// Phantom payments are only PendingHTLCRouting::Receive.
5898
5913
phantom_shared_secret: None,
5899
5914
blinded_failure: blinded.map(|b| b.failure),
5915
+ cltv_expiry: incoming_cltv_expiry,
5900
5916
});
5901
5917
let next_blinding_point = blinded.and_then(|b| {
5902
5918
b.next_blinding_override.or_else(|| {
@@ -6086,6 +6102,7 @@ where
6086
6102
incoming_packet_shared_secret: incoming_shared_secret,
6087
6103
phantom_shared_secret,
6088
6104
blinded_failure,
6105
+ cltv_expiry: Some(cltv_expiry),
6089
6106
},
6090
6107
// We differentiate the received value from the sender intended value
6091
6108
// if possible so that we don't prematurely mark MPP payments complete
@@ -6119,6 +6136,7 @@ where
6119
6136
incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret,
6120
6137
phantom_shared_secret,
6121
6138
blinded_failure,
6139
+ cltv_expiry: Some(cltv_expiry),
6122
6140
}), payment_hash,
6123
6141
HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data),
6124
6142
HTLCDestination::FailedPayment { payment_hash: $payment_hash },
@@ -8979,6 +8997,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
8979
8997
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
8980
8998
phantom_shared_secret: None,
8981
8999
blinded_failure: forward_info.routing.blinded_failure(),
9000
+ cltv_expiry: forward_info.routing.incoming_cltv_expiry(),
8982
9001
});
8983
9002
8984
9003
failed_intercept_forwards.push((htlc_source, forward_info.payment_hash,
@@ -11221,6 +11240,7 @@ where
11221
11240
outpoint: htlc.prev_funding_outpoint,
11222
11241
channel_id: htlc.prev_channel_id,
11223
11242
blinded_failure: htlc.forward_info.routing.blinded_failure(),
11243
+ cltv_expiry: htlc.forward_info.routing.incoming_cltv_expiry(),
11224
11244
});
11225
11245
11226
11246
let requested_forward_scid /* intercept scid */ = match htlc.forward_info.routing {
@@ -12559,6 +12579,7 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, {
12559
12579
(2, outpoint, required),
12560
12580
(3, blinded_failure, option),
12561
12581
(4, htlc_id, required),
12582
+ (5, cltv_expiry, option),
12562
12583
(6, incoming_packet_shared_secret, required),
12563
12584
(7, user_channel_id, option),
12564
12585
// Note that by the time we get past the required read for type 2 above, outpoint will be
0 commit comments