|
13 | 13 | //! Includes traits for monitoring and receiving notifications of new blocks and block
|
14 | 14 | //! disconnections, transaction broadcasting, and feerate information requests.
|
15 | 15 |
|
16 |
| -use bitcoin::blockdata::block::{Block, BlockHeader}; |
| 16 | +use bitcoin::blockdata::block::BlockHeader; |
17 | 17 | use bitcoin::blockdata::transaction::Transaction;
|
18 | 18 | use bitcoin::blockdata::script::Script;
|
19 | 19 | use bitcoin::hash_types::Txid;
|
20 | 20 |
|
21 |
| -use std::sync::{Mutex, Arc}; |
22 | 21 | use std::collections::HashSet;
|
23 |
| -use std::ops::Deref; |
24 |
| -use std::marker::PhantomData; |
25 |
| -use std::ptr; |
26 | 22 |
|
27 | 23 | /// An interface to send a transaction to the Bitcoin network.
|
28 | 24 | pub trait BroadcasterInterface: Sync + Send {
|
@@ -161,139 +157,3 @@ impl ChainWatchedUtil {
|
161 | 157 | false
|
162 | 158 | }
|
163 | 159 | }
|
164 |
| - |
165 |
| -/// BlockNotifierArc is useful when you need a BlockNotifier that points to ChainListeners with |
166 |
| -/// static lifetimes, e.g. when you're using lightning-net-tokio (since tokio::spawn requires |
167 |
| -/// parameters with static lifetimes). Other times you can afford a reference, which is more |
168 |
| -/// efficient, in which case BlockNotifierRef is a more appropriate type. Defining these type |
169 |
| -/// aliases prevents issues such as overly long function definitions. |
170 |
| -pub type BlockNotifierArc = Arc<BlockNotifier<'static, Arc<ChainListener>>>; |
171 |
| - |
172 |
| -/// BlockNotifierRef is useful when you want a BlockNotifier that points to ChainListeners |
173 |
| -/// with nonstatic lifetimes. This is useful for when static lifetimes are not needed. Nonstatic |
174 |
| -/// lifetimes are more efficient but less flexible, and should be used by default unless static |
175 |
| -/// lifetimes are required, e.g. when you're using lightning-net-tokio (since tokio::spawn |
176 |
| -/// requires parameters with static lifetimes), in which case BlockNotifierArc is a more |
177 |
| -/// appropriate type. Defining these type aliases for common usages prevents issues such as |
178 |
| -/// overly long function definitions. |
179 |
| -pub type BlockNotifierRef<'a> = BlockNotifier<'a, &'a ChainListener>; |
180 |
| - |
181 |
| -/// Utility for notifying listeners when blocks are connected or disconnected. |
182 |
| -/// |
183 |
| -/// Rather than using a plain BlockNotifier, it is preferable to use either a BlockNotifierArc |
184 |
| -/// or a BlockNotifierRef for conciseness. See their documentation for more details, but essentially |
185 |
| -/// you should default to using a BlockNotifierRef, and use a BlockNotifierArc instead when you |
186 |
| -/// require ChainListeners with static lifetimes, such as when you're using lightning-net-tokio. |
187 |
| -pub struct BlockNotifier<'a, CL: Deref + 'a> |
188 |
| - where CL::Target: ChainListener + 'a { |
189 |
| - listeners: Mutex<Vec<CL>>, |
190 |
| - phantom: PhantomData<&'a ()>, |
191 |
| -} |
192 |
| - |
193 |
| -impl<'a, CL: Deref + 'a> BlockNotifier<'a, CL> |
194 |
| - where CL::Target: ChainListener + 'a { |
195 |
| - /// Constructs a new BlockNotifier without any listeners. |
196 |
| - pub fn new() -> BlockNotifier<'a, CL> { |
197 |
| - BlockNotifier { |
198 |
| - listeners: Mutex::new(Vec::new()), |
199 |
| - phantom: PhantomData, |
200 |
| - } |
201 |
| - } |
202 |
| - |
203 |
| - /// Register the given listener to receive events. |
204 |
| - pub fn register_listener(&self, listener: CL) { |
205 |
| - let mut vec = self.listeners.lock().unwrap(); |
206 |
| - vec.push(listener); |
207 |
| - } |
208 |
| - /// Unregister the given listener to no longer |
209 |
| - /// receive events. |
210 |
| - /// |
211 |
| - /// If the same listener is registered multiple times, unregistering |
212 |
| - /// will remove ALL occurrences of that listener. Comparison is done using |
213 |
| - /// the pointer returned by the Deref trait implementation. |
214 |
| - pub fn unregister_listener(&self, listener: CL) { |
215 |
| - let mut vec = self.listeners.lock().unwrap(); |
216 |
| - // item is a ref to an abstract thing that dereferences to a ChainListener, |
217 |
| - // so dereference it twice to get the ChainListener itself |
218 |
| - vec.retain(|item | !ptr::eq(&(**item), &(*listener))); |
219 |
| - } |
220 |
| - |
221 |
| - /// Notify listeners that a block was connected. |
222 |
| - pub fn block_connected(&self, block: &Block, height: u32) { |
223 |
| - let txdata: Vec<_> = block.txdata.iter().enumerate().collect(); |
224 |
| - let listeners = self.listeners.lock().unwrap(); |
225 |
| - for listener in listeners.iter() { |
226 |
| - listener.block_connected(&block.header, &txdata, height); |
227 |
| - } |
228 |
| - } |
229 |
| - |
230 |
| - /// Notify listeners that a block was disconnected. |
231 |
| - pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) { |
232 |
| - let listeners = self.listeners.lock().unwrap(); |
233 |
| - for listener in listeners.iter() { |
234 |
| - listener.block_disconnected(&header, disconnected_height); |
235 |
| - } |
236 |
| - } |
237 |
| -} |
238 |
| - |
239 |
| -#[cfg(test)] |
240 |
| -mod tests { |
241 |
| - use bitcoin::blockdata::block::BlockHeader; |
242 |
| - use bitcoin::blockdata::transaction::Transaction; |
243 |
| - use super::{BlockNotifier, ChainListener}; |
244 |
| - use std::ptr; |
245 |
| - |
246 |
| - struct TestChainListener(u8); |
247 |
| - |
248 |
| - impl ChainListener for TestChainListener { |
249 |
| - fn block_connected(&self, _header: &BlockHeader, _txdata: &[(usize, &Transaction)], _height: u32) {} |
250 |
| - fn block_disconnected(&self, _header: &BlockHeader, _disconnected_height: u32) {} |
251 |
| - } |
252 |
| - |
253 |
| - #[test] |
254 |
| - fn register_listener_test() { |
255 |
| - let block_notifier = BlockNotifier::new(); |
256 |
| - assert_eq!(block_notifier.listeners.lock().unwrap().len(), 0); |
257 |
| - let listener = &TestChainListener(0); |
258 |
| - block_notifier.register_listener(listener as &ChainListener); |
259 |
| - let vec = block_notifier.listeners.lock().unwrap(); |
260 |
| - assert_eq!(vec.len(), 1); |
261 |
| - let item = vec.first().unwrap(); |
262 |
| - assert!(ptr::eq(&(**item), listener)); |
263 |
| - } |
264 |
| - |
265 |
| - #[test] |
266 |
| - fn unregister_single_listener_test() { |
267 |
| - let block_notifier = BlockNotifier::new(); |
268 |
| - let listener1 = &TestChainListener(1); |
269 |
| - let listener2 = &TestChainListener(2); |
270 |
| - block_notifier.register_listener(listener1 as &ChainListener); |
271 |
| - block_notifier.register_listener(listener2 as &ChainListener); |
272 |
| - let vec = block_notifier.listeners.lock().unwrap(); |
273 |
| - assert_eq!(vec.len(), 2); |
274 |
| - drop(vec); |
275 |
| - block_notifier.unregister_listener(listener1); |
276 |
| - let vec = block_notifier.listeners.lock().unwrap(); |
277 |
| - assert_eq!(vec.len(), 1); |
278 |
| - let item = vec.first().unwrap(); |
279 |
| - assert!(ptr::eq(&(**item), listener2)); |
280 |
| - } |
281 |
| - |
282 |
| - #[test] |
283 |
| - fn unregister_multiple_of_the_same_listeners_test() { |
284 |
| - let block_notifier = BlockNotifier::new(); |
285 |
| - let listener1 = &TestChainListener(1); |
286 |
| - let listener2 = &TestChainListener(2); |
287 |
| - block_notifier.register_listener(listener1 as &ChainListener); |
288 |
| - block_notifier.register_listener(listener1 as &ChainListener); |
289 |
| - block_notifier.register_listener(listener2 as &ChainListener); |
290 |
| - let vec = block_notifier.listeners.lock().unwrap(); |
291 |
| - assert_eq!(vec.len(), 3); |
292 |
| - drop(vec); |
293 |
| - block_notifier.unregister_listener(listener1); |
294 |
| - let vec = block_notifier.listeners.lock().unwrap(); |
295 |
| - assert_eq!(vec.len(), 1); |
296 |
| - let item = vec.first().unwrap(); |
297 |
| - assert!(ptr::eq(&(**item), listener2)); |
298 |
| - } |
299 |
| -} |
0 commit comments