@@ -90,7 +90,7 @@ pub(crate) struct LSPS2ClientConfig {
9090}
9191
9292struct LSPS2Service {
93- service_config : LSPS2ServiceConfig ,
93+ service_config : Arc < RwLock < LSPS2ServiceConfig > > ,
9494 ldk_service_config : LdkLSPS2ServiceConfig ,
9595}
9696
@@ -132,6 +132,60 @@ pub struct LSPS2ServiceConfig {
132132 pub max_payment_size_msat : u64 ,
133133}
134134
135+ /// Represents a partial update to the LSPS2 service configuration.
136+ ///
137+ /// Only fields set to `Some` will be updated; fields set to `None` will be ignored.
138+ #[ derive( Debug , Clone , Default ) ]
139+ pub struct LSPS2ServiceConfigUpdate {
140+ /// Update the required token (None to remove, Some to set).
141+ pub require_token : Option < Option < String > > ,
142+ /// Update the channel opening fee in parts-per-million.
143+ pub channel_opening_fee_ppm : Option < u32 > ,
144+ /// Update the proportional overprovisioning for the channel.
145+ pub channel_over_provisioning_ppm : Option < u32 > ,
146+ /// Update the minimum fee required for opening a channel.
147+ pub min_channel_opening_fee_msat : Option < u64 > ,
148+ /// Update the minimum number of blocks to keep the channel open.
149+ pub min_channel_lifetime : Option < u32 > ,
150+ /// Update the maximum client to_self_delay.
151+ pub max_client_to_self_delay : Option < u32 > ,
152+ /// Update the minimum payment size.
153+ pub min_payment_size_msat : Option < u64 > ,
154+ /// Update the maximum payment size.
155+ pub max_payment_size_msat : Option < u64 > ,
156+ }
157+
158+ impl LSPS2ServiceConfig {
159+ /// Applies a partial update to the configuration.
160+ /// Only fields present in `update` (i.e., `Some`) will be changed.
161+ pub fn apply_update ( & mut self , update : LSPS2ServiceConfigUpdate ) {
162+ if let Some ( require_token) = update. require_token {
163+ self . require_token = require_token;
164+ }
165+ if let Some ( channel_opening_fee_ppm) = update. channel_opening_fee_ppm {
166+ self . channel_opening_fee_ppm = channel_opening_fee_ppm;
167+ }
168+ if let Some ( channel_over_provisioning_ppm) = update. channel_over_provisioning_ppm {
169+ self . channel_over_provisioning_ppm = channel_over_provisioning_ppm;
170+ }
171+ if let Some ( min_channel_opening_fee_msat) = update. min_channel_opening_fee_msat {
172+ self . min_channel_opening_fee_msat = min_channel_opening_fee_msat;
173+ }
174+ if let Some ( min_channel_lifetime) = update. min_channel_lifetime {
175+ self . min_channel_lifetime = min_channel_lifetime;
176+ }
177+ if let Some ( max_client_to_self_delay) = update. max_client_to_self_delay {
178+ self . max_client_to_self_delay = max_client_to_self_delay;
179+ }
180+ if let Some ( min_payment_size_msat) = update. min_payment_size_msat {
181+ self . min_payment_size_msat = min_payment_size_msat;
182+ }
183+ if let Some ( max_payment_size_msat) = update. max_payment_size_msat {
184+ self . max_payment_size_msat = max_payment_size_msat;
185+ }
186+ }
187+ }
188+
135189pub ( crate ) struct LiquiditySourceBuilder < L : Deref >
136190where
137191 L :: Target : LdkLogger ,
@@ -217,16 +271,29 @@ where
217271 & mut self , promise_secret : [ u8 ; 32 ] , service_config : LSPS2ServiceConfig ,
218272 ) -> & mut Self {
219273 let ldk_service_config = LdkLSPS2ServiceConfig { promise_secret } ;
220- self . lsps2_service = Some ( LSPS2Service { service_config, ldk_service_config } ) ;
274+ self . lsps2_service = Some ( LSPS2Service {
275+ service_config : Arc :: new ( RwLock :: new ( service_config) ) ,
276+ ldk_service_config,
277+ } ) ;
221278 self
222279 }
223280
224281 pub ( crate ) async fn build ( self ) -> Result < LiquiditySource < L > , BuildError > {
225- let liquidity_service_config = self . lsps2_service . as_ref ( ) . map ( |s| {
282+ let liquidity_service_config = self . lsps2_service . as_ref ( ) . and_then ( |s| {
226283 let lsps2_service_config = Some ( s. ldk_service_config . clone ( ) ) ;
227284 let lsps5_service_config = None ;
228- let advertise_service = s. service_config . advertise_service ;
229- LiquidityServiceConfig { lsps2_service_config, lsps5_service_config, advertise_service }
285+ let advertise_service = match s. service_config . read ( ) {
286+ Ok ( cfg) => cfg. advertise_service ,
287+ Err ( e) => {
288+ log_error ! ( self . logger, "Failed to acquire LSPS2 service config lock: {:?}" , e) ;
289+ return None ;
290+ } ,
291+ } ;
292+ Some ( LiquidityServiceConfig {
293+ lsps2_service_config,
294+ lsps5_service_config,
295+ advertise_service,
296+ } )
230297 } ) ;
231298
232299 let lsps1_client_config = self . lsps1_client . as_ref ( ) . map ( |s| s. ldk_client_config . clone ( ) ) ;
@@ -305,6 +372,13 @@ where
305372 self . lsps2_client . as_ref ( ) . map ( |s| ( s. lsp_node_id , s. lsp_address . clone ( ) ) )
306373 }
307374
375+ fn get_lsps2_service_config ( & self ) -> Option < LSPS2ServiceConfig > {
376+ self . lsps2_service
377+ . as_ref ( )
378+ . and_then ( |s| s. service_config . read ( ) . ok ( ) )
379+ . map ( |cfg| cfg. clone ( ) ) // Clone to release lock
380+ }
381+
308382 pub ( crate ) async fn handle_next_event ( & self ) {
309383 match self . liquidity_manager . next_event_async ( ) . await {
310384 LiquidityEvent :: LSPS1Client ( LSPS1ClientEvent :: SupportedOptionsReady {
@@ -485,7 +559,7 @@ where
485559 self . liquidity_manager . lsps2_service_handler ( ) . as_ref ( )
486560 {
487561 let service_config = if let Some ( service_config) =
488- self . lsps2_service . as_ref ( ) . map ( |s| s . service_config . clone ( ) )
562+ self . get_lsps2_service_config ( )
489563 {
490564 service_config
491565 } else {
@@ -554,7 +628,7 @@ where
554628 self . liquidity_manager . lsps2_service_handler ( ) . as_ref ( )
555629 {
556630 let service_config = if let Some ( service_config) =
557- self . lsps2_service . as_ref ( ) . map ( |s| s . service_config . clone ( ) )
631+ self . get_lsps2_service_config ( )
558632 {
559633 service_config
560634 } else {
@@ -626,9 +700,7 @@ where
626700 return ;
627701 } ;
628702
629- let service_config = if let Some ( service_config) =
630- self . lsps2_service . as_ref ( ) . map ( |s| s. service_config . clone ( ) )
631- {
703+ let service_config = if let Some ( service_config) = self . get_lsps2_service_config ( ) {
632704 service_config
633705 } else {
634706 log_error ! ( self . logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured." , ) ;
@@ -1000,6 +1072,27 @@ where
10001072 Ok ( response)
10011073 }
10021074
1075+ pub ( crate ) fn lsps2_update_service_config (
1076+ & self , update : LSPS2ServiceConfigUpdate ,
1077+ ) -> Result < ( ) , Error > {
1078+ if let Some ( lsps2_service) = self . lsps2_service . as_ref ( ) {
1079+ if let Ok ( mut config) = lsps2_service. service_config . write ( ) {
1080+ config. apply_update ( update) ;
1081+ log_info ! ( self . logger, "Partially updated LSPS2 service configuration." ) ;
1082+ Ok ( ( ) )
1083+ } else {
1084+ log_error ! ( self . logger, "Failed to acquire LSPS2 service config lock." ) ;
1085+ Err ( Error :: InvalidLSP2Config )
1086+ }
1087+ } else {
1088+ log_error ! (
1089+ self . logger,
1090+ "Failed to update LSPS2 service config as LSPS2 service was not configured."
1091+ ) ;
1092+ Err ( Error :: LSP2ServiceNotConfigured )
1093+ }
1094+ }
1095+
10031096 pub ( crate ) async fn lsps2_receive_to_jit_channel (
10041097 & self , amount_msat : u64 , description : & Bolt11InvoiceDescription , expiry_secs : u32 ,
10051098 max_total_lsp_fee_limit_msat : Option < u64 > , payment_hash : Option < PaymentHash > ,
0 commit comments