Skip to content

Commit fcc16bb

Browse files
committed
Test LSPS2 router payment-path generation for BOLT12
Exercise the LSPS2 buy flow and assert that registered LSPS2 parameters produce a blinded payment path whose first forwarding hop uses the negotiated intercept SCID. Co-Authored-By: HAL 9000 Signed-off-by: Elias Rohrer <dev@tnull.de>
1 parent aa53846 commit fcc16bb

1 file changed

Lines changed: 134 additions & 0 deletions

File tree

lightning-liquidity/tests/lsps2_integration_tests.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,28 @@ 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::onion_message::messenger::NullMessageRouter;
21+
use lightning::routing::router::{InFlightHtlcs, Route, RouteParameters, Router};
22+
use lightning::sign::ReceiveAuthKey;
1823

1924
use lightning_liquidity::events::LiquidityEvent;
2025
use lightning_liquidity::lsps0::ser::LSPSDateTime;
2126
use lightning_liquidity::lsps2::client::LSPS2ClientConfig;
2227
use lightning_liquidity::lsps2::event::LSPS2ClientEvent;
2328
use lightning_liquidity::lsps2::event::LSPS2ServiceEvent;
2429
use lightning_liquidity::lsps2::msgs::LSPS2RawOpeningFeeParams;
30+
use lightning_liquidity::lsps2::router::{LSPS2BOLT12Router, LSPS2Bolt12InvoiceParameters};
2531
use lightning_liquidity::lsps2::service::LSPS2ServiceConfig;
2632
use lightning_liquidity::lsps2::utils::is_valid_opening_fee_params;
2733
use lightning_liquidity::utils::time::{DefaultTimeProvider, TimeProvider};
2834
use lightning_liquidity::{LiquidityClientConfig, LiquidityManagerSync, LiquidityServiceConfig};
2935

36+
use lightning::blinded_path::payment::{
37+
Bolt12OfferContext, PaymentConstraints, PaymentContext, ReceiveTlvs,
38+
};
39+
use lightning::blinded_path::NodeIdLookUp;
3040
use lightning::ln::channelmanager::{InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
3141
use lightning::ln::functional_test_utils::{
3242
create_chanmon_cfgs, create_node_cfgs, create_node_chanmgrs,
@@ -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 };
@@ -1476,6 +1526,90 @@ fn execute_lsps2_dance(
14761526
}
14771527
}
14781528

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

0 commit comments

Comments
 (0)