@@ -198,6 +198,75 @@ impl ChainWatchedUtil {
198
198
}
199
199
}
200
200
201
+ /// Utility for notifying listeners about new blocks, and handling block rescans if new watch
202
+ /// data is registered.
203
+ pub struct BlockNotifier {
204
+ listeners : Mutex < Vec < Weak < ChainListener > > > , //TODO(vmw): try removing Weak
205
+ chain_monitor : Arc < ChainWatchInterface > ,
206
+ }
207
+
208
+ impl BlockNotifier {
209
+ /// Constructs a new BlockNotifier without any listeners.
210
+ pub fn new ( chain_monitor : Arc < ChainWatchInterface > ) -> BlockNotifier {
211
+ BlockNotifier {
212
+ listeners : Mutex :: new ( Vec :: new ( ) ) ,
213
+ chain_monitor,
214
+ }
215
+ }
216
+
217
+ /// Register the given listener to receive events. Only a weak pointer is provided and
218
+ /// the registration should be freed once that pointer expires.
219
+ // TODO: unregister
220
+ pub fn register_listener ( & self , listener : Weak < ChainListener > ) {
221
+ let mut vec = self . listeners . lock ( ) . unwrap ( ) ;
222
+ vec. push ( listener) ;
223
+ }
224
+
225
+ /// Notify listeners that a block was connected given a full, unfiltered block.
226
+ ///
227
+ /// Handles re-scanning the block and calling block_connected again if listeners register new
228
+ /// watch data during the callbacks for you (see ChainListener::block_connected for more info).
229
+ pub fn block_connected ( & self , block : & Block , height : u32 ) {
230
+ let mut reentered = true ;
231
+ while reentered {
232
+ let ( matched, matched_index) = self . chain_monitor . get_watched_txs ( block) ;
233
+ reentered = self . block_connected_checked ( & block. header , height, matched. as_slice ( ) , matched_index. as_slice ( ) ) ;
234
+ }
235
+ }
236
+
237
+ /// Notify listeners that a block was connected, given pre-filtered list of transactions in the
238
+ /// block which matched the filter (probably using does_match_tx).
239
+ ///
240
+ /// Returns true if notified listeners registered additional watch data (implying that the
241
+ /// block must be re-scanned and this function called again prior to further block_connected
242
+ /// calls, see ChainListener::block_connected for more info).
243
+ pub fn block_connected_checked ( & self , header : & BlockHeader , height : u32 , txn_matched : & [ Transaction ] , indexes_of_txn_matched : & [ u32 ] ) -> bool {
244
+ let last_seen = self . chain_monitor . reentered ( ) ;
245
+
246
+ let listeners = self . listeners . lock ( ) . unwrap ( ) . clone ( ) ;
247
+ for listener in listeners. iter ( ) {
248
+ match listener. upgrade ( ) {
249
+ Some ( arc) => arc. block_connected ( header, height, txn_matched, indexes_of_txn_matched) ,
250
+ None => ( )
251
+ }
252
+ }
253
+ return last_seen != self . chain_monitor . reentered ( ) ;
254
+ }
255
+
256
+
257
+ /// Notify listeners that a block was disconnected.
258
+ pub fn block_disconnected ( & self , header : & BlockHeader , disconnected_height : u32 ) {
259
+ let listeners = self . listeners . lock ( ) . unwrap ( ) . clone ( ) ;
260
+ for listener in listeners. iter ( ) {
261
+ match listener. upgrade ( ) {
262
+ Some ( arc) => arc. block_disconnected ( & header, disconnected_height) ,
263
+ None => ( )
264
+ }
265
+ }
266
+ }
267
+
268
+ }
269
+
201
270
/// Utility to capture some common parts of ChainWatchInterface implementors.
202
271
///
203
272
/// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
0 commit comments