@@ -27,93 +27,50 @@ use core::default::Default;
27
27
use core:: ops:: Deref ;
28
28
29
29
use crate :: lsps2:: msgs:: {
30
- BuyRequest , BuyResponse , GetInfoRequest , GetInfoResponse , InterceptScid , LSPS2Message ,
31
- LSPS2Request , LSPS2Response , OpeningFeeParams ,
30
+ BuyRequest , BuyResponse , GetInfoRequest , GetInfoResponse , LSPS2Message , LSPS2Request ,
31
+ LSPS2Response , OpeningFeeParams ,
32
32
} ;
33
33
34
34
/// Client-side configuration options for JIT channels.
35
35
#[ 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 { }
45
37
46
38
impl Default for LSPS2ClientConfig {
47
39
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 { }
79
41
}
80
42
}
81
43
82
44
struct InboundJITChannel {
83
- state : InboundJITChannelState ,
84
- user_channel_id : u128 ,
85
45
payment_size_msat : Option < u64 > ,
86
46
}
87
47
88
48
impl 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 }
98
51
}
99
52
}
100
53
101
54
struct PeerState {
102
- inbound_channels_by_id : HashMap < u128 , InboundJITChannel > ,
103
55
pending_get_info_requests : HashSet < RequestId > ,
104
- pending_buy_requests : HashMap < RequestId , u128 > ,
56
+ pending_buy_requests : HashMap < RequestId , InboundJITChannel > ,
105
57
}
106
58
107
59
impl PeerState {
108
60
fn new ( ) -> Self {
109
- let inbound_channels_by_id = HashMap :: new ( ) ;
110
61
let pending_get_info_requests = HashSet :: new ( ) ;
111
62
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 }
113
64
}
114
65
}
115
66
116
67
/// 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
117
74
pub struct LSPS2ClientHandler < ES : Deref >
118
75
where
119
76
ES :: Target : EntropySource ,
122
79
pending_messages : Arc < MessageQueue > ,
123
80
pending_events : Arc < EventQueue > ,
124
81
per_peer_state : RwLock < HashMap < PublicKey , Mutex < PeerState > > > ,
125
- config : LSPS2ClientConfig ,
82
+ _config : LSPS2ClientConfig ,
126
83
}
127
84
128
85
impl < ES : Deref > LSPS2ClientHandler < ES >
@@ -132,14 +89,14 @@ where
132
89
/// Constructs an `LSPS2ClientHandler`.
133
90
pub ( crate ) fn new (
134
91
entropy_source : ES , pending_messages : Arc < MessageQueue > , pending_events : Arc < EventQueue > ,
135
- config : LSPS2ClientConfig ,
92
+ _config : LSPS2ClientConfig ,
136
93
) -> Self {
137
94
Self {
138
95
entropy_source,
139
96
pending_messages,
140
97
pending_events,
141
98
per_peer_state : RwLock :: new ( HashMap :: new ( ) ) ,
142
- config ,
99
+ _config ,
143
100
}
144
101
}
145
102
@@ -155,8 +112,12 @@ where
155
112
/// `token` is an optional `String` that will be provided to the LSP.
156
113
/// It can be used by the LSP as an API key, coupon code, or some other way to identify a user.
157
114
///
115
+ /// Returns the used [`RequestId`], which will be returned via [`OpeningParametersReady`].
116
+ ///
158
117
/// [`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 {
160
121
let request_id = crate :: utils:: generate_request_id ( & self . entropy_source ) ;
161
122
162
123
{
@@ -170,9 +131,14 @@ where
170
131
171
132
self . pending_messages . enqueue (
172
133
& 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 ( ) ,
175
139
) ;
140
+
141
+ request_id
176
142
}
177
143
178
144
/// Confirms a set of chosen channel opening parameters to use for the JIT channel and
@@ -182,9 +148,6 @@ where
182
148
///
183
149
/// The user will receive the LSP's response via an [`InvoiceParametersReady`] event.
184
150
///
185
- /// The user needs to provide a locally unique `user_channel_id` which will be used for
186
- /// tracking the channel state.
187
- ///
188
151
/// If `payment_size_msat` is [`Option::Some`] then the invoice will be for a fixed amount
189
152
/// and MPP can be used to pay it.
190
153
///
@@ -197,36 +160,33 @@ where
197
160
/// [`OpeningParametersReady`]: crate::lsps2::event::LSPS2ClientEvent::OpeningParametersReady
198
161
/// [`InvoiceParametersReady`]: crate::lsps2::event::LSPS2ClientEvent::InvoiceParametersReady
199
162
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 > {
203
166
let mut outer_state_lock = self . per_peer_state . write ( ) . unwrap ( ) ;
204
167
let inner_state_lock =
205
168
outer_state_lock. entry ( counterparty_node_id) . or_insert ( Mutex :: new ( PeerState :: new ( ) ) ) ;
206
169
let mut peer_state_lock = inner_state_lock. lock ( ) . unwrap ( ) ;
207
170
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 ( ) {
210
175
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!" ) ,
214
177
} ) ;
215
178
}
216
179
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
-
220
180
self . pending_messages . enqueue (
221
181
& counterparty_node_id,
222
182
LSPS2Message :: Request (
223
- request_id,
183
+ request_id. clone ( ) ,
224
184
LSPS2Request :: Buy ( BuyRequest { opening_fee_params, payment_size_msat } ) ,
225
185
)
226
186
. into ( ) ,
227
187
) ;
228
188
229
- Ok ( ( ) )
189
+ Ok ( request_id )
230
190
}
231
191
232
192
fn handle_get_info_response (
@@ -249,6 +209,7 @@ where
249
209
250
210
self . pending_events . enqueue ( Event :: LSPS2Client (
251
211
LSPS2ClientEvent :: OpeningParametersReady {
212
+ request_id,
252
213
counterparty_node_id : * counterparty_node_id,
253
214
opening_fee_params_menu : result. opening_fee_params_menu ,
254
215
min_payment_size_msat : result. min_payment_size_msat ,
@@ -304,7 +265,7 @@ where
304
265
Some ( inner_state_lock) => {
305
266
let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
306
267
307
- let user_channel_id =
268
+ let jit_channel =
308
269
peer_state. pending_buy_requests . remove ( & request_id) . ok_or ( LightningError {
309
270
err : format ! (
310
271
"Received buy response for an unknown request: {:?}" ,
@@ -313,45 +274,14 @@ where
313
274
action : ErrorAction :: IgnoreAndLog ( Level :: Info ) ,
314
275
} ) ?;
315
276
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
-
347
277
if let Ok ( intercept_scid) = result. intercept_scid . to_scid ( ) {
348
278
self . pending_events . enqueue ( Event :: LSPS2Client (
349
279
LSPS2ClientEvent :: InvoiceParametersReady {
280
+ request_id,
350
281
counterparty_node_id : * counterparty_node_id,
351
282
intercept_scid,
352
283
cltv_expiry_delta : result. lsp_cltv_expiry_delta ,
353
284
payment_size_msat : jit_channel. payment_size_msat ,
354
- user_channel_id : jit_channel. user_channel_id ,
355
285
} ,
356
286
) ) ;
357
287
} else {
@@ -385,25 +315,15 @@ where
385
315
Some ( inner_state_lock) => {
386
316
let mut peer_state = inner_state_lock. lock ( ) . unwrap ( ) ;
387
317
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
+ } ) ?;
393
322
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
- ) ?;
403
323
Ok ( ( ) )
404
324
}
405
325
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 ) } ) ;
407
327
}
408
328
}
409
329
}
0 commit comments