Skip to content

Commit fec9c23

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 94ac41f commit fec9c23

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,19 +15,29 @@ 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};
2833
use lightning_liquidity::{LiquidityClientConfig, LiquidityManagerSync, LiquidityServiceConfig};
2934

30-
use lightning::ln::channelmanager::{InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
35+
use lightning::blinded_path::payment::{
36+
Bolt12OfferContext, PaymentConstraints, PaymentContext, ReceiveTlvs,
37+
};
38+
use lightning::blinded_path::NodeIdLookUp;
39+
use lightning::chain::{BestBlock, Filter};
40+
use lightning::ln::channelmanager::{ChainParameters, InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
3141
use lightning::ln::functional_test_utils::{
3242
create_chanmon_cfgs, create_node_cfgs, create_node_chanmgrs,
3343
};
@@ -56,6 +66,46 @@ use std::time::Duration;
5666
const MAX_PENDING_REQUESTS_PER_PEER: usize = 10;
5767
const MAX_TOTAL_PENDING_REQUESTS: usize = 1000;
5868

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

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

0 commit comments

Comments
 (0)