lightning_liquidity/lsps0/
service.rs

1// This file is Copyright its original authors, visible in version control
2// history.
3//
4// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7// You may not use this file except in accordance with one or both of these
8// licenses.
9
10//! Contains the main LSPS0 server-side object, [`LSPS0ServiceHandler`].
11//!
12//! Please refer to the [LSPS0
13//! specifcation](https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS0) for more
14//! information.
15
16use crate::lsps0::msgs::{LSPS0Message, LSPS0Request, LSPS0Response, ListProtocolsResponse};
17use crate::lsps0::ser::{ProtocolMessageHandler, RequestId};
18use crate::message_queue::MessageQueue;
19use crate::prelude::Vec;
20use crate::sync::Arc;
21
22use lightning::ln::msgs::{ErrorAction, LightningError};
23use lightning::util::logger::Level;
24
25use bitcoin::secp256k1::PublicKey;
26
27/// The main server-side object allowing to send and receive LSPS0 messages.
28pub struct LSPS0ServiceHandler {
29	pending_messages: Arc<MessageQueue>,
30	protocols: Vec<u16>,
31}
32
33impl LSPS0ServiceHandler {
34	/// Returns a new instance of [`LSPS0ServiceHandler`].
35	pub(crate) fn new(protocols: Vec<u16>, pending_messages: Arc<MessageQueue>) -> Self {
36		Self { protocols, pending_messages }
37	}
38
39	fn handle_request(
40		&self, request_id: RequestId, request: LSPS0Request, counterparty_node_id: &PublicKey,
41	) -> Result<(), lightning::ln::msgs::LightningError> {
42		match request {
43			LSPS0Request::ListProtocols(_) => {
44				let msg = LSPS0Message::Response(
45					request_id,
46					LSPS0Response::ListProtocols(ListProtocolsResponse {
47						protocols: self.protocols.clone(),
48					}),
49				);
50				self.pending_messages.enqueue(counterparty_node_id, msg.into());
51				Ok(())
52			},
53		}
54	}
55}
56
57impl ProtocolMessageHandler for LSPS0ServiceHandler {
58	type ProtocolMessage = LSPS0Message;
59	const PROTOCOL_NUMBER: Option<u16> = None;
60
61	fn handle_message(
62		&self, message: Self::ProtocolMessage, counterparty_node_id: &PublicKey,
63	) -> Result<(), LightningError> {
64		match message {
65			LSPS0Message::Request(request_id, request) => {
66				self.handle_request(request_id, request, counterparty_node_id)
67			},
68			LSPS0Message::Response(..) => {
69				debug_assert!(
70					false,
71					"Service handler received LSPS0 response message. This should never happen."
72				);
73				Err(LightningError { err: format!("Service handler received LSPS0 response message from node {:?}. This should never happen.", counterparty_node_id), action: ErrorAction::IgnoreAndLog(Level::Info)})
74			},
75		}
76	}
77}
78
79#[cfg(test)]
80mod tests {
81
82	use crate::lsps0::msgs::ListProtocolsRequest;
83	use crate::lsps0::ser::LSPSMessage;
84	use crate::tests::utils;
85	use alloc::string::ToString;
86	use alloc::sync::Arc;
87
88	use super::*;
89
90	#[test]
91	fn test_handle_list_protocols_request() {
92		let protocols: Vec<u16> = vec![];
93		let pending_messages = Arc::new(MessageQueue::new());
94
95		let lsps0_handler = Arc::new(LSPS0ServiceHandler::new(protocols, pending_messages.clone()));
96
97		let list_protocols_request = LSPS0Message::Request(
98			RequestId("xyz123".to_string()),
99			LSPS0Request::ListProtocols(ListProtocolsRequest {}),
100		);
101		let counterparty_node_id = utils::parse_pubkey(
102			"027100442c3b79f606f80f322d98d499eefcb060599efc5d4ecb00209c2cb54190",
103		)
104		.unwrap();
105
106		lsps0_handler.handle_message(list_protocols_request, &counterparty_node_id).unwrap();
107		let pending_messages = pending_messages.get_and_clear_pending_msgs();
108
109		assert_eq!(pending_messages.len(), 1);
110
111		let (pubkey, message) = &pending_messages[0];
112
113		assert_eq!(*pubkey, counterparty_node_id);
114		assert_eq!(
115			*message,
116			LSPSMessage::LSPS0(LSPS0Message::Response(
117				RequestId("xyz123".to_string()),
118				LSPS0Response::ListProtocols(ListProtocolsResponse { protocols: vec![] })
119			))
120		);
121	}
122}