@@ -77,6 +77,7 @@ use vss_client::headers::{FixedHeaders, LnurlAuthToJwtProvider, VssHeaderProvide
77
77
78
78
const VSS_HARDENED_CHILD_INDEX : u32 = 877 ;
79
79
const VSS_LNURL_AUTH_HARDENED_CHILD_INDEX : u32 = 138 ;
80
+ const LSPS_HARDENED_CHILD_INDEX : u32 = 577 ;
80
81
81
82
#[ derive( Debug , Clone ) ]
82
83
enum ChainDataSourceConfig {
@@ -103,6 +104,8 @@ struct LiquiditySourceConfig {
103
104
lsps1_client : Option < LSPS1ClientConfig > ,
104
105
// Act as an LSPS2 client connecting to the given service.
105
106
lsps2_client : Option < LSPS2ClientConfig > ,
107
+ // Act as an LSPS2 service.
108
+ lsps2_service : Option < LSPS2ServiceConfig > ,
106
109
}
107
110
108
111
#[ derive( Debug , Clone ) ]
@@ -119,6 +122,12 @@ struct LSPS2ClientConfig {
119
122
token : Option < String > ,
120
123
}
121
124
125
+ #[ derive( Debug , Clone ) ]
126
+ struct LSPS2ServiceConfig {
127
+ token : Option < String > ,
128
+ advertise_service : bool ,
129
+ }
130
+
122
131
#[ derive( Clone ) ]
123
132
enum LogWriterConfig {
124
133
File { log_file_path : Option < String > , max_log_level : Option < LogLevel > } ,
@@ -356,6 +365,26 @@ impl NodeBuilder {
356
365
self
357
366
}
358
367
368
+ /// Configures the [`Node`] instance to provide an [LSPS2] service, issuing just-in-time
369
+ /// channels to clients.
370
+ ///
371
+ /// If a `token` is provided, only requests matching this token will be accepted.
372
+ ///
373
+ /// If `advertise_service` is set, the LSPS service will be announced via the gossip network.
374
+ ///
375
+ /// **Caution**: LSP service support is in **alpha** and is considered an experimental feature.
376
+ ///
377
+ /// [LSPS2]: https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/main/LSPS2/README.md
378
+ pub fn set_liquidity_provider_lsps2 (
379
+ & mut self , token : Option < String > , advertise_service : bool ,
380
+ ) -> & mut Self {
381
+ let liquidity_source_config =
382
+ self . liquidity_source_config . get_or_insert ( LiquiditySourceConfig :: default ( ) ) ;
383
+ let lsps2_service_config = LSPS2ServiceConfig { token, advertise_service } ;
384
+ liquidity_source_config. lsps2_service = Some ( lsps2_service_config) ;
385
+ self
386
+ }
387
+
359
388
/// Sets the used storage directory path.
360
389
pub fn set_storage_dir_path ( & mut self , storage_dir_path : String ) -> & mut Self {
361
390
self . config . storage_dir_path = storage_dir_path;
@@ -713,6 +742,20 @@ impl ArcedNodeBuilder {
713
742
self . inner . write ( ) . unwrap ( ) . set_liquidity_source_lsps2 ( node_id, address, token) ;
714
743
}
715
744
745
+ /// Configures the [`Node`] instance to provide an [LSPS2] service, issuing just-in-time
746
+ /// channels to clients.
747
+ ///
748
+ /// If a `token` is provided, only requests matching this token will be accepted.
749
+ ///
750
+ /// If `advertise_service` is set, the LSPS service will be announced via the gossip network.
751
+ ///
752
+ /// **Caution**: LSP service support is in **alpha** and is considered an experimental feature.
753
+ ///
754
+ /// [LSPS2]: https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/main/LSPS2/README.md
755
+ pub fn set_liquidity_provider_lsps2 ( & self , token : Option < String > , advertise_service : bool ) {
756
+ self . inner . write ( ) . unwrap ( ) . set_liquidity_provider_lsps2 ( token, advertise_service) ;
757
+ }
758
+
716
759
/// Sets the used storage directory path.
717
760
pub fn set_storage_dir_path ( & self , storage_dir_path : String ) {
718
761
self . inner . write ( ) . unwrap ( ) . set_storage_dir_path ( storage_dir_path) ;
@@ -1193,39 +1236,56 @@ fn build_with_store_internal(
1193
1236
} ,
1194
1237
} ;
1195
1238
1196
- let liquidity_source = liquidity_source_config. as_ref ( ) . map ( |lsc| {
1197
- let mut liquidity_source_builder = LiquiditySourceBuilder :: new (
1198
- Arc :: clone ( & channel_manager) ,
1199
- Arc :: clone ( & keys_manager) ,
1200
- Arc :: clone ( & chain_source) ,
1201
- Arc :: clone ( & config) ,
1202
- Arc :: clone ( & logger) ,
1203
- ) ;
1239
+ let ( liquidity_source, custom_message_handler) =
1240
+ if let Some ( lsc) = liquidity_source_config. as_ref ( ) {
1241
+ let mut liquidity_source_builder = LiquiditySourceBuilder :: new (
1242
+ Arc :: clone ( & channel_manager) ,
1243
+ Arc :: clone ( & keys_manager) ,
1244
+ Arc :: clone ( & chain_source) ,
1245
+ Arc :: clone ( & config) ,
1246
+ Arc :: clone ( & logger) ,
1247
+ ) ;
1204
1248
1205
- lsc. lsps1_client . as_ref ( ) . map ( |config| {
1206
- liquidity_source_builder. lsps1_client (
1207
- config. node_id ,
1208
- config. address . clone ( ) ,
1209
- config. token . clone ( ) ,
1210
- )
1211
- } ) ;
1249
+ lsc. lsps1_client . as_ref ( ) . map ( |config| {
1250
+ liquidity_source_builder. lsps1_client (
1251
+ config. node_id ,
1252
+ config. address . clone ( ) ,
1253
+ config. token . clone ( ) ,
1254
+ )
1255
+ } ) ;
1212
1256
1213
- lsc. lsps2_client . as_ref ( ) . map ( |config| {
1214
- liquidity_source_builder. lsps2_client (
1215
- config. node_id ,
1216
- config. address . clone ( ) ,
1217
- config. token . clone ( ) ,
1218
- )
1219
- } ) ;
1257
+ lsc. lsps2_client . as_ref ( ) . map ( |config| {
1258
+ liquidity_source_builder. lsps2_client (
1259
+ config. node_id ,
1260
+ config. address . clone ( ) ,
1261
+ config. token . clone ( ) ,
1262
+ )
1263
+ } ) ;
1220
1264
1221
- Arc :: new ( liquidity_source_builder. build ( ) )
1222
- } ) ;
1265
+ let promise_secret = {
1266
+ let lsps_xpriv = derive_xprv (
1267
+ Arc :: clone ( & config) ,
1268
+ & seed_bytes,
1269
+ LSPS_HARDENED_CHILD_INDEX ,
1270
+ Arc :: clone ( & logger) ,
1271
+ ) ?;
1272
+ lsps_xpriv. private_key . secret_bytes ( )
1273
+ } ;
1274
+ lsc. lsps2_service . as_ref ( ) . map ( |config| {
1275
+ liquidity_source_builder. lsps2_service (
1276
+ promise_secret,
1277
+ config. token . clone ( ) ,
1278
+ config. advertise_service ,
1279
+ )
1280
+ } ) ;
1223
1281
1224
- let custom_message_handler = if let Some ( liquidity_source) = liquidity_source. as_ref ( ) {
1225
- Arc :: new ( NodeCustomMessageHandler :: new_liquidity ( Arc :: clone ( & liquidity_source) ) )
1226
- } else {
1227
- Arc :: new ( NodeCustomMessageHandler :: new_ignoring ( ) )
1228
- } ;
1282
+ let liquidity_source = Arc :: new ( liquidity_source_builder. build ( ) ) ;
1283
+ let custom_message_handler =
1284
+ Arc :: new ( NodeCustomMessageHandler :: new_liquidity ( Arc :: clone ( & liquidity_source) ) ) ;
1285
+ ( Some ( liquidity_source) , custom_message_handler)
1286
+ } else {
1287
+ ( None , Arc :: new ( NodeCustomMessageHandler :: new_ignoring ( ) ) )
1288
+ } ;
1229
1289
1230
1290
let msg_handler = match gossip_source. as_gossip_sync ( ) {
1231
1291
GossipSync :: P2P ( p2p_gossip_sync) => MessageHandler {
0 commit comments