Skip to content

Commit 673eb3f

Browse files
committed
Test LSPS2 router payment-path generation for BOLT12
Exercise the LSPS2 buy flow and assert that a registered `OfferId` produces a blinded payment path whose first forwarding hop uses the negotiated intercept `SCID`. Co-Authored-By: HAL 9000
1 parent 3dc1c22 commit 673eb3f

1 file changed

Lines changed: 131 additions & 1 deletion

File tree

lightning-liquidity/tests/lsps2_integration_tests.rs

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@ use lightning::ln::msgs::BaseMessageHandler;
1515
use lightning::ln::msgs::ChannelMessageHandler;
1616
use lightning::ln::msgs::MessageSendEvent;
1717
use lightning::ln::types::ChannelId;
18+
use lightning::offers::invoice_request::InvoiceRequestFields;
19+
use lightning::offers::offer::OfferId;
20+
use lightning::routing::router::{InFlightHtlcs, Route, RouteParameters, Router};
21+
use lightning::sign::ReceiveAuthKey;
1822

1923
use lightning_liquidity::events::LiquidityEvent;
2024
use lightning_liquidity::lsps0::ser::LSPSDateTime;
2125
use lightning_liquidity::lsps2::client::LSPS2ClientConfig;
2226
use lightning_liquidity::lsps2::event::LSPS2ClientEvent;
2327
use lightning_liquidity::lsps2::event::LSPS2ServiceEvent;
2428
use lightning_liquidity::lsps2::msgs::LSPS2RawOpeningFeeParams;
29+
use lightning_liquidity::lsps2::router::{LSPS2BOLT12Router, LSPS2Bolt12InvoiceParameters};
2530
use lightning_liquidity::lsps2::service::LSPS2ServiceConfig;
2631
use lightning_liquidity::lsps2::utils::is_valid_opening_fee_params;
2732
use lightning_liquidity::utils::time::{DefaultTimeProvider, TimeProvider};
@@ -30,7 +35,12 @@ use lightning_liquidity::{
3035
LiquidityServiceConfig,
3136
};
3237

33-
use lightning::ln::channelmanager::{InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
38+
use lightning::blinded_path::payment::{
39+
Bolt12OfferContext, PaymentConstraints, PaymentContext, ReceiveTlvs,
40+
};
41+
use lightning::blinded_path::NodeIdLookUp;
42+
use lightning::chain::{BestBlock, Filter};
43+
use lightning::ln::channelmanager::{ChainParameters, InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
3444
use lightning::ln::functional_test_utils::{
3545
create_chanmon_cfgs, create_node_cfgs, create_node_chanmgrs,
3646
};
@@ -59,6 +69,46 @@ use std::time::Duration;
5969
const MAX_PENDING_REQUESTS_PER_PEER: usize = 10;
6070
const MAX_TOTAL_PENDING_REQUESTS: usize = 1000;
6171

72+
struct RecordingLookup {
73+
next_node_id: PublicKey,
74+
short_channel_id: std::sync::Mutex<Option<u64>>,
75+
}
76+
77+
impl NodeIdLookUp for RecordingLookup {
78+
fn next_node_id(&self, short_channel_id: u64) -> Option<PublicKey> {
79+
*self.short_channel_id.lock().unwrap() = Some(short_channel_id);
80+
Some(self.next_node_id)
81+
}
82+
}
83+
84+
struct FailingRouter;
85+
86+
impl FailingRouter {
87+
fn new() -> Self {
88+
Self
89+
}
90+
}
91+
92+
impl Router for FailingRouter {
93+
fn find_route(
94+
&self, _payer: &PublicKey, _route_params: &RouteParameters,
95+
_first_hops: Option<&[&lightning::ln::channel_state::ChannelDetails]>,
96+
_inflight_htlcs: InFlightHtlcs,
97+
) -> Result<Route, &'static str> {
98+
Err("failing test router")
99+
}
100+
101+
fn create_blinded_payment_paths<
102+
T: bitcoin::secp256k1::Signing + bitcoin::secp256k1::Verification,
103+
>(
104+
&self, _recipient: PublicKey, _local_node_receive_key: ReceiveAuthKey,
105+
_first_hops: Vec<lightning::ln::channel_state::ChannelDetails>, _tlvs: ReceiveTlvs,
106+
_amount_msats: Option<u64>, _secp_ctx: &Secp256k1<T>,
107+
) -> Result<Vec<lightning::blinded_path::payment::BlindedPaymentPath>, ()> {
108+
Err(())
109+
}
110+
}
111+
62112
fn build_lsps2_configs() -> ([u8; 32], LiquidityServiceConfig, LiquidityClientConfig) {
63113
let promise_secret = [42; 32];
64114
let lsps2_service_config = LSPS2ServiceConfig { promise_secret };
@@ -1494,6 +1544,86 @@ fn execute_lsps2_dance(
14941544
}
14951545
}
14961546

1547+
#[test]
1548+
fn bolt12_custom_router_uses_lsps2_intercept_scid() {
1549+
let chanmon_cfgs = create_chanmon_cfgs(3);
1550+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
1551+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
1552+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
1553+
let (lsps_nodes, promise_secret) = setup_test_lsps2_nodes_with_payer(nodes);
1554+
1555+
let service_node_id = lsps_nodes.service_node.inner.node.get_our_node_id();
1556+
let client_node_id = lsps_nodes.client_node.inner.node.get_our_node_id();
1557+
1558+
let intercept_scid = lsps_nodes.service_node.node.get_intercept_scid();
1559+
let cltv_expiry_delta = 72;
1560+
1561+
execute_lsps2_dance(
1562+
&lsps_nodes,
1563+
intercept_scid,
1564+
42,
1565+
cltv_expiry_delta,
1566+
promise_secret,
1567+
Some(250_000),
1568+
1_000,
1569+
);
1570+
1571+
let inner_router = FailingRouter::new();
1572+
let router = LSPS2BOLT12Router::new(inner_router, lsps_nodes.client_node.keys_manager);
1573+
let offer_id = OfferId([42; 32]);
1574+
1575+
router.register_offer(
1576+
offer_id,
1577+
LSPS2Bolt12InvoiceParameters {
1578+
counterparty_node_id: service_node_id,
1579+
intercept_scid,
1580+
cltv_expiry_delta,
1581+
},
1582+
);
1583+
1584+
let tlvs = ReceiveTlvs {
1585+
payment_secret: lightning_types::payment::PaymentSecret([7; 32]),
1586+
payment_constraints: PaymentConstraints { max_cltv_expiry: 50, htlc_minimum_msat: 1 },
1587+
payment_context: PaymentContext::Bolt12Offer(Bolt12OfferContext {
1588+
offer_id,
1589+
invoice_request: InvoiceRequestFields {
1590+
payer_signing_pubkey: lsps_nodes.payer_node.node.get_our_node_id(),
1591+
quantity: None,
1592+
payer_note_truncated: None,
1593+
human_readable_name: None,
1594+
},
1595+
}),
1596+
};
1597+
1598+
let secp_ctx = Secp256k1::new();
1599+
let mut paths = router
1600+
.create_blinded_payment_paths(
1601+
client_node_id,
1602+
ReceiveAuthKey([3; 32]),
1603+
Vec::new(),
1604+
tlvs,
1605+
Some(100_000),
1606+
&secp_ctx,
1607+
)
1608+
.unwrap();
1609+
1610+
assert_eq!(paths.len(), 1);
1611+
let mut path = paths.pop().unwrap();
1612+
assert_eq!(
1613+
path.introduction_node(),
1614+
&lightning::blinded_path::IntroductionNode::NodeId(service_node_id)
1615+
);
1616+
assert_eq!(path.payinfo.fee_base_msat, 0);
1617+
assert_eq!(path.payinfo.fee_proportional_millionths, 0);
1618+
1619+
let lookup = RecordingLookup {
1620+
next_node_id: client_node_id,
1621+
short_channel_id: std::sync::Mutex::new(None),
1622+
};
1623+
path.advance_path_by_one(lsps_nodes.service_node.keys_manager, &lookup, &secp_ctx).unwrap();
1624+
assert_eq!(*lookup.short_channel_id.lock().unwrap(), Some(intercept_scid));
1625+
}
1626+
14971627
fn create_channel_with_manual_broadcast(
14981628
service_node_id: &PublicKey, client_node_id: &PublicKey, service_node: &LiquidityNode,
14991629
client_node: &LiquidityNode, user_channel_id: u128, expected_outbound_amount_msat: &u64,

0 commit comments

Comments
 (0)