Skip to content

Commit ba2f86d

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 ecf2322 commit ba2f86d

5 files changed

Lines changed: 20 additions & 79 deletions

File tree

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
@@ -160,19 +160,16 @@ impl<R: Router, ES: EntropySource> Router for LSPS2BOLT12Router<R, ES> {
160160
// the paths in this exact order.
161161
let mut paths = inner_res.unwrap_or_default();
162162
for lsps2_invoice_params in all_params {
163-
let payment_relay = match u16::try_from(lsps2_invoice_params.cltv_expiry_delta) {
164-
Ok(cltv_expiry_delta) => PaymentRelay {
165-
cltv_expiry_delta,
166-
fee_proportional_millionths: 0,
167-
fee_base_msat: 0,
168-
},
169-
Err(_) => continue,
163+
let payment_relay = PaymentRelay {
164+
cltv_expiry_delta: lsps2_invoice_params.cltv_expiry_delta,
165+
fee_proportional_millionths: 0,
166+
fee_base_msat: 0,
170167
};
171168
let payment_constraints = PaymentConstraints {
172169
max_cltv_expiry: tlvs
173170
.payment_constraints
174171
.max_cltv_expiry
175-
.saturating_add(lsps2_invoice_params.cltv_expiry_delta),
172+
.saturating_add(lsps2_invoice_params.cltv_expiry_delta as u32),
176173
htlc_minimum_msat: 0,
177174
};
178175

@@ -376,7 +373,7 @@ mod tests {
376373
assert_eq!(path.payinfo.fee_proportional_millionths, 0);
377374
assert_eq!(
378375
path.payinfo.cltv_expiry_delta,
379-
expected_cltv_delta as u16 + MIN_FINAL_CLTV_EXPIRY_DELTA
376+
expected_cltv_delta + MIN_FINAL_CLTV_EXPIRY_DELTA
380377
);
381378

382379
let lookup =
@@ -427,62 +424,6 @@ mod tests {
427424
assert_eq!(router.inner_router.create_blinded_payment_paths_calls(), 1);
428425
}
429426

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

168168
fn create_jit_invoice(
169169
node: &LiquidityNode<'_, '_, '_>, service_node_id: PublicKey, intercept_scid: u64,
170-
cltv_expiry_delta: u32, payment_size_msat: Option<u64>, description: &str, expiry_secs: u32,
170+
cltv_expiry_delta: u16, payment_size_msat: Option<u64>, description: &str, expiry_secs: u32,
171171
) -> Result<Bolt11Invoice, ()> {
172172
// LSPS2 requires min_final_cltv_expiry_delta to be at least 2 more than usual.
173173
let min_final_cltv_expiry_delta = MIN_FINAL_CLTV_EXPIRY_DELTA + 2;
@@ -182,7 +182,7 @@ fn create_jit_invoice(
182182
src_node_id: service_node_id,
183183
short_channel_id: intercept_scid,
184184
fees: RoutingFees { base_msat: 0, proportional_millionths: 0 },
185-
cltv_expiry_delta: cltv_expiry_delta as u16,
185+
cltv_expiry_delta,
186186
htlc_minimum_msat: None,
187187
htlc_maximum_msat: None,
188188
}]);
@@ -1218,7 +1218,7 @@ fn client_trusts_lsp_end_to_end_test() {
12181218

12191219
let intercept_scid = service_node.node.get_intercept_scid();
12201220
let user_channel_id = 42;
1221-
let cltv_expiry_delta: u32 = 144;
1221+
let cltv_expiry_delta: u16 = 144;
12221222
let payment_size_msat = Some(1_000_000);
12231223

12241224
let fee_base_msat = 1000;
@@ -1396,7 +1396,7 @@ fn client_trusts_lsp_end_to_end_test() {
13961396

13971397
fn execute_lsps2_dance(
13981398
lsps_nodes: &LSPSNodesWithPayer, intercept_scid: u64, user_channel_id: u128,
1399-
cltv_expiry_delta: u32, promise_secret: [u8; 32], payment_size_msat: Option<u64>,
1399+
cltv_expiry_delta: u16, promise_secret: [u8; 32], payment_size_msat: Option<u64>,
14001400
fee_base_msat: u64,
14011401
) {
14021402
let service_node = &lsps_nodes.service_node;
@@ -1640,7 +1640,7 @@ fn bolt12_lsps2_end_to_end_test() {
16401640

16411641
let intercept_scid = service_node.node.get_intercept_scid();
16421642
let user_channel_id = 42;
1643-
let cltv_expiry_delta: u32 = 144;
1643+
let cltv_expiry_delta: u16 = 144;
16441644
let payment_size_msat = Some(1_000_000);
16451645
let fee_base_msat = 1_000;
16461646

@@ -1904,7 +1904,7 @@ fn bolt12_lsps2_compact_message_path_test() {
19041904

19051905
let intercept_scid = service_node.node.get_intercept_scid();
19061906
let user_channel_id = 42;
1907-
let cltv_expiry_delta: u32 = 144;
1907+
let cltv_expiry_delta: u16 = 144;
19081908
let payment_size_msat = Some(1_000_000);
19091909
let fee_base_msat = 1_000;
19101910

@@ -2228,7 +2228,7 @@ fn late_payment_forwarded_and_safe_after_force_close_does_not_broadcast() {
22282228

22292229
let intercept_scid = service_node.node.get_intercept_scid();
22302230
let user_channel_id = 43u128;
2231-
let cltv_expiry_delta: u32 = 144;
2231+
let cltv_expiry_delta: u16 = 144;
22322232
let payment_size_msat = Some(1_000_000);
22332233
let fee_base_msat: u64 = 10_000;
22342234

@@ -2417,7 +2417,7 @@ fn htlc_timeout_before_client_claim_results_in_handling_failed() {
24172417

24182418
let intercept_scid = service_node.node.get_intercept_scid();
24192419
let user_channel_id = 44u128;
2420-
let cltv_expiry_delta: u32 = 144;
2420+
let cltv_expiry_delta: u16 = 144;
24212421
let payment_size_msat = Some(1_000_000);
24222422
let fee_base_msat: u64 = 10_000;
24232423

@@ -2751,7 +2751,7 @@ fn client_trusts_lsp_partial_fee_does_not_trigger_broadcast() {
27512751

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

27572757
let fee_base_msat: u64 = 10_000;

0 commit comments

Comments
 (0)