Skip to content

Commit bf0ead8

Browse files
committed
Make cltv_expiry_delta u16
The BOLT 7 wire format defines `cltv_expiry_delta` as a 2-byte field, and LDK uses u16 for it everywhere (`RouteHintHop`, `ChannelUpdateInfo`, `UnsignedChannelUpdate`). Align the LSPS2 types accordingly. serde_json will reject values exceeding `u16::MAX` during deserialization, so a counterparty sending an out-of-range value is handled gracefully. Co-Authored-By: HAL 9000 Signed-off-by: Elias Rohrer <dev@tnull.de>
1 parent 84d56fa commit bf0ead8

File tree

5 files changed

+20
-79
lines changed

5 files changed

+20
-79
lines changed

lightning-liquidity/src/lsps2/event.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub enum LSPS2ClientEvent {
7373
/// The intercept short channel id to use in the route hint.
7474
intercept_scid: u64,
7575
/// The `cltv_expiry_delta` to use in the route hint.
76-
cltv_expiry_delta: u32,
76+
cltv_expiry_delta: u16,
7777
/// The initial payment size you specified.
7878
payment_size_msat: Option<u64>,
7979
},

lightning-liquidity/src/lsps2/msgs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ pub struct LSPS2BuyResponse {
182182
/// The intercept short channel id used by LSP to identify need to open channel.
183183
pub jit_channel_scid: LSPS2InterceptScid,
184184
/// The locktime expiry delta the lsp requires.
185-
pub lsp_cltv_expiry_delta: u32,
185+
pub lsp_cltv_expiry_delta: u16,
186186
/// Trust model flag (default: false).
187187
///
188188
/// false => "LSP trusts client": LSP immediately (or as soon as safe) broadcasts the

lightning-liquidity/src/lsps2/router.rs

Lines changed: 7 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub struct LSPS2Bolt12InvoiceParameters {
3535
/// The LSPS2 intercept short channel id.
3636
pub intercept_scid: u64,
3737
/// The CLTV expiry delta the LSP requires for forwarding over `intercept_scid`.
38-
pub cltv_expiry_delta: u32,
38+
pub cltv_expiry_delta: u16,
3939
}
4040

4141
/// A router wrapper that injects LSPS2-specific BOLT12 blinded payment paths for registered
@@ -155,19 +155,16 @@ impl<R: Router, ES: EntropySource + Send + Sync> Router for LSPS2BOLT12Router<R,
155155
// the paths in this exact order.
156156
let mut paths = inner_res.unwrap_or_default();
157157
for lsps2_invoice_params in all_params {
158-
let payment_relay = match u16::try_from(lsps2_invoice_params.cltv_expiry_delta) {
159-
Ok(cltv_expiry_delta) => PaymentRelay {
160-
cltv_expiry_delta,
161-
fee_proportional_millionths: 0,
162-
fee_base_msat: 0,
163-
},
164-
Err(_) => continue,
158+
let payment_relay = PaymentRelay {
159+
cltv_expiry_delta: lsps2_invoice_params.cltv_expiry_delta,
160+
fee_proportional_millionths: 0,
161+
fee_base_msat: 0,
165162
};
166163
let payment_constraints = PaymentConstraints {
167164
max_cltv_expiry: tlvs
168165
.payment_constraints
169166
.max_cltv_expiry
170-
.saturating_add(lsps2_invoice_params.cltv_expiry_delta),
167+
.saturating_add(lsps2_invoice_params.cltv_expiry_delta as u32),
171168
htlc_minimum_msat: 0,
172169
};
173170

@@ -371,7 +368,7 @@ mod tests {
371368
assert_eq!(path.payinfo.fee_proportional_millionths, 0);
372369
assert_eq!(
373370
path.payinfo.cltv_expiry_delta,
374-
expected_cltv_delta as u16 + MIN_FINAL_CLTV_EXPIRY_DELTA
371+
expected_cltv_delta + MIN_FINAL_CLTV_EXPIRY_DELTA
375372
);
376373

377374
let lookup =
@@ -422,62 +419,6 @@ mod tests {
422419
assert_eq!(router.inner_router.create_blinded_payment_paths_calls(), 1);
423420
}
424421

425-
#[test]
426-
fn skips_out_of_range_cltv_delta_and_keeps_valid_paths() {
427-
let inner_router = MockRouter::new();
428-
let recipient = pubkey(13);
429-
let secp_ctx = Secp256k1::new();
430-
431-
let existing_tlvs = bolt12_offer_tlvs(OfferId([11; 32]));
432-
let existing_path = lightning::blinded_path::payment::BlindedPaymentPath::new(
433-
&[],
434-
recipient,
435-
ReceiveAuthKey([3; 32]),
436-
existing_tlvs,
437-
u64::MAX,
438-
MIN_FINAL_CLTV_EXPIRY_DELTA,
439-
&TestEntropy,
440-
&secp_ctx,
441-
)
442-
.unwrap();
443-
*inner_router.paths_to_return.lock().unwrap() = Some(vec![existing_path]);
444-
445-
let entropy_source = TestEntropy;
446-
let router = LSPS2BOLT12Router::new(inner_router, entropy_source);
447-
448-
let valid_scid = 21;
449-
router.register_intercept_scid(
450-
valid_scid,
451-
LSPS2Bolt12InvoiceParameters {
452-
counterparty_node_id: pubkey(12),
453-
intercept_scid: valid_scid,
454-
cltv_expiry_delta: 48,
455-
},
456-
);
457-
router.register_intercept_scid(
458-
22,
459-
LSPS2Bolt12InvoiceParameters {
460-
counterparty_node_id: pubkey(14),
461-
intercept_scid: 22,
462-
cltv_expiry_delta: u32::from(u16::MAX) + 1,
463-
},
464-
);
465-
466-
let paths = router
467-
.create_blinded_payment_paths(
468-
recipient,
469-
ReceiveAuthKey([3; 32]),
470-
Vec::new(),
471-
bolt12_offer_tlvs(OfferId([11; 32])),
472-
Some(1_000),
473-
&secp_ctx,
474-
)
475-
.unwrap();
476-
477-
assert_eq!(paths.len(), 2);
478-
assert_eq!(router.inner_router.create_blinded_payment_paths_calls(), 1);
479-
}
480-
481422
#[test]
482423
fn can_deregister_intercept_scid() {
483424
let inner_router = MockRouter::new();

lightning-liquidity/src/lsps2/service.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ where
904904
/// [`LSPS2ServiceEvent::BuyRequest`]: crate::lsps2::event::LSPS2ServiceEvent::BuyRequest
905905
pub async fn invoice_parameters_generated(
906906
&self, counterparty_node_id: &PublicKey, request_id: LSPSRequestId, intercept_scid: u64,
907-
cltv_expiry_delta: u32, client_trusts_lsp: bool, user_channel_id: u128,
907+
cltv_expiry_delta: u16, client_trusts_lsp: bool, user_channel_id: u128,
908908
) -> Result<(), APIError> {
909909
let mut message_queue_notifier = self.pending_messages.notifier();
910910
let mut should_persist = false;
@@ -2179,7 +2179,7 @@ where
21792179
/// Wraps [`LSPS2ServiceHandler::invoice_parameters_generated`].
21802180
pub fn invoice_parameters_generated(
21812181
&self, counterparty_node_id: &PublicKey, request_id: LSPSRequestId, intercept_scid: u64,
2182-
cltv_expiry_delta: u32, client_trusts_lsp: bool, user_channel_id: u128,
2182+
cltv_expiry_delta: u16, client_trusts_lsp: bool, user_channel_id: u128,
21832183
) -> Result<(), APIError> {
21842184
let mut fut = pin!(self.inner.invoice_parameters_generated(
21852185
counterparty_node_id,

lightning-liquidity/tests/lsps2_integration_tests.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ fn setup_test_lsps2_nodes_with_payer<'a, 'b, 'c>(
165165

166166
fn create_jit_invoice(
167167
node: &LiquidityNode<'_, '_, '_>, service_node_id: PublicKey, intercept_scid: u64,
168-
cltv_expiry_delta: u32, payment_size_msat: Option<u64>, description: &str, expiry_secs: u32,
168+
cltv_expiry_delta: u16, payment_size_msat: Option<u64>, description: &str, expiry_secs: u32,
169169
) -> Result<Bolt11Invoice, ()> {
170170
// LSPS2 requires min_final_cltv_expiry_delta to be at least 2 more than usual.
171171
let min_final_cltv_expiry_delta = MIN_FINAL_CLTV_EXPIRY_DELTA + 2;
@@ -180,7 +180,7 @@ fn create_jit_invoice(
180180
src_node_id: service_node_id,
181181
short_channel_id: intercept_scid,
182182
fees: RoutingFees { base_msat: 0, proportional_millionths: 0 },
183-
cltv_expiry_delta: cltv_expiry_delta as u16,
183+
cltv_expiry_delta,
184184
htlc_minimum_msat: None,
185185
htlc_maximum_msat: None,
186186
}]);
@@ -1216,7 +1216,7 @@ fn client_trusts_lsp_end_to_end_test() {
12161216

12171217
let intercept_scid = service_node.node.get_intercept_scid();
12181218
let user_channel_id = 42;
1219-
let cltv_expiry_delta: u32 = 144;
1219+
let cltv_expiry_delta: u16 = 144;
12201220
let payment_size_msat = Some(1_000_000);
12211221

12221222
let fee_base_msat = 1000;
@@ -1394,7 +1394,7 @@ fn client_trusts_lsp_end_to_end_test() {
13941394

13951395
fn execute_lsps2_dance(
13961396
lsps_nodes: &LSPSNodesWithPayer, intercept_scid: u64, user_channel_id: u128,
1397-
cltv_expiry_delta: u32, promise_secret: [u8; 32], payment_size_msat: Option<u64>,
1397+
cltv_expiry_delta: u16, promise_secret: [u8; 32], payment_size_msat: Option<u64>,
13981398
fee_base_msat: u64,
13991399
) {
14001400
let service_node = &lsps_nodes.service_node;
@@ -1638,7 +1638,7 @@ fn bolt12_lsps2_end_to_end_test() {
16381638

16391639
let intercept_scid = service_node.node.get_intercept_scid();
16401640
let user_channel_id = 42;
1641-
let cltv_expiry_delta: u32 = 144;
1641+
let cltv_expiry_delta: u16 = 144;
16421642
let payment_size_msat = Some(1_000_000);
16431643
let fee_base_msat = 1_000;
16441644

@@ -1902,7 +1902,7 @@ fn bolt12_lsps2_compact_message_path_test() {
19021902

19031903
let intercept_scid = service_node.node.get_intercept_scid();
19041904
let user_channel_id = 42;
1905-
let cltv_expiry_delta: u32 = 144;
1905+
let cltv_expiry_delta: u16 = 144;
19061906
let payment_size_msat = Some(1_000_000);
19071907
let fee_base_msat = 1_000;
19081908

@@ -2225,7 +2225,7 @@ fn late_payment_forwarded_and_safe_after_force_close_does_not_broadcast() {
22252225

22262226
let intercept_scid = service_node.node.get_intercept_scid();
22272227
let user_channel_id = 43u128;
2228-
let cltv_expiry_delta: u32 = 144;
2228+
let cltv_expiry_delta: u16 = 144;
22292229
let payment_size_msat = Some(1_000_000);
22302230
let fee_base_msat: u64 = 10_000;
22312231

@@ -2414,7 +2414,7 @@ fn htlc_timeout_before_client_claim_results_in_handling_failed() {
24142414

24152415
let intercept_scid = service_node.node.get_intercept_scid();
24162416
let user_channel_id = 44u128;
2417-
let cltv_expiry_delta: u32 = 144;
2417+
let cltv_expiry_delta: u16 = 144;
24182418
let payment_size_msat = Some(1_000_000);
24192419
let fee_base_msat: u64 = 10_000;
24202420

@@ -2748,7 +2748,7 @@ fn client_trusts_lsp_partial_fee_does_not_trigger_broadcast() {
27482748

27492749
let intercept_scid = service_node.node.get_intercept_scid();
27502750
let user_channel_id = 42;
2751-
let cltv_expiry_delta: u32 = 144;
2751+
let cltv_expiry_delta: u16 = 144;
27522752
let payment_size_msat = Some(1_000_000);
27532753

27542754
let fee_base_msat: u64 = 10_000;

0 commit comments

Comments
 (0)