@@ -27,93 +27,50 @@ use core::default::Default;
2727use core:: ops:: Deref ;
2828
2929use crate :: lsps2:: msgs:: {
30- BuyRequest , BuyResponse , GetInfoRequest , GetInfoResponse , InterceptScid , LSPS2Message ,
31- LSPS2Request , LSPS2Response , OpeningFeeParams ,
30+ BuyRequest , BuyResponse , GetInfoRequest , GetInfoResponse , LSPS2Message , LSPS2Request ,
31+ LSPS2Response , OpeningFeeParams ,
3232} ;
3333
3434/// Client-side configuration options for JIT channels.
3535#[ derive( Clone , Debug , Copy ) ]
36- pub struct LSPS2ClientConfig {
37- /// Trust the LSP to create a valid channel funding transaction and have it confirmed on-chain.
38- ///
39- /// TODO: If set to `false`, we'll only release the pre-image after we see an on-chain
40- /// confirmation of the channel's funding transaction.
41- ///
42- /// Defaults to `true`.
43- pub client_trusts_lsp : bool ,
44- }
36+ pub struct LSPS2ClientConfig { }
4537
4638impl Default for LSPS2ClientConfig {
4739 fn default ( ) -> Self {
48- Self { client_trusts_lsp : true }
49- }
50- }
51-
52- struct ChannelStateError ( String ) ;
53-
54- impl From < ChannelStateError > for LightningError {
55- fn from ( value : ChannelStateError ) -> Self {
56- LightningError { err : value. 0 , action : ErrorAction :: IgnoreAndLog ( Level :: Info ) }
57- }
58- }
59-
60- #[ derive( PartialEq , Debug ) ]
61- enum InboundJITChannelState {
62- BuyRequested ,
63- PendingPayment { client_trusts_lsp : bool , intercept_scid : InterceptScid } ,
64- }
65-
66- impl InboundJITChannelState {
67- fn invoice_params_received (
68- & self , client_trusts_lsp : bool , intercept_scid : InterceptScid ,
69- ) -> Result < Self , ChannelStateError > {
70- match self {
71- InboundJITChannelState :: BuyRequested { .. } => {
72- Ok ( InboundJITChannelState :: PendingPayment { client_trusts_lsp, intercept_scid } )
73- }
74- state => Err ( ChannelStateError ( format ! (
75- "Invoice params received when JIT Channel was in state: {:?}" ,
76- state
77- ) ) ) ,
78- }
40+ Self { }
7941 }
8042}
8143
8244struct InboundJITChannel {
83- state : InboundJITChannelState ,
84- user_channel_id : u128 ,
8545 payment_size_msat : Option < u64 > ,
8646}
8747
8848impl InboundJITChannel {
89- fn new ( user_channel_id : u128 , payment_size_msat : Option < u64 > ) -> Self {
90- Self { user_channel_id, payment_size_msat, state : InboundJITChannelState :: BuyRequested }
91- }
92-
93- fn invoice_params_received (
94- & mut self , client_trusts_lsp : bool , intercept_scid : InterceptScid ,
95- ) -> Result < ( ) , LightningError > {
96- self . state = self . state . invoice_params_received ( client_trusts_lsp, intercept_scid) ?;
97- Ok ( ( ) )
49+ fn new ( payment_size_msat : Option < u64 > ) -> Self {
50+ Self { payment_size_msat }
9851 }
9952}
10053
10154struct PeerState {
102- inbound_channels_by_id : HashMap < u128 , InboundJITChannel > ,
10355 pending_get_info_requests : HashSet < RequestId > ,
104- pending_buy_requests : HashMap < RequestId , u128 > ,
56+ pending_buy_requests : HashMap < RequestId , InboundJITChannel > ,
10557}
10658
10759impl PeerState {
10860 fn new ( ) -> Self {
109- let inbound_channels_by_id = HashMap :: new ( ) ;
11061 let pending_get_info_requests = HashSet :: new ( ) ;
11162 let pending_buy_requests = HashMap :: new ( ) ;
112- Self { inbound_channels_by_id , pending_get_info_requests, pending_buy_requests }
63+ Self { pending_get_info_requests, pending_buy_requests }
11364 }
11465}
11566
11667/// The main object allowing to send and receive LSPS2 messages.
68+ ///
69+ /// Note that currently only the 'client-trusts-LSP' trust model is supported, i.e., we don't
70+ /// provide any additional API guidance to allow withholding the preimage until the channel is
71+ /// opened. Please refer to the [`LSPS2 specification`] for more information.
72+ ///
73+ /// [`LSPS2 specification`]: https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS2#trust-models
11774pub struct LSPS2ClientHandler < ES : Deref >
11875where
11976 ES :: Target : EntropySource ,
12279 pending_messages : Arc < MessageQueue > ,
12380 pending_events : Arc < EventQueue > ,
12481 per_peer_state : RwLock < HashMap < PublicKey , Mutex < PeerState > > > ,
125- config : LSPS2ClientConfig ,
82+ _config : LSPS2ClientConfig ,
12683}
12784
12885impl < ES : Deref > LSPS2ClientHandler < ES >
@@ -132,14 +89,14 @@ where
13289 /// Constructs an `LSPS2ClientHandler`.
13390 pub ( crate ) fn new (
13491 entropy_source : ES , pending_messages : Arc < MessageQueue > , pending_events : Arc < EventQueue > ,
135- config : LSPS2ClientConfig ,
92+ _config : LSPS2ClientConfig ,
13693 ) -> Self {
13794 Self {
13895 entropy_source,
13996 pending_messages,
14097 pending_events,
14198 per_peer_state : RwLock :: new ( HashMap :: new ( ) ) ,
142- config ,
99+ _config ,
143100 }
144101 }
145102
@@ -155,8 +112,12 @@ where
155112 /// `token` is an optional `String` that will be provided to the LSP.
156113 /// It can be used by the LSP as an API key, coupon code, or some other way to identify a user.
157114 ///
115+ /// Returns the used [`RequestId`], which will be returned via [`OpeningParametersReady`].
116+ ///
158117 /// [`OpeningParametersReady`]: crate::lsps2::event::LSPS2ClientEvent::OpeningParametersReady
159- pub fn request_opening_params ( & self , counterparty_node_id : PublicKey , token : Option < String > ) {
118+ pub fn request_opening_params (
119+ & self , counterparty_node_id : PublicKey , token : Option < String > ,
120+ ) -> RequestId {
160121 let request_id = crate :: utils:: generate_request_id ( & self . entropy_source ) ;
161122
162123 {
@@ -170,9 +131,14 @@ where
170131
171132 self . pending_messages . enqueue (
172133 & counterparty_node_id,
173- LSPS2Message :: Request ( request_id, LSPS2Request :: GetInfo ( GetInfoRequest { token } ) )
174- . into ( ) ,
134+ LSPS2Message :: Request (
135+ request_id. clone ( ) ,
136+ LSPS2Request :: GetInfo ( GetInfoRequest { token } ) ,
137+ )
138+ . into ( ) ,
175139 ) ;
140+
141+ request_id
176142 }
177143
178144 /// Confirms a set of chosen channel opening parameters to use for the JIT channel and
@@ -182,9 +148,6 @@ where
182148 ///
183149 /// The user will receive the LSP's response via an [`InvoiceParametersReady`] event.
184150 ///
185- /// The user needs to provide a locally unique `user_channel_id` which will be used for
186- /// tracking the channel state.
187- ///
188151 /// If `payment_size_msat` is [`Option::Some`] then the invoice will be for a fixed amount
189152 /// and MPP can be used to pay it.
190153 ///
@@ -197,36 +160,33 @@ where
197160 /// [`OpeningParametersReady`]: crate::lsps2::event::LSPS2ClientEvent::OpeningParametersReady
198161 /// [`InvoiceParametersReady`]: crate::lsps2::event::LSPS2ClientEvent::InvoiceParametersReady
199162 pub fn select_opening_params (
200- & self , counterparty_node_id : PublicKey , user_channel_id : u128 ,
201- payment_size_msat : Option < u64 > , opening_fee_params : OpeningFeeParams ,
202- ) -> Result < ( ) , APIError > {
163+ & self , counterparty_node_id : PublicKey , payment_size_msat : Option < u64 > ,
164+ opening_fee_params : OpeningFeeParams ,
165+ ) -> Result < RequestId , APIError > {
203166 let mut outer_state_lock = self . per_peer_state . write ( ) . unwrap ( ) ;
204167 let inner_state_lock =
205168 outer_state_lock. entry ( counterparty_node_id) . or_insert ( Mutex :: new ( PeerState :: new ( ) ) ) ;
206169 let mut peer_state_lock = inner_state_lock. lock ( ) . unwrap ( ) ;
207170
208- let jit_channel = InboundJITChannel :: new ( user_channel_id, payment_size_msat) ;
209- if peer_state_lock. inbound_channels_by_id . insert ( user_channel_id, jit_channel) . is_some ( ) {
171+ let request_id = crate :: utils:: generate_request_id ( & self . entropy_source ) ;
172+
173+ let jit_channel = InboundJITChannel :: new ( payment_size_msat) ;
174+ if peer_state_lock. pending_buy_requests . insert ( request_id. clone ( ) , jit_channel) . is_some ( ) {
210175 return Err ( APIError :: APIMisuseError {
211- err : format ! (
212- "Failed due to duplicate user_channel_id. Please ensure its uniqueness!"
213- ) ,
176+ err : format ! ( "Failed due to duplicate request_id. This should never happen!" ) ,
214177 } ) ;
215178 }
216179
217- let request_id = crate :: utils:: generate_request_id ( & self . entropy_source ) ;
218- peer_state_lock. pending_buy_requests . insert ( request_id. clone ( ) , user_channel_id) ;
219-
220180 self . pending_messages . enqueue (
221181 & counterparty_node_id,
222182 LSPS2Message :: Request (
223- request_id,
183+ request_id. clone ( ) ,
224184 LSPS2Request :: Buy ( BuyRequest { opening_fee_params, payment_size_msat } ) ,
225185 )
226186 . into ( ) ,
227187 ) ;
228188
229- Ok ( ( ) )
189+ Ok ( request_id )
230190 }
231191
232192 fn handle_get_info_response (
@@ -249,6 +209,7 @@ where
249209
250210 self . pending_events . enqueue ( Event :: LSPS2Client (
251211 LSPS2ClientEvent :: OpeningParametersReady {
212+ request_id,
252213 counterparty_node_id : * counterparty_node_id,
253214 opening_fee_params_menu : result. opening_fee_params_menu ,
254215 min_payment_size_msat : result. min_payment_size_msat ,
@@ -304,7 +265,7 @@ where
304265 Some ( inner_state_lock) => {
305266 let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
306267
307- let user_channel_id =
268+ let jit_channel =
308269 peer_state. pending_buy_requests . remove ( & request_id) . ok_or ( LightningError {
309270 err : format ! (
310271 "Received buy response for an unknown request: {:?}" ,
@@ -313,45 +274,14 @@ where
313274 action : ErrorAction :: IgnoreAndLog ( Level :: Info ) ,
314275 } ) ?;
315276
316- let jit_channel = peer_state
317- . inbound_channels_by_id
318- . get_mut ( & user_channel_id)
319- . ok_or ( LightningError {
320- err : format ! (
321- "Received buy response for an unknown channel: {:?}" ,
322- user_channel_id
323- ) ,
324- action : ErrorAction :: IgnoreAndLog ( Level :: Info ) ,
325- } ) ?;
326-
327- // Reject the buy response if we disallow client_trusts_lsp and the LSP requires
328- // it.
329- if !self . config . client_trusts_lsp && result. client_trusts_lsp {
330- peer_state. inbound_channels_by_id . remove ( & user_channel_id) ;
331- return Err ( LightningError {
332- err : format ! (
333- "Aborting JIT channel flow as the LSP requires 'client_trusts_lsp' mode, which we disallow"
334- ) ,
335- action : ErrorAction :: IgnoreAndLog ( Level :: Info ) ,
336- } ) ;
337- }
338-
339- if let Err ( e) = jit_channel. invoice_params_received (
340- result. client_trusts_lsp ,
341- result. intercept_scid . clone ( ) ,
342- ) {
343- peer_state. inbound_channels_by_id . remove ( & user_channel_id) ;
344- return Err ( e) ;
345- }
346-
347277 if let Ok ( intercept_scid) = result. intercept_scid . to_scid ( ) {
348278 self . pending_events . enqueue ( Event :: LSPS2Client (
349279 LSPS2ClientEvent :: InvoiceParametersReady {
280+ request_id,
350281 counterparty_node_id : * counterparty_node_id,
351282 intercept_scid,
352283 cltv_expiry_delta : result. lsp_cltv_expiry_delta ,
353284 payment_size_msat : jit_channel. payment_size_msat ,
354- user_channel_id : jit_channel. user_channel_id ,
355285 } ,
356286 ) ) ;
357287 } else {
@@ -385,25 +315,15 @@ where
385315 Some ( inner_state_lock) => {
386316 let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
387317
388- let user_channel_id =
389- peer_state. pending_buy_requests . remove ( & request_id) . ok_or ( LightningError {
390- err : format ! ( "Received buy error for an unknown request: {:?}" , request_id) ,
391- action : ErrorAction :: IgnoreAndLog ( Level :: Info ) ,
392- } ) ?;
318+ peer_state. pending_buy_requests . remove ( & request_id) . ok_or ( LightningError {
319+ err : format ! ( "Received buy error for an unknown request: {:?}" , request_id) ,
320+ action : ErrorAction :: IgnoreAndLog ( Level :: Info ) ,
321+ } ) ?;
393322
394- peer_state. inbound_channels_by_id . remove ( & user_channel_id) . ok_or (
395- LightningError {
396- err : format ! (
397- "Received buy error for an unknown channel: {:?}" ,
398- user_channel_id
399- ) ,
400- action : ErrorAction :: IgnoreAndLog ( Level :: Info ) ,
401- } ,
402- ) ?;
403323 Ok ( ( ) )
404324 }
405325 None => {
406- return Err ( LightningError { err : format ! ( "Received error response for a buy request from an unknown counterparty ({:?})" , counterparty_node_id) , action : ErrorAction :: IgnoreAndLog ( Level :: Info ) } ) ;
326+ return Err ( LightningError { err : format ! ( "Received error response for a buy request from an unknown counterparty ({:?})" , counterparty_node_id) , action : ErrorAction :: IgnoreAndLog ( Level :: Info ) } ) ;
407327 }
408328 }
409329 }
0 commit comments