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