@@ -11,7 +11,7 @@ use crate::chain::ChainSource;
1111use crate :: connection:: ConnectionManager ;
1212use crate :: logger:: { log_debug, log_error, log_info, LdkLogger , Logger } ;
1313use crate :: types:: { ChannelManager , KeysManager , LiquidityManager , PeerManager , Wallet } ;
14- use crate :: { Config , Error } ;
14+ use crate :: { total_anchor_channels_reserve_sats , Config , Error } ;
1515
1616use lightning:: events:: HTLCDestination ;
1717use lightning:: ln:: channelmanager:: { InterceptId , MIN_FINAL_CLTV_EXPIRY_DELTA } ;
@@ -27,8 +27,8 @@ use lightning_liquidity::lsps1::client::LSPS1ClientConfig as LdkLSPS1ClientConfi
2727use lightning_liquidity:: lsps1:: event:: LSPS1ClientEvent ;
2828use lightning_liquidity:: lsps1:: msgs:: { ChannelInfo , LSPS1Options , OrderId , OrderParameters } ;
2929use lightning_liquidity:: lsps2:: client:: LSPS2ClientConfig as LdkLSPS2ClientConfig ;
30- use lightning_liquidity:: lsps2:: event:: LSPS2ClientEvent ;
31- use lightning_liquidity:: lsps2:: msgs:: OpeningFeeParams ;
30+ use lightning_liquidity:: lsps2:: event:: { LSPS2ClientEvent , LSPS2ServiceEvent } ;
31+ use lightning_liquidity:: lsps2:: msgs:: { OpeningFeeParams , RawOpeningFeeParams } ;
3232use lightning_liquidity:: lsps2:: service:: LSPS2ServiceConfig as LdkLSPS2ServiceConfig ;
3333use lightning_liquidity:: lsps2:: utils:: compute_opening_fee;
3434use lightning_liquidity:: { LiquidityClientConfig , LiquidityServiceConfig } ;
@@ -40,13 +40,21 @@ use bitcoin::secp256k1::{PublicKey, Secp256k1};
4040
4141use tokio:: sync:: oneshot;
4242
43+ use chrono:: { DateTime , Utc } ;
44+
45+ use rand:: Rng ;
46+
4347use std:: collections:: HashMap ;
4448use std:: ops:: Deref ;
4549use std:: sync:: { Arc , Mutex , RwLock } ;
4650use std:: time:: Duration ;
4751
4852const LIQUIDITY_REQUEST_TIMEOUT_SECS : u64 = 5 ;
4953
54+ const LSPS2_GETINFO_REQUEST_EXPIRY : Duration = Duration :: from_secs ( 60 * 60 * 24 ) ;
55+ const LSPS2_CLIENT_TRUSTS_LSP_MODE : bool = true ;
56+ const LSPS2_CHANNEL_CLTV_EXPIRY_DELTA : u32 = 72 ;
57+
5058struct LSPS1Client {
5159 lsp_node_id : PublicKey ,
5260 lsp_address : SocketAddress ,
@@ -131,6 +139,7 @@ where
131139 lsps1_client : Option < LSPS1Client > ,
132140 lsps2_client : Option < LSPS2Client > ,
133141 lsps2_service : Option < LSPS2Service > ,
142+ wallet : Arc < Wallet > ,
134143 channel_manager : Arc < ChannelManager > ,
135144 keys_manager : Arc < KeysManager > ,
136145 chain_source : Arc < ChainSource > ,
@@ -143,7 +152,7 @@ where
143152 L :: Target : LdkLogger ,
144153{
145154 pub ( crate ) fn new (
146- channel_manager : Arc < ChannelManager > , keys_manager : Arc < KeysManager > ,
155+ wallet : Arc < Wallet > , channel_manager : Arc < ChannelManager > , keys_manager : Arc < KeysManager > ,
147156 chain_source : Arc < ChainSource > , config : Arc < Config > , logger : L ,
148157 ) -> Self {
149158 let lsps1_client = None ;
@@ -153,6 +162,7 @@ where
153162 lsps1_client,
154163 lsps2_client,
155164 lsps2_service,
165+ wallet,
156166 channel_manager,
157167 keys_manager,
158168 chain_source,
@@ -231,7 +241,9 @@ where
231241 lsps1_client : self . lsps1_client ,
232242 lsps2_client : self . lsps2_client ,
233243 lsps2_service : self . lsps2_service ,
244+ wallet : self . wallet ,
234245 channel_manager : self . channel_manager ,
246+ peer_manager : RwLock :: new ( None ) ,
235247 keys_manager : self . keys_manager ,
236248 liquidity_manager,
237249 config : self . config ,
@@ -247,7 +259,9 @@ where
247259 lsps1_client : Option < LSPS1Client > ,
248260 lsps2_client : Option < LSPS2Client > ,
249261 lsps2_service : Option < LSPS2Service > ,
262+ wallet : Arc < Wallet > ,
250263 channel_manager : Arc < ChannelManager > ,
264+ peer_manager : RwLock < Option < Arc < PeerManager > > > ,
251265 keys_manager : Arc < KeysManager > ,
252266 liquidity_manager : Arc < LiquidityManager > ,
253267 config : Arc < Config > ,
@@ -259,6 +273,7 @@ where
259273 L :: Target : LdkLogger ,
260274{
261275 pub ( crate ) fn set_peer_manager ( & self , peer_manager : Arc < PeerManager > ) {
276+ * self . peer_manager . write ( ) . unwrap ( ) = Some ( Arc :: clone ( & peer_manager) ) ;
262277 let process_msgs_callback = move || peer_manager. process_events ( ) ;
263278 self . liquidity_manager . set_process_msgs_callback ( process_msgs_callback) ;
264279 }
@@ -446,6 +461,254 @@ where
446461 log_error ! ( self . logger, "Received unexpected LSPS1Client::OrderStatus event!" ) ;
447462 }
448463 } ,
464+ Event :: LSPS2Service ( LSPS2ServiceEvent :: GetInfo {
465+ request_id,
466+ counterparty_node_id,
467+ token,
468+ } ) => {
469+ if let Some ( lsps2_service_handler) =
470+ self . liquidity_manager . lsps2_service_handler ( ) . as_ref ( )
471+ {
472+ let service_config = if let Some ( service_config) =
473+ self . lsps2_service . as_ref ( ) . map ( |s| s. service_config . clone ( ) )
474+ {
475+ service_config
476+ } else {
477+ log_error ! ( self . logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured." , ) ;
478+ return ;
479+ } ;
480+
481+ if let Some ( required) = service_config. require_token {
482+ if token != Some ( required) {
483+ log_error ! (
484+ self . logger,
485+ "Rejecting LSPS2 request {:?} from counterparty {} as the client provided an invalid token." ,
486+ request_id,
487+ counterparty_node_id
488+ ) ;
489+ lsps2_service_handler. invalid_token_provided ( & counterparty_node_id, request_id. clone ( ) ) . unwrap_or_else ( |e| {
490+ debug_assert ! ( false , "Failed to reject LSPS2 request. This should never happen." ) ;
491+ log_error ! (
492+ self . logger,
493+ "Failed to reject LSPS2 request {:?} from counterparty {} due to: {:?}. This should never happen." ,
494+ request_id,
495+ counterparty_node_id,
496+ e
497+ ) ;
498+ } ) ;
499+ return ;
500+ }
501+ }
502+
503+ let mut valid_until: DateTime < Utc > = Utc :: now ( ) ;
504+ valid_until += LSPS2_GETINFO_REQUEST_EXPIRY ;
505+
506+ let opening_fee_params = RawOpeningFeeParams {
507+ min_fee_msat : service_config. min_channel_opening_fee_msat ,
508+ proportional : service_config. channel_opening_fee_ppm ,
509+ valid_until,
510+ min_lifetime : service_config. min_channel_lifetime ,
511+ max_client_to_self_delay : service_config. max_client_to_self_delay ,
512+ min_payment_size_msat : service_config. min_payment_size_msat ,
513+ max_payment_size_msat : service_config. max_payment_size_msat ,
514+ } ;
515+
516+ let opening_fee_params_menu = vec ! [ opening_fee_params] ;
517+
518+ if let Err ( e) = lsps2_service_handler. opening_fee_params_generated (
519+ & counterparty_node_id,
520+ request_id,
521+ opening_fee_params_menu,
522+ ) {
523+ log_error ! (
524+ self . logger,
525+ "Failed to handle generated opening fee params: {:?}" ,
526+ e
527+ ) ;
528+ }
529+ } else {
530+ log_error ! ( self . logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured." , ) ;
531+ return ;
532+ }
533+ } ,
534+ Event :: LSPS2Service ( LSPS2ServiceEvent :: BuyRequest {
535+ request_id,
536+ counterparty_node_id,
537+ opening_fee_params : _,
538+ payment_size_msat,
539+ } ) => {
540+ if let Some ( lsps2_service_handler) =
541+ self . liquidity_manager . lsps2_service_handler ( ) . as_ref ( )
542+ {
543+ let service_config = if let Some ( service_config) =
544+ self . lsps2_service . as_ref ( ) . map ( |s| s. service_config . clone ( ) )
545+ {
546+ service_config
547+ } else {
548+ log_error ! ( self . logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured." , ) ;
549+ return ;
550+ } ;
551+
552+ let user_channel_id: u128 = rand:: thread_rng ( ) . gen :: < u128 > ( ) ;
553+ let intercept_scid = self . channel_manager . get_intercept_scid ( ) ;
554+
555+ if let Some ( payment_size_msat) = payment_size_msat {
556+ // We already check this in `lightning-liquidity`, but better safe than
557+ // sorry.
558+ //
559+ // TODO: We might want to eventually send back an error here, but we
560+ // currently can't and have to trust `lightning-liquidity` is doing the
561+ // right thing.
562+ //
563+ // TODO: Eventually we also might want to make sure that we have sufficient
564+ // liquidity for the channel opening here.
565+ if payment_size_msat > service_config. max_payment_size_msat
566+ || payment_size_msat < service_config. min_payment_size_msat
567+ {
568+ log_error ! (
569+ self . logger,
570+ "Rejecting to handle LSPS2 buy request {:?} from counterparty {} as the client requested an invalid payment size." ,
571+ request_id,
572+ counterparty_node_id
573+ ) ;
574+ return ;
575+ }
576+ }
577+
578+ match lsps2_service_handler. invoice_parameters_generated (
579+ & counterparty_node_id,
580+ request_id,
581+ intercept_scid,
582+ LSPS2_CHANNEL_CLTV_EXPIRY_DELTA ,
583+ LSPS2_CLIENT_TRUSTS_LSP_MODE ,
584+ user_channel_id,
585+ ) {
586+ Ok ( ( ) ) => { } ,
587+ Err ( e) => {
588+ log_error ! (
589+ self . logger,
590+ "Failed to provide invoice parameters: {:?}" ,
591+ e
592+ ) ;
593+ return ;
594+ } ,
595+ }
596+ } else {
597+ log_error ! ( self . logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured." , ) ;
598+ return ;
599+ }
600+ } ,
601+ Event :: LSPS2Service ( LSPS2ServiceEvent :: OpenChannel {
602+ their_network_key,
603+ amt_to_forward_msat,
604+ opening_fee_msat : _,
605+ user_channel_id,
606+ intercept_scid : _,
607+ } ) => {
608+ if self . liquidity_manager . lsps2_service_handler ( ) . is_none ( ) {
609+ log_error ! ( self . logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured." , ) ;
610+ return ;
611+ } ;
612+
613+ let service_config = if let Some ( service_config) =
614+ self . lsps2_service . as_ref ( ) . map ( |s| s. service_config . clone ( ) )
615+ {
616+ service_config
617+ } else {
618+ log_error ! ( self . logger, "Failed to handle LSPS2ServiceEvent as LSPS2 liquidity service was not configured." , ) ;
619+ return ;
620+ } ;
621+
622+ let init_features = if let Some ( peer_manager) =
623+ self . peer_manager . read ( ) . unwrap ( ) . as_ref ( )
624+ {
625+ // Fail if we're not connected to the prospective channel partner.
626+ if let Some ( peer) = peer_manager. peer_by_node_id ( & their_network_key) {
627+ peer. init_features
628+ } else {
629+ // TODO: We just silently fail here. Eventually we will need to remember
630+ // the pending requests and regularly retry opening the channel until we
631+ // succeed.
632+ log_error ! (
633+ self . logger,
634+ "Failed to open LSPS2 channel to {} due to peer not being not connected." ,
635+ their_network_key,
636+ ) ;
637+ return ;
638+ }
639+ } else {
640+ debug_assert ! ( false , "Failed to handle LSPS2ServiceEvent as peer manager isn't available. This should never happen." , ) ;
641+ log_error ! ( self . logger, "Failed to handle LSPS2ServiceEvent as peer manager isn't available. This should never happen." , ) ;
642+ return ;
643+ } ;
644+
645+ // Fail if we have insufficient onchain funds available.
646+ let over_provisioning_msat = ( amt_to_forward_msat
647+ * service_config. channel_over_provisioning_ppm as u64 )
648+ / 1_000_000 ;
649+ let channel_amount_sats = ( amt_to_forward_msat + over_provisioning_msat) / 1000 ;
650+ let cur_anchor_reserve_sats =
651+ total_anchor_channels_reserve_sats ( & self . channel_manager , & self . config ) ;
652+ let spendable_amount_sats =
653+ self . wallet . get_spendable_amount_sats ( cur_anchor_reserve_sats) . unwrap_or ( 0 ) ;
654+ let required_funds_sats = channel_amount_sats
655+ + self . config . anchor_channels_config . as_ref ( ) . map_or ( 0 , |c| {
656+ if init_features. requires_anchors_zero_fee_htlc_tx ( )
657+ && !c. trusted_peers_no_reserve . contains ( & their_network_key)
658+ {
659+ c. per_channel_reserve_sats
660+ } else {
661+ 0
662+ }
663+ } ) ;
664+ if spendable_amount_sats < required_funds_sats {
665+ log_error ! ( self . logger,
666+ "Unable to create channel due to insufficient funds. Available: {}sats, Required: {}sats" ,
667+ spendable_amount_sats, channel_amount_sats
668+ ) ;
669+ // TODO: We just silently fail here. Eventually we will need to remember
670+ // the pending requests and regularly retry opening the channel until we
671+ // succeed.
672+ return ;
673+ }
674+
675+ let mut config = * self . channel_manager . get_current_default_configuration ( ) ;
676+
677+ // Set the HTLC-value-in-flight to 100% of the channel value to ensure we can
678+ // forward the payment.
679+ config
680+ . channel_handshake_config
681+ . max_inbound_htlc_value_in_flight_percent_of_channel = 100 ;
682+
683+ // We set the forwarding fee to 0 for now as we're getting paid by the channel fee.
684+ //
685+ // TODO: revisit this decision eventually.
686+ config. channel_config . forwarding_fee_base_msat = 0 ;
687+ config. channel_config . forwarding_fee_proportional_millionths = 0 ;
688+
689+ match self . channel_manager . create_channel (
690+ their_network_key,
691+ channel_amount_sats,
692+ 0 ,
693+ user_channel_id,
694+ None ,
695+ Some ( config) ,
696+ ) {
697+ Ok ( _) => { } ,
698+ Err ( e) => {
699+ // TODO: We just silently fail here. Eventually we will need to remember
700+ // the pending requests and regularly retry opening the channel until we
701+ // succeed.
702+ log_error ! (
703+ self . logger,
704+ "Failed to open LSPS2 channel to {}: {:?}" ,
705+ their_network_key,
706+ e
707+ ) ;
708+ return ;
709+ } ,
710+ }
711+ } ,
449712 Event :: LSPS2Client ( LSPS2ClientEvent :: OpeningParametersReady {
450713 request_id,
451714 counterparty_node_id,
0 commit comments