1use super::event::LSPS1ClientEvent;
13use super::msgs::{
14 LSPS1CreateOrderRequest, LSPS1CreateOrderResponse, LSPS1GetInfoRequest, LSPS1GetInfoResponse,
15 LSPS1GetOrderRequest, LSPS1Message, LSPS1OrderId, LSPS1OrderParams, LSPS1Request,
16 LSPS1Response,
17};
18use crate::message_queue::MessageQueue;
19
20use crate::events::EventQueue;
21use crate::lsps0::ser::{LSPSProtocolMessageHandler, LSPSRequestId, LSPSResponseError};
22use crate::prelude::{new_hash_map, HashMap, HashSet};
23use crate::sync::{Arc, Mutex, RwLock};
24
25use lightning::ln::msgs::{ErrorAction, LightningError};
26use lightning::sign::EntropySource;
27use lightning::util::logger::Level;
28use lightning::util::persist::KVStore;
29
30use bitcoin::secp256k1::PublicKey;
31use bitcoin::Address;
32
33use core::ops::Deref;
34
35#[derive(Clone, Debug)]
37pub struct LSPS1ClientConfig {
38 pub max_channel_fees_msat: Option<u64>,
40}
41
42#[derive(Default)]
43struct PeerState {
44 pending_get_info_requests: HashSet<LSPSRequestId>,
45 pending_create_order_requests: HashSet<LSPSRequestId>,
46 pending_get_order_requests: HashSet<LSPSRequestId>,
47}
48
49pub struct LSPS1ClientHandler<ES: Deref, K: Deref + Clone>
51where
52 ES::Target: EntropySource,
53 K::Target: KVStore,
54{
55 entropy_source: ES,
56 pending_messages: Arc<MessageQueue>,
57 pending_events: Arc<EventQueue<K>>,
58 per_peer_state: RwLock<HashMap<PublicKey, Mutex<PeerState>>>,
59 config: LSPS1ClientConfig,
60}
61
62impl<ES: Deref, K: Deref + Clone> LSPS1ClientHandler<ES, K>
63where
64 ES::Target: EntropySource,
65 K::Target: KVStore,
66{
67 pub(crate) fn new(
69 entropy_source: ES, pending_messages: Arc<MessageQueue>,
70 pending_events: Arc<EventQueue<K>>, config: LSPS1ClientConfig,
71 ) -> Self {
72 Self {
73 entropy_source,
74 pending_messages,
75 pending_events,
76 per_peer_state: RwLock::new(new_hash_map()),
77 config,
78 }
79 }
80
81 pub fn config(&self) -> &LSPS1ClientConfig {
83 &self.config
84 }
85
86 pub fn request_supported_options(&self, counterparty_node_id: PublicKey) -> LSPSRequestId {
96 let mut message_queue_notifier = self.pending_messages.notifier();
97
98 let request_id = crate::utils::generate_request_id(&self.entropy_source);
99 {
100 let mut outer_state_lock = self.per_peer_state.write().unwrap();
101 let inner_state_lock = outer_state_lock
102 .entry(counterparty_node_id)
103 .or_insert(Mutex::new(PeerState::default()));
104 let mut peer_state_lock = inner_state_lock.lock().unwrap();
105 peer_state_lock.pending_get_info_requests.insert(request_id.clone());
106 }
107
108 let request = LSPS1Request::GetInfo(LSPS1GetInfoRequest {});
109 let msg = LSPS1Message::Request(request_id.clone(), request).into();
110 message_queue_notifier.enqueue(&counterparty_node_id, msg);
111 request_id
112 }
113
114 fn handle_get_info_response(
115 &self, request_id: LSPSRequestId, counterparty_node_id: &PublicKey,
116 result: LSPS1GetInfoResponse,
117 ) -> Result<(), LightningError> {
118 let event_queue_notifier = self.pending_events.notifier();
119
120 let outer_state_lock = self.per_peer_state.write().unwrap();
121 match outer_state_lock.get(counterparty_node_id) {
122 Some(inner_state_lock) => {
123 let mut peer_state_lock = inner_state_lock.lock().unwrap();
124
125 if !peer_state_lock.pending_get_info_requests.remove(&request_id) {
126 return Err(LightningError {
127 err: format!(
128 "Received get_info response for an unknown request: {:?}",
129 request_id
130 ),
131 action: ErrorAction::IgnoreAndLog(Level::Debug),
132 });
133 }
134
135 event_queue_notifier.enqueue(LSPS1ClientEvent::SupportedOptionsReady {
136 counterparty_node_id: *counterparty_node_id,
137 supported_options: result.options,
138 request_id,
139 });
140 Ok(())
141 },
142 None => Err(LightningError {
143 err: format!(
144 "Received get_info response from unknown peer: {}",
145 counterparty_node_id
146 ),
147 action: ErrorAction::IgnoreAndLog(Level::Debug),
148 }),
149 }
150 }
151
152 fn handle_get_info_error(
153 &self, request_id: LSPSRequestId, counterparty_node_id: &PublicKey,
154 error: LSPSResponseError,
155 ) -> Result<(), LightningError> {
156 let event_queue_notifier = self.pending_events.notifier();
157
158 let outer_state_lock = self.per_peer_state.read().unwrap();
159 match outer_state_lock.get(counterparty_node_id) {
160 Some(inner_state_lock) => {
161 let mut peer_state_lock = inner_state_lock.lock().unwrap();
162
163 if !peer_state_lock.pending_get_info_requests.remove(&request_id) {
164 return Err(LightningError {
165 err: format!(
166 "Received get_info error for an unknown request: {:?}",
167 request_id
168 ),
169 action: ErrorAction::IgnoreAndLog(Level::Debug),
170 });
171 }
172
173 event_queue_notifier.enqueue(LSPS1ClientEvent::SupportedOptionsRequestFailed {
174 request_id: request_id.clone(),
175 counterparty_node_id: *counterparty_node_id,
176 error: error.clone(),
177 });
178
179 Err(LightningError {
180 err: format!(
181 "Received get_info error response for request {:?}: {:?}",
182 request_id, error
183 ),
184 action: ErrorAction::IgnoreAndLog(Level::Error),
185 })
186 },
187 None => {
188 return Err(LightningError {
189 err: format!(
190 "Received get_info error response from an unknown counterparty {}",
191 counterparty_node_id
192 ),
193 action: ErrorAction::IgnoreAndLog(Level::Debug),
194 });
195 },
196 }
197 }
198
199 pub fn create_order(
203 &self, counterparty_node_id: &PublicKey, order: LSPS1OrderParams,
204 refund_onchain_address: Option<Address>,
205 ) -> LSPSRequestId {
206 let mut message_queue_notifier = self.pending_messages.notifier();
207
208 let mut outer_state_lock = self.per_peer_state.write().unwrap();
209 let inner_state_lock = outer_state_lock
210 .entry(*counterparty_node_id)
211 .or_insert(Mutex::new(PeerState::default()));
212 let mut peer_state_lock = inner_state_lock.lock().unwrap();
213
214 let request_id = crate::utils::generate_request_id(&self.entropy_source);
215 let request =
216 LSPS1Request::CreateOrder(LSPS1CreateOrderRequest { order, refund_onchain_address });
217 let msg = LSPS1Message::Request(request_id.clone(), request).into();
218 peer_state_lock.pending_create_order_requests.insert(request_id.clone());
219
220 message_queue_notifier.enqueue(&counterparty_node_id, msg);
221
222 request_id
223 }
224
225 fn handle_create_order_response(
226 &self, request_id: LSPSRequestId, counterparty_node_id: &PublicKey,
227 response: LSPS1CreateOrderResponse,
228 ) -> Result<(), LightningError> {
229 let event_queue_notifier = self.pending_events.notifier();
230
231 let outer_state_lock = self.per_peer_state.read().unwrap();
232 match outer_state_lock.get(counterparty_node_id) {
233 Some(inner_state_lock) => {
234 let mut peer_state_lock = inner_state_lock.lock().unwrap();
235
236 if !peer_state_lock.pending_create_order_requests.remove(&request_id) {
237 return Err(LightningError {
238 err: format!(
239 "Received create_order response for an unknown request: {:?}",
240 request_id
241 ),
242 action: ErrorAction::IgnoreAndLog(Level::Debug),
243 });
244 }
245
246 event_queue_notifier.enqueue(LSPS1ClientEvent::OrderCreated {
247 request_id,
248 counterparty_node_id: *counterparty_node_id,
249 order_id: response.order_id,
250 order: response.order,
251 payment: response.payment,
252 channel: response.channel,
253 });
254 },
255 None => {
256 return Err(LightningError {
257 err: format!(
258 "Received create_order response from unknown peer: {}",
259 counterparty_node_id
260 ),
261 action: ErrorAction::IgnoreAndLog(Level::Debug),
262 })
263 },
264 }
265
266 Ok(())
267 }
268
269 fn handle_create_order_error(
270 &self, request_id: LSPSRequestId, counterparty_node_id: &PublicKey,
271 error: LSPSResponseError,
272 ) -> Result<(), LightningError> {
273 let event_queue_notifier = self.pending_events.notifier();
274
275 let outer_state_lock = self.per_peer_state.read().unwrap();
276 match outer_state_lock.get(counterparty_node_id) {
277 Some(inner_state_lock) => {
278 let mut peer_state_lock = inner_state_lock.lock().unwrap();
279
280 if !peer_state_lock.pending_create_order_requests.remove(&request_id) {
281 return Err(LightningError {
282 err: format!(
283 "Received create order error for an unknown request: {:?}",
284 request_id
285 ),
286 action: ErrorAction::IgnoreAndLog(Level::Debug),
287 });
288 }
289
290 event_queue_notifier.enqueue(LSPS1ClientEvent::OrderRequestFailed {
291 request_id: request_id.clone(),
292 counterparty_node_id: *counterparty_node_id,
293 error: error.clone(),
294 });
295
296 Err(LightningError {
297 err: format!(
298 "Received create_order error response for request {:?}: {:?}",
299 request_id, error
300 ),
301 action: ErrorAction::IgnoreAndLog(Level::Error),
302 })
303 },
304 None => {
305 return Err(LightningError {
306 err: format!(
307 "Received error response for a create order request from an unknown counterparty {}",
308 counterparty_node_id
309 ),
310 action: ErrorAction::IgnoreAndLog(Level::Debug),
311 });
312 },
313 }
314 }
315
316 pub fn check_order_status(
322 &self, counterparty_node_id: &PublicKey, order_id: LSPS1OrderId,
323 ) -> LSPSRequestId {
324 let mut message_queue_notifier = self.pending_messages.notifier();
325
326 let mut outer_state_lock = self.per_peer_state.write().unwrap();
327 let inner_state_lock = outer_state_lock
328 .entry(*counterparty_node_id)
329 .or_insert(Mutex::new(PeerState::default()));
330 let mut peer_state_lock = inner_state_lock.lock().unwrap();
331
332 let request_id = crate::utils::generate_request_id(&self.entropy_source);
333 peer_state_lock.pending_get_order_requests.insert(request_id.clone());
334
335 let request = LSPS1Request::GetOrder(LSPS1GetOrderRequest { order_id: order_id.clone() });
336 let msg = LSPS1Message::Request(request_id.clone(), request).into();
337
338 message_queue_notifier.enqueue(&counterparty_node_id, msg);
339
340 request_id
341 }
342
343 fn handle_get_order_response(
344 &self, request_id: LSPSRequestId, counterparty_node_id: &PublicKey,
345 response: LSPS1CreateOrderResponse,
346 ) -> Result<(), LightningError> {
347 let event_queue_notifier = self.pending_events.notifier();
348
349 let outer_state_lock = self.per_peer_state.read().unwrap();
350 match outer_state_lock.get(counterparty_node_id) {
351 Some(inner_state_lock) => {
352 let mut peer_state_lock = inner_state_lock.lock().unwrap();
353
354 if !peer_state_lock.pending_get_order_requests.remove(&request_id) {
355 return Err(LightningError {
356 err: format!(
357 "Received get_order response for an unknown request: {:?}",
358 request_id
359 ),
360 action: ErrorAction::IgnoreAndLog(Level::Debug),
361 });
362 }
363
364 event_queue_notifier.enqueue(LSPS1ClientEvent::OrderStatus {
365 request_id,
366 counterparty_node_id: *counterparty_node_id,
367 order_id: response.order_id,
368 order: response.order,
369 payment: response.payment,
370 channel: response.channel,
371 });
372 },
373 None => {
374 return Err(LightningError {
375 err: format!(
376 "Received get_order response from unknown peer: {}",
377 counterparty_node_id
378 ),
379 action: ErrorAction::IgnoreAndLog(Level::Debug),
380 })
381 },
382 }
383
384 Ok(())
385 }
386
387 fn handle_get_order_error(
388 &self, request_id: LSPSRequestId, counterparty_node_id: &PublicKey,
389 error: LSPSResponseError,
390 ) -> Result<(), LightningError> {
391 let event_queue_notifier = self.pending_events.notifier();
392
393 let outer_state_lock = self.per_peer_state.read().unwrap();
394 match outer_state_lock.get(counterparty_node_id) {
395 Some(inner_state_lock) => {
396 let mut peer_state_lock = inner_state_lock.lock().unwrap();
397
398 if !peer_state_lock.pending_get_order_requests.remove(&request_id) {
399 return Err(LightningError {
400 err: format!(
401 "Received get order error for an unknown request: {:?}",
402 request_id
403 ),
404 action: ErrorAction::IgnoreAndLog(Level::Debug),
405 });
406 }
407
408 event_queue_notifier.enqueue(LSPS1ClientEvent::OrderRequestFailed {
409 request_id: request_id.clone(),
410 counterparty_node_id: *counterparty_node_id,
411 error: error.clone(),
412 });
413
414 Err(LightningError {
415 err: format!(
416 "Received get_order error response for request {:?}: {:?}",
417 request_id, error
418 ),
419 action: ErrorAction::IgnoreAndLog(Level::Error),
420 })
421 },
422 None => {
423 return Err(LightningError {
424 err: format!(
425 "Received error response for a get order request from an unknown counterparty ({:?})",
426 counterparty_node_id
427 ),
428 action: ErrorAction::IgnoreAndLog(Level::Debug),
429 });
430 },
431 }
432 }
433}
434
435impl<ES: Deref, K: Deref + Clone> LSPSProtocolMessageHandler for LSPS1ClientHandler<ES, K>
436where
437 ES::Target: EntropySource,
438 K::Target: KVStore,
439{
440 type ProtocolMessage = LSPS1Message;
441 const PROTOCOL_NUMBER: Option<u16> = Some(1);
442
443 fn handle_message(
444 &self, message: Self::ProtocolMessage, counterparty_node_id: &PublicKey,
445 ) -> Result<(), LightningError> {
446 match message {
447 LSPS1Message::Response(request_id, response) => match response {
448 LSPS1Response::GetInfo(params) => {
449 self.handle_get_info_response(request_id, counterparty_node_id, params)
450 },
451 LSPS1Response::GetInfoError(error) => {
452 self.handle_get_info_error(request_id, counterparty_node_id, error)
453 },
454 LSPS1Response::CreateOrder(params) => {
455 self.handle_create_order_response(request_id, counterparty_node_id, params)
456 },
457 LSPS1Response::CreateOrderError(error) => {
458 self.handle_create_order_error(request_id, counterparty_node_id, error)
459 },
460 LSPS1Response::GetOrder(params) => {
461 self.handle_get_order_response(request_id, counterparty_node_id, params)
462 },
463 LSPS1Response::GetOrderError(error) => {
464 self.handle_get_order_error(request_id, counterparty_node_id, error)
465 },
466 },
467 _ => {
468 debug_assert!(
469 false,
470 "Client handler received LSPS1 request message. This should never happen."
471 );
472 Err(LightningError {
473 err: format!(
474 "Client handler received LSPS1 request message from node {:?}. This should never happen.",
475 counterparty_node_id
476 ),
477 action: ErrorAction::IgnoreAndLog(Level::Error),
478 })
479 },
480 }
481 }
482}