lightning_liquidity/lsps0/
client.rs1use crate::events::EventQueue;
8use crate::lsps0::event::LSPS0ClientEvent;
9use crate::lsps0::msgs::{
10 LSPS0ListProtocolsRequest, LSPS0ListProtocolsResponse, LSPS0Message, LSPS0Request,
11 LSPS0Response,
12};
13use crate::lsps0::ser::{LSPSProtocolMessageHandler, LSPSResponseError};
14use crate::message_queue::MessageQueue;
15use crate::sync::Arc;
16use crate::utils;
17
18use lightning::ln::msgs::{ErrorAction, LightningError};
19use lightning::sign::EntropySource;
20use lightning::util::logger::Level;
21use lightning::util::persist::KVStore;
22
23use bitcoin::secp256k1::PublicKey;
24
25use core::ops::Deref;
26
27pub struct LSPS0ClientHandler<ES: Deref, K: Deref + Clone>
29where
30 ES::Target: EntropySource,
31 K::Target: KVStore,
32{
33 entropy_source: ES,
34 pending_messages: Arc<MessageQueue>,
35 pending_events: Arc<EventQueue<K>>,
36}
37
38impl<ES: Deref, K: Deref + Clone> LSPS0ClientHandler<ES, K>
39where
40 ES::Target: EntropySource,
41 K::Target: KVStore,
42{
43 pub(crate) fn new(
45 entropy_source: ES, pending_messages: Arc<MessageQueue>, pending_events: Arc<EventQueue<K>>,
46 ) -> Self {
47 Self { entropy_source, pending_messages, pending_events }
48 }
49
50 pub fn list_protocols(&self, counterparty_node_id: &PublicKey) {
56 let mut message_queue_notifier = self.pending_messages.notifier();
57
58 let msg = LSPS0Message::Request(
59 utils::generate_request_id(&self.entropy_source),
60 LSPS0Request::ListProtocols(LSPS0ListProtocolsRequest {}),
61 );
62
63 message_queue_notifier.enqueue(counterparty_node_id, msg.into());
64 }
65
66 fn handle_response(
67 &self, response: LSPS0Response, counterparty_node_id: &PublicKey,
68 ) -> Result<(), LightningError> {
69 let event_queue_notifier = self.pending_events.notifier();
70
71 match response {
72 LSPS0Response::ListProtocols(LSPS0ListProtocolsResponse { protocols }) => {
73 event_queue_notifier.enqueue(LSPS0ClientEvent::ListProtocolsResponse {
74 counterparty_node_id: *counterparty_node_id,
75 protocols,
76 });
77 Ok(())
78 },
79 LSPS0Response::ListProtocolsError(LSPSResponseError {
80 code, message, data, ..
81 }) => Err(LightningError {
82 err: format!(
83 "ListProtocols error received. code = {}, message = {}, data = {:?}",
84 code, message, data
85 ),
86 action: ErrorAction::IgnoreAndLog(Level::Info),
87 }),
88 }
89 }
90}
91
92impl<ES: Deref, K: Deref + Clone> LSPSProtocolMessageHandler for LSPS0ClientHandler<ES, K>
93where
94 ES::Target: EntropySource,
95 K::Target: KVStore,
96{
97 type ProtocolMessage = LSPS0Message;
98 const PROTOCOL_NUMBER: Option<u16> = None;
99
100 fn handle_message(
101 &self, message: Self::ProtocolMessage, counterparty_node_id: &PublicKey,
102 ) -> Result<(), LightningError> {
103 match message {
104 LSPS0Message::Response(_, response) => {
105 self.handle_response(response, counterparty_node_id)
106 },
107 LSPS0Message::Request(..) => {
108 debug_assert!(
109 false,
110 "Client handler received LSPS0 request message. This should never happen."
111 );
112 Err(LightningError { err: format!("Client handler received LSPS0 request message from node {}. This should never happen.", counterparty_node_id), action: ErrorAction::IgnoreAndLog(Level::Info)})
113 },
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use alloc::collections::VecDeque;
121 use alloc::string::ToString;
122 use alloc::sync::Arc;
123
124 use lightning::util::persist::KVStoreSyncWrapper;
125 use lightning::util::test_utils::TestStore;
126 use lightning::util::wakers::Notifier;
127
128 use crate::lsps0::ser::{LSPSMessage, LSPSRequestId};
129 use crate::tests::utils::{self, TestEntropy};
130
131 use super::*;
132
133 #[test]
134 fn test_list_protocols() {
135 let notifier = Arc::new(Notifier::new());
136 let pending_messages = Arc::new(MessageQueue::new(notifier));
137 let entropy_source = Arc::new(TestEntropy {});
138 let kv_store = Arc::new(KVStoreSyncWrapper(Arc::new(TestStore::new(false))));
139 let persist_notifier = Arc::new(Notifier::new());
140 let event_queue = Arc::new(EventQueue::new(VecDeque::new(), kv_store, persist_notifier));
141
142 let lsps0_handler = Arc::new(LSPS0ClientHandler::new(
143 entropy_source,
144 Arc::clone(&pending_messages),
145 event_queue,
146 ));
147
148 let counterparty_node_id = utils::parse_pubkey(
149 "027100442c3b79f606f80f322d98d499eefcb060599efc5d4ecb00209c2cb54190",
150 )
151 .unwrap();
152
153 lsps0_handler.list_protocols(&counterparty_node_id);
154 let pending_messages = pending_messages.get_and_clear_pending_msgs();
155
156 assert_eq!(pending_messages.len(), 1);
157
158 let (pubkey, message) = &pending_messages[0];
159
160 assert_eq!(*pubkey, counterparty_node_id);
161 assert_eq!(
162 *message,
163 LSPSMessage::LSPS0(LSPS0Message::Request(
164 LSPSRequestId("00000000000000000000000000000000".to_string()),
165 LSPS0Request::ListProtocols(LSPS0ListProtocolsRequest {})
166 ))
167 );
168 }
169}