Skip to content

Commit 14df384

Browse files
Add cltv expiry to HTLCPreviousHopData
In a coming commit we'll expire HTLCs backwards even if we haven't yet claimed them on-chain based on their inbound edge being close to causing a channel force-closure. Here we track and expose the incoming edge's CLTV expiry in the `HTLCSource`, giving `ChannelMonitor` access to it. Co-authored-by: Matt Corallo <[email protected]>
1 parent e62e9fb commit 14df384

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ pub(crate) struct HTLCPreviousHopData {
394394
// channel with a preimage provided by the forward channel.
395395
outpoint: OutPoint,
396396
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>,
397400
}
398401

399402
#[derive(PartialEq, Eq)]
@@ -696,6 +699,15 @@ impl HTLCSource {
696699
true
697700
}
698701
}
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+
}
699711
}
700712

701713
/// This enum is used to specify which error data to send to peers when failing back an HTLC
@@ -5592,7 +5604,7 @@ where
55925604
err: format!("Payment with intercept id {} not found", log_bytes!(intercept_id.0))
55935605
})?;
55945606

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 {
55965608
let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData {
55975609
short_channel_id: payment.prev_short_channel_id,
55985610
user_channel_id: Some(payment.prev_user_channel_id),
@@ -5603,6 +5615,7 @@ where
56035615
incoming_packet_shared_secret: payment.forward_info.incoming_shared_secret,
56045616
phantom_shared_secret: None,
56055617
blinded_failure: payment.forward_info.routing.blinded_failure(),
5618+
cltv_expiry: incoming_cltv_expiry,
56065619
});
56075620

56085621
let failure_reason = HTLCFailReason::from_failure_code(0x4000 | 10);
@@ -5777,6 +5790,7 @@ where
57775790
outgoing_cltv_value, ..
57785791
}
57795792
}) => {
5793+
let cltv_expiry = routing.incoming_cltv_expiry();
57805794
macro_rules! failure_handler {
57815795
($msg: expr, $err_code: expr, $err_data: expr, $phantom_ss: expr, $next_hop_unknown: expr) => {
57825796
let logger = WithContext::from(&self.logger, forwarding_counterparty, Some(prev_channel_id), Some(payment_hash));
@@ -5792,6 +5806,7 @@ where
57925806
incoming_packet_shared_secret: incoming_shared_secret,
57935807
phantom_shared_secret: $phantom_ss,
57945808
blinded_failure: routing.blinded_failure(),
5809+
cltv_expiry,
57955810
});
57965811

57975812
let reason = if $next_hop_unknown {
@@ -5901,7 +5916,7 @@ where
59015916
prev_user_channel_id, prev_counterparty_node_id, forward_info: PendingHTLCInfo {
59025917
incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value,
59035918
routing: PendingHTLCRouting::Forward {
5904-
ref onion_packet, blinded, ..
5919+
ref onion_packet, blinded, incoming_cltv_expiry, ..
59055920
}, skimmed_fee_msat, ..
59065921
},
59075922
}) => {
@@ -5916,6 +5931,7 @@ where
59165931
// Phantom payments are only PendingHTLCRouting::Receive.
59175932
phantom_shared_secret: None,
59185933
blinded_failure: blinded.map(|b| b.failure),
5934+
cltv_expiry: incoming_cltv_expiry,
59195935
});
59205936
let next_blinding_point = blinded.and_then(|b| {
59215937
b.next_blinding_override.or_else(|| {
@@ -6090,6 +6106,7 @@ where
60906106
incoming_packet_shared_secret: incoming_shared_secret,
60916107
phantom_shared_secret,
60926108
blinded_failure,
6109+
cltv_expiry: Some(cltv_expiry),
60936110
},
60946111
// We differentiate the received value from the sender intended value
60956112
// if possible so that we don't prematurely mark MPP payments complete
@@ -6123,6 +6140,7 @@ where
61236140
incoming_packet_shared_secret: $htlc.prev_hop.incoming_packet_shared_secret,
61246141
phantom_shared_secret,
61256142
blinded_failure,
6143+
cltv_expiry: Some(cltv_expiry),
61266144
}), payment_hash,
61276145
HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data),
61286146
HTLCDestination::FailedPayment { payment_hash: $payment_hash },
@@ -8998,6 +9016,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
89989016
incoming_packet_shared_secret: forward_info.incoming_shared_secret,
89999017
phantom_shared_secret: None,
90009018
blinded_failure: forward_info.routing.blinded_failure(),
9019+
cltv_expiry: forward_info.routing.incoming_cltv_expiry(),
90019020
});
90029021

90039022
failed_intercept_forwards.push((htlc_source, forward_info.payment_hash,
@@ -11161,6 +11180,7 @@ where
1116111180
outpoint: htlc.prev_funding_outpoint,
1116211181
channel_id: htlc.prev_channel_id,
1116311182
blinded_failure: htlc.forward_info.routing.blinded_failure(),
11183+
cltv_expiry: htlc.forward_info.routing.incoming_cltv_expiry(),
1116411184
});
1116511185

1116611186
let requested_forward_scid /* intercept scid */ = match htlc.forward_info.routing {
@@ -12504,6 +12524,7 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, {
1250412524
(2, outpoint, required),
1250512525
(3, blinded_failure, option),
1250612526
(4, htlc_id, required),
12527+
(5, cltv_expiry, option),
1250712528
(6, incoming_packet_shared_secret, required),
1250812529
(7, user_channel_id, option),
1250912530
// Note that by the time we get past the required read for type 2 above, outpoint will be

0 commit comments

Comments
 (0)