11use super :: LiquidityEvent ;
2+
3+ use crate :: lsps2:: event:: LSPS2ServiceEvent ;
4+ use crate :: persist:: {
5+ LIQUIDITY_MANAGER_EVENT_QUEUE_PERSISTENCE_KEY ,
6+ LIQUIDITY_MANAGER_EVENT_QUEUE_PERSISTENCE_SECONDARY_NAMESPACE ,
7+ LIQUIDITY_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE ,
8+ } ;
29use crate :: sync:: { Arc , Mutex } ;
310
411use alloc:: collections:: VecDeque ;
512use alloc:: vec:: Vec ;
613
714use core:: future:: Future ;
15+ use core:: ops:: Deref ;
816use core:: task:: { Poll , Waker } ;
917
18+ use lightning:: ln:: msgs:: DecodeError ;
19+ use lightning:: util:: persist:: KVStore ;
20+ use lightning:: util:: ser:: {
21+ BigSize , CollectionLength , FixedLengthReader , Readable , Writeable , Writer ,
22+ } ;
23+
1024/// The maximum queue size we allow before starting to drop events.
1125pub const MAX_EVENT_QUEUE_SIZE : usize = 1000 ;
1226
13- pub ( crate ) struct EventQueue {
27+ pub ( crate ) struct EventQueue < K : Deref + Clone >
28+ where
29+ K :: Target : KVStore ,
30+ {
1431 queue : Arc < Mutex < VecDeque < LiquidityEvent > > > ,
1532 waker : Arc < Mutex < Option < Waker > > > ,
1633 #[ cfg( feature = "std" ) ]
1734 condvar : Arc < crate :: sync:: Condvar > ,
35+ kv_store : K ,
1836}
1937
20- impl EventQueue {
21- pub fn new ( ) -> Self {
38+ impl < K : Deref + Clone > EventQueue < K >
39+ where
40+ K :: Target : KVStore ,
41+ {
42+ pub fn new ( kv_store : K ) -> Self {
2243 let queue = Arc :: new ( Mutex :: new ( VecDeque :: new ( ) ) ) ;
2344 let waker = Arc :: new ( Mutex :: new ( None ) ) ;
2445 Self {
2546 queue,
2647 waker,
2748 #[ cfg( feature = "std" ) ]
2849 condvar : Arc :: new ( crate :: sync:: Condvar :: new ( ) ) ,
50+ kv_store,
2951 }
3052 }
3153
@@ -67,16 +89,35 @@ impl EventQueue {
6789 }
6890
6991 // Returns an [`EventQueueNotifierGuard`] that will notify about new event when dropped.
70- pub fn notifier ( & self ) -> EventQueueNotifierGuard < ' _ > {
92+ pub fn notifier ( & self ) -> EventQueueNotifierGuard < ' _ , K > {
7193 EventQueueNotifierGuard ( self )
7294 }
95+
96+ pub async fn persist ( & self ) -> Result < ( ) , lightning:: io:: Error > {
97+ let queue = self . queue . lock ( ) . unwrap ( ) ;
98+ let encoded = EventQueueSerWrapper ( & queue) . encode ( ) ;
99+
100+ self . kv_store
101+ . write (
102+ LIQUIDITY_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE ,
103+ LIQUIDITY_MANAGER_EVENT_QUEUE_PERSISTENCE_SECONDARY_NAMESPACE ,
104+ LIQUIDITY_MANAGER_EVENT_QUEUE_PERSISTENCE_KEY ,
105+ encoded,
106+ )
107+ . await
108+ }
73109}
74110
75111// A guard type that will notify about new events when dropped.
76112#[ must_use]
77- pub ( crate ) struct EventQueueNotifierGuard < ' a > ( & ' a EventQueue ) ;
78-
79- impl < ' a > EventQueueNotifierGuard < ' a > {
113+ pub ( crate ) struct EventQueueNotifierGuard < ' a , K : Deref + Clone > ( & ' a EventQueue < K > )
114+ where
115+ K :: Target : KVStore ;
116+
117+ impl < ' a , K : Deref + Clone > EventQueueNotifierGuard < ' a , K >
118+ where
119+ K :: Target : KVStore ,
120+ {
80121 pub fn enqueue < E : Into < LiquidityEvent > > ( & self , event : E ) {
81122 let mut queue = self . 0 . queue . lock ( ) . unwrap ( ) ;
82123 if queue. len ( ) < MAX_EVENT_QUEUE_SIZE {
@@ -87,7 +128,10 @@ impl<'a> EventQueueNotifierGuard<'a> {
87128 }
88129}
89130
90- impl < ' a > Drop for EventQueueNotifierGuard < ' a > {
131+ impl < ' a , K : Deref + Clone > Drop for EventQueueNotifierGuard < ' a , K >
132+ where
133+ K :: Target : KVStore ,
134+ {
91135 fn drop ( & mut self ) {
92136 let should_notify = !self . 0 . queue . lock ( ) . unwrap ( ) . is_empty ( ) ;
93137
@@ -122,6 +166,91 @@ impl Future for EventFuture {
122166 }
123167}
124168
169+ pub ( crate ) struct EventQueueDeserWrapper ( pub VecDeque < LiquidityEvent > ) ;
170+
171+ impl Readable for EventQueueDeserWrapper {
172+ fn read < R : lightning:: io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
173+ let len: CollectionLength = Readable :: read ( reader) ?;
174+ let mut queue = VecDeque :: with_capacity ( len. 0 as usize ) ;
175+ for _ in 0 ..len. 0 {
176+ let event = match Readable :: read ( reader) ? {
177+ 0u8 => {
178+ let ev = Readable :: read ( reader) ?;
179+ LiquidityEvent :: LSPS2Service ( ev)
180+ } ,
181+ 2u8 => {
182+ let ev = Readable :: read ( reader) ?;
183+ LiquidityEvent :: LSPS5Service ( ev)
184+ } ,
185+ x if x % 2 == 1 => {
186+ // If the event is of unknown type, assume it was written with `write_tlv_fields`,
187+ // which prefixes the whole thing with a length BigSize. Because the event is
188+ // odd-type unknown, we should treat it as `Ok(None)` even if it has some TLV
189+ // fields that are even. Thus, we avoid using `read_tlv_fields` and simply read
190+ // exactly the number of bytes specified, ignoring them entirely.
191+ let tlv_len: BigSize = Readable :: read ( reader) ?;
192+ FixedLengthReader :: new ( reader, tlv_len. 0 )
193+ . eat_remaining ( )
194+ . map_err ( |_| DecodeError :: ShortRead ) ?;
195+ continue ;
196+ } ,
197+ _ => return Err ( DecodeError :: InvalidValue ) ,
198+ } ;
199+ queue. push_back ( event) ;
200+ }
201+ Ok ( Self ( queue) )
202+ }
203+ }
204+
205+ struct EventQueueSerWrapper < ' a > ( & ' a VecDeque < LiquidityEvent > ) ;
206+
207+ impl Writeable for EventQueueSerWrapper < ' _ > {
208+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , lightning:: io:: Error > {
209+ let maybe_process_event = |event : & LiquidityEvent ,
210+ writer : Option < & mut W > |
211+ -> Result < bool , lightning:: io:: Error > {
212+ match event {
213+ LiquidityEvent :: LSPS2Service ( event) => {
214+ if matches ! ( event, LSPS2ServiceEvent :: GetInfo { .. } )
215+ || matches ! ( event, LSPS2ServiceEvent :: BuyRequest { .. } )
216+ {
217+ // Skip persisting GetInfoRequest and BuyRequest events as we prune the pending
218+ // request state currently anyways.
219+ Ok ( false )
220+ } else {
221+ if let Some ( writer) = writer {
222+ 0u8 . write ( writer) ?;
223+ event. write ( writer) ?;
224+ }
225+ Ok ( true )
226+ }
227+ } ,
228+ LiquidityEvent :: LSPS5Service ( event) => {
229+ if let Some ( writer) = writer {
230+ 2u8 . write ( writer) ?;
231+ event. write ( writer) ?;
232+ }
233+ Ok ( true )
234+ } ,
235+ _ => Ok ( false ) ,
236+ }
237+ } ;
238+
239+ let mut persisted_events_len = 0 ;
240+ for e in self . 0 . iter ( ) {
241+ if maybe_process_event ( e, None ) ? {
242+ persisted_events_len += 1 ;
243+ }
244+ }
245+
246+ CollectionLength ( persisted_events_len) . write ( writer) ?;
247+ for e in self . 0 . iter ( ) {
248+ maybe_process_event ( e, Some ( writer) ) ?;
249+ }
250+ Ok ( ( ) )
251+ }
252+ }
253+
125254#[ cfg( test) ]
126255mod tests {
127256 #[ tokio:: test]
@@ -131,10 +260,13 @@ mod tests {
131260 use crate :: lsps0:: event:: LSPS0ClientEvent ;
132261 use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
133262 use core:: sync:: atomic:: { AtomicU16 , Ordering } ;
263+ use lightning:: util:: persist:: KVStoreSyncWrapper ;
264+ use lightning:: util:: test_utils:: TestStore ;
134265 use std:: sync:: Arc ;
135266 use std:: time:: Duration ;
136267
137- let event_queue = Arc :: new ( EventQueue :: new ( ) ) ;
268+ let kv_store = Arc :: new ( KVStoreSyncWrapper ( Arc :: new ( TestStore :: new ( false ) ) ) ) ;
269+ let event_queue = Arc :: new ( EventQueue :: new ( kv_store) ) ;
138270 assert_eq ! ( event_queue. next_event( ) , None ) ;
139271
140272 let secp_ctx = Secp256k1 :: new ( ) ;
0 commit comments