Add Electrum integration test
[rust-lightning] / lightning-transaction-sync / tests / integration_tests.rs
1 #![cfg(any(feature = "esplora-blocking", feature = "esplora-async", feature = "electrum"))]
2
3 #[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))]
4 use lightning_transaction_sync::EsploraSyncClient;
5 #[cfg(feature = "electrum")]
6 use lightning_transaction_sync::ElectrumSyncClient;
7 use lightning::chain::{Confirm, Filter, WatchedOutput};
8 use lightning::chain::transaction::{OutPoint, TransactionData};
9 use lightning::util::test_utils::TestLogger;
10
11 use electrsd::{bitcoind, bitcoind::BitcoinD, ElectrsD};
12 use bitcoin::{Amount, Txid, BlockHash};
13 use bitcoin::blockdata::block::Header;
14 use bitcoin::blockdata::constants::genesis_block;
15 use bitcoin::network::constants::Network;
16 use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
17 use bitcoind::bitcoincore_rpc::RpcApi;
18
19 use std::env;
20 use std::sync::Mutex;
21 use std::time::Duration;
22 use std::collections::{HashMap, HashSet};
23
24 pub fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) {
25         let bitcoind_exe =
26                 env::var("BITCOIND_EXE").ok().or_else(|| bitcoind::downloaded_exe_path().ok()).expect(
27                         "you need to provide an env var BITCOIND_EXE or specify a bitcoind version feature",
28                 );
29         let mut bitcoind_conf = bitcoind::Conf::default();
30         bitcoind_conf.network = "regtest";
31         let bitcoind = BitcoinD::with_conf(bitcoind_exe, &bitcoind_conf).unwrap();
32
33         let electrs_exe = env::var("ELECTRS_EXE")
34                 .ok()
35                 .or_else(electrsd::downloaded_exe_path)
36                 .expect("you need to provide env var ELECTRS_EXE or specify an electrsd version feature");
37         let mut electrsd_conf = electrsd::Conf::default();
38         electrsd_conf.http_enabled = true;
39         electrsd_conf.network = "regtest";
40         let electrsd = ElectrsD::with_conf(electrs_exe, &bitcoind, &electrsd_conf).unwrap();
41         (bitcoind, electrsd)
42 }
43
44 pub fn generate_blocks_and_wait(bitcoind: &BitcoinD, electrsd: &ElectrsD, num: usize) {
45         let cur_height = bitcoind.client.get_block_count().expect("failed to get current block height");
46         let address = bitcoind
47                 .client
48                 .get_new_address(Some("test"), Some(AddressType::Legacy))
49                 .expect("failed to get new address")
50                 .assume_checked();
51         // TODO: expect this Result once the WouldBlock issue is resolved upstream.
52         let _block_hashes_res = bitcoind.client.generate_to_address(num as u64, &address);
53         wait_for_block(electrsd, cur_height as usize + num);
54 }
55
56 pub fn wait_for_block(electrsd: &ElectrsD, min_height: usize) {
57         use electrsd::electrum_client::ElectrumApi;
58         let mut header = match electrsd.client.block_headers_subscribe_raw() {
59                 Ok(header) => header,
60                 Err(_) => {
61                         // While subscribing should succeed the first time around, we ran into some cases where
62                         // it didn't. Since we can't proceed without subscribing, we try again after a delay
63                         // and panic if it still fails.
64                         std::thread::sleep(Duration::from_secs(1));
65                         electrsd.client.block_headers_subscribe_raw().expect("failed to subscribe to block headers")
66                 }
67         };
68         loop {
69                 if header.height >= min_height {
70                         break;
71                 }
72                 header = exponential_backoff_poll(|| {
73                         electrsd.trigger().expect("failed to trigger electrsd");
74                         electrsd.client.ping().expect("failed to ping electrsd");
75                         electrsd.client.block_headers_pop_raw().expect("failed to pop block header")
76                 });
77         }
78 }
79
80 fn exponential_backoff_poll<T, F>(mut poll: F) -> T
81 where
82         F: FnMut() -> Option<T>,
83 {
84         let mut delay = Duration::from_millis(64);
85         let mut tries = 0;
86         loop {
87                 match poll() {
88                         Some(data) => break data,
89                         None if delay.as_millis() < 512 => {
90                                 delay = delay.mul_f32(2.0);
91                                 tries += 1;
92                         }
93                         None if tries == 10 => panic!("Exceeded our maximum wait time."),
94                         None => tries += 1,
95                 }
96
97                 std::thread::sleep(delay);
98         }
99 }
100
101 #[derive(Debug)]
102 enum TestConfirmableEvent {
103         Confirmed(Txid, BlockHash, u32),
104         Unconfirmed(Txid),
105         BestBlockUpdated(BlockHash, u32),
106 }
107
108 struct TestConfirmable {
109         pub confirmed_txs: Mutex<HashMap<Txid, (BlockHash, u32)>>,
110         pub unconfirmed_txs: Mutex<HashSet<Txid>>,
111         pub best_block: Mutex<(BlockHash, u32)>,
112         pub events: Mutex<Vec<TestConfirmableEvent>>,
113 }
114
115 impl TestConfirmable {
116         pub fn new() -> Self {
117                 let genesis_hash = genesis_block(Network::Regtest).block_hash();
118                 Self {
119                         confirmed_txs: Mutex::new(HashMap::new()),
120                         unconfirmed_txs: Mutex::new(HashSet::new()),
121                         best_block: Mutex::new((genesis_hash, 0)),
122                         events: Mutex::new(Vec::new()),
123                 }
124         }
125 }
126
127 impl Confirm for TestConfirmable {
128         fn transactions_confirmed(&self, header: &Header, txdata: &TransactionData<'_>, height: u32) {
129                 for (_, tx) in txdata {
130                         let txid = tx.txid();
131                         let block_hash = header.block_hash();
132                         self.confirmed_txs.lock().unwrap().insert(txid, (block_hash, height));
133                         self.unconfirmed_txs.lock().unwrap().remove(&txid);
134                         self.events.lock().unwrap().push(TestConfirmableEvent::Confirmed(txid, block_hash, height));
135                 }
136         }
137
138         fn transaction_unconfirmed(&self, txid: &Txid) {
139                 self.unconfirmed_txs.lock().unwrap().insert(*txid);
140                 self.confirmed_txs.lock().unwrap().remove(txid);
141                 self.events.lock().unwrap().push(TestConfirmableEvent::Unconfirmed(*txid));
142         }
143
144         fn best_block_updated(&self, header: &Header, height: u32) {
145                 let block_hash = header.block_hash();
146                 *self.best_block.lock().unwrap() = (block_hash, height);
147                 self.events.lock().unwrap().push(TestConfirmableEvent::BestBlockUpdated(block_hash, height));
148         }
149
150         fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
151                 self.confirmed_txs.lock().unwrap().iter().map(|(&txid, (hash, height))| (txid, *height, Some(*hash))).collect::<Vec<_>>()
152         }
153 }
154
155 #[test]
156 #[cfg(feature = "esplora-blocking")]
157 fn test_esplora_syncs() {
158         let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
159         generate_blocks_and_wait(&bitcoind, &electrsd, 101);
160         let mut logger = TestLogger::new();
161         let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
162         let tx_sync = EsploraSyncClient::new(esplora_url, &mut logger);
163         let confirmable = TestConfirmable::new();
164
165         // Check we pick up on new best blocks
166         assert_eq!(confirmable.best_block.lock().unwrap().1, 0);
167
168         tx_sync.sync(vec![&confirmable]).unwrap();
169         assert_eq!(confirmable.best_block.lock().unwrap().1, 102);
170
171         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
172         assert_eq!(events.len(), 1);
173
174         // Check registered confirmed transactions are marked confirmed
175         let new_address = bitcoind.client.get_new_address(Some("test"),
176                 Some(AddressType::Legacy)).unwrap().assume_checked();
177         let txid = bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None, None,
178                 None, None, None, None).unwrap();
179         let second_txid = bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None,
180                 None, None, None, None, None).unwrap();
181         tx_sync.register_tx(&txid, &new_address.script_pubkey());
182
183         tx_sync.sync(vec![&confirmable]).unwrap();
184
185         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
186         assert_eq!(events.len(), 0);
187         assert!(confirmable.confirmed_txs.lock().unwrap().is_empty());
188         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
189
190         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
191         tx_sync.sync(vec![&confirmable]).unwrap();
192
193         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
194         assert_eq!(events.len(), 2);
195         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
196         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
197
198         // Now take an arbitrary output of the second transaction and check we'll confirm its spend.
199         let tx_res = bitcoind.client.get_transaction(&second_txid, None).unwrap();
200         let block_hash = tx_res.info.blockhash.unwrap();
201         let tx = tx_res.transaction().unwrap();
202         let prev_outpoint = tx.input.first().unwrap().previous_output;
203         let prev_tx = bitcoind.client.get_transaction(&prev_outpoint.txid, None).unwrap().transaction()
204                 .unwrap();
205         let prev_script_pubkey = prev_tx.output[prev_outpoint.vout as usize].script_pubkey.clone();
206         let output = WatchedOutput {
207                 block_hash: Some(block_hash),
208                 outpoint: OutPoint { txid: prev_outpoint.txid, index: prev_outpoint.vout as u16 },
209                 script_pubkey: prev_script_pubkey
210         };
211
212         tx_sync.register_output(output);
213         tx_sync.sync(vec![&confirmable]).unwrap();
214
215         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
216         assert_eq!(events.len(), 1);
217         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&second_txid));
218         assert_eq!(confirmable.confirmed_txs.lock().unwrap().len(), 2);
219         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
220
221         // Check previously confirmed transactions are marked unconfirmed when they are reorged.
222         let best_block_hash = bitcoind.client.get_best_block_hash().unwrap();
223         bitcoind.client.invalidate_block(&best_block_hash).unwrap();
224
225         // We're getting back to the previous height with a new tip, but best block shouldn't change.
226         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
227         assert_ne!(bitcoind.client.get_best_block_hash().unwrap(), best_block_hash);
228         tx_sync.sync(vec![&confirmable]).unwrap();
229         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
230         assert_eq!(events.len(), 0);
231
232         // Now we're surpassing previous height, getting new tip.
233         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
234         assert_ne!(bitcoind.client.get_best_block_hash().unwrap(), best_block_hash);
235         tx_sync.sync(vec![&confirmable]).unwrap();
236
237         // Transactions still confirmed but under new tip.
238         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
239         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&second_txid));
240         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
241
242         // Check we got unconfirmed, then reconfirmed in the meantime.
243         let mut seen_txids = HashSet::new();
244         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
245         assert_eq!(events.len(), 5);
246
247         match events[0] {
248                 TestConfirmableEvent::Unconfirmed(t) => {
249                         assert!(t == txid || t == second_txid);
250                         assert!(seen_txids.insert(t));
251                 },
252                 _ => panic!("Unexpected event"),
253         }
254
255         match events[1] {
256                 TestConfirmableEvent::Unconfirmed(t) => {
257                         assert!(t == txid || t == second_txid);
258                         assert!(seen_txids.insert(t));
259                 },
260                 _ => panic!("Unexpected event"),
261         }
262
263         match events[2] {
264                 TestConfirmableEvent::BestBlockUpdated(..) => {},
265                 _ => panic!("Unexpected event"),
266         }
267
268         match events[3] {
269                 TestConfirmableEvent::Confirmed(t, _, _) => {
270                         assert!(t == txid || t == second_txid);
271                         assert!(seen_txids.remove(&t));
272                 },
273                 _ => panic!("Unexpected event"),
274         }
275
276         match events[4] {
277                 TestConfirmableEvent::Confirmed(t, _, _) => {
278                         assert!(t == txid || t == second_txid);
279                         assert!(seen_txids.remove(&t));
280                 },
281                 _ => panic!("Unexpected event"),
282         }
283
284         assert_eq!(seen_txids.len(), 0);
285 }
286
287 #[tokio::test]
288 #[cfg(feature = "esplora-async")]
289 async fn test_esplora_syncs() {
290         let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
291         generate_blocks_and_wait(&bitcoind, &electrsd, 101);
292         let mut logger = TestLogger::new();
293         let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
294         let tx_sync = EsploraSyncClient::new(esplora_url, &mut logger);
295         let confirmable = TestConfirmable::new();
296
297         // Check we pick up on new best blocks
298         assert_eq!(confirmable.best_block.lock().unwrap().1, 0);
299
300         tx_sync.sync(vec![&confirmable]).await.unwrap();
301         assert_eq!(confirmable.best_block.lock().unwrap().1, 102);
302
303         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
304         assert_eq!(events.len(), 1);
305
306         // Check registered confirmed transactions are marked confirmed
307         let new_address = bitcoind.client.get_new_address(Some("test"),
308                 Some(AddressType::Legacy)).unwrap().assume_checked();
309         let txid = bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None, None,
310                 None, None, None, None).unwrap();
311         let second_txid = bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None,
312                 None, None, None, None, None).unwrap();
313         tx_sync.register_tx(&txid, &new_address.script_pubkey());
314
315         tx_sync.sync(vec![&confirmable]).await.unwrap();
316
317         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
318         assert_eq!(events.len(), 0);
319         assert!(confirmable.confirmed_txs.lock().unwrap().is_empty());
320         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
321
322         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
323         tx_sync.sync(vec![&confirmable]).await.unwrap();
324
325         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
326         assert_eq!(events.len(), 2);
327         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
328         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
329
330         // Now take an arbitrary output of the second transaction and check we'll confirm its spend.
331         let tx_res = bitcoind.client.get_transaction(&second_txid, None).unwrap();
332         let block_hash = tx_res.info.blockhash.unwrap();
333         let tx = tx_res.transaction().unwrap();
334         let prev_outpoint = tx.input.first().unwrap().previous_output;
335         let prev_tx = bitcoind.client.get_transaction(&prev_outpoint.txid, None).unwrap().transaction()
336                 .unwrap();
337         let prev_script_pubkey = prev_tx.output[prev_outpoint.vout as usize].script_pubkey.clone();
338         let output = WatchedOutput {
339                 block_hash: Some(block_hash),
340                 outpoint: OutPoint { txid: prev_outpoint.txid, index: prev_outpoint.vout as u16 },
341                 script_pubkey: prev_script_pubkey
342         };
343
344         tx_sync.register_output(output);
345         tx_sync.sync(vec![&confirmable]).await.unwrap();
346
347         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
348         assert_eq!(events.len(), 1);
349         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&second_txid));
350         assert_eq!(confirmable.confirmed_txs.lock().unwrap().len(), 2);
351         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
352
353         // Check previously confirmed transactions are marked unconfirmed when they are reorged.
354         let best_block_hash = bitcoind.client.get_best_block_hash().unwrap();
355         bitcoind.client.invalidate_block(&best_block_hash).unwrap();
356
357         // We're getting back to the previous height with a new tip, but best block shouldn't change.
358         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
359         assert_ne!(bitcoind.client.get_best_block_hash().unwrap(), best_block_hash);
360         tx_sync.sync(vec![&confirmable]).await.unwrap();
361         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
362         assert_eq!(events.len(), 0);
363
364         // Now we're surpassing previous height, getting new tip.
365         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
366         assert_ne!(bitcoind.client.get_best_block_hash().unwrap(), best_block_hash);
367         tx_sync.sync(vec![&confirmable]).await.unwrap();
368
369         // Transactions still confirmed but under new tip.
370         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
371         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&second_txid));
372         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
373
374         // Check we got unconfirmed, then reconfirmed in the meantime.
375         let mut seen_txids = HashSet::new();
376         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
377         assert_eq!(events.len(), 5);
378
379         match events[0] {
380                 TestConfirmableEvent::Unconfirmed(t) => {
381                         assert!(t == txid || t == second_txid);
382                         assert!(seen_txids.insert(t));
383                 },
384                 _ => panic!("Unexpected event"),
385         }
386
387         match events[1] {
388                 TestConfirmableEvent::Unconfirmed(t) => {
389                         assert!(t == txid || t == second_txid);
390                         assert!(seen_txids.insert(t));
391                 },
392                 _ => panic!("Unexpected event"),
393         }
394
395         match events[2] {
396                 TestConfirmableEvent::BestBlockUpdated(..) => {},
397                 _ => panic!("Unexpected event"),
398         }
399
400         match events[3] {
401                 TestConfirmableEvent::Confirmed(t, _, _) => {
402                         assert!(t == txid || t == second_txid);
403                         assert!(seen_txids.remove(&t));
404                 },
405                 _ => panic!("Unexpected event"),
406         }
407
408         match events[4] {
409                 TestConfirmableEvent::Confirmed(t, _, _) => {
410                         assert!(t == txid || t == second_txid);
411                         assert!(seen_txids.remove(&t));
412                 },
413                 _ => panic!("Unexpected event"),
414         }
415
416         assert_eq!(seen_txids.len(), 0);
417 }
418
419 #[test]
420 #[cfg(feature = "electrum")]
421 fn test_electrum_syncs() {
422         let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
423         generate_blocks_and_wait(&bitcoind, &electrsd, 101);
424         let mut logger = TestLogger::new();
425         let electrum_url = format!("tcp://{}", electrsd.electrum_url);
426         let tx_sync = ElectrumSyncClient::new(electrum_url, &mut logger).unwrap();
427         let confirmable = TestConfirmable::new();
428
429         // Check we pick up on new best blocks
430         assert_eq!(confirmable.best_block.lock().unwrap().1, 0);
431
432         tx_sync.sync(vec![&confirmable]).unwrap();
433         assert_eq!(confirmable.best_block.lock().unwrap().1, 102);
434
435         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
436         assert_eq!(events.len(), 1);
437
438         // Check registered confirmed transactions are marked confirmed
439         let new_address = bitcoind.client.get_new_address(Some("test"),
440                 Some(AddressType::Legacy)).unwrap().assume_checked();
441         let txid = bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None, None,
442                 None, None, None, None).unwrap();
443         let second_txid = bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None,
444                 None, None, None, None, None).unwrap();
445         tx_sync.register_tx(&txid, &new_address.script_pubkey());
446
447         tx_sync.sync(vec![&confirmable]).unwrap();
448
449         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
450         assert_eq!(events.len(), 0);
451         assert!(confirmable.confirmed_txs.lock().unwrap().is_empty());
452         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
453
454         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
455         tx_sync.sync(vec![&confirmable]).unwrap();
456
457         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
458         assert_eq!(events.len(), 2);
459         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
460         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
461
462         // Now take an arbitrary output of the second transaction and check we'll confirm its spend.
463         let tx_res = bitcoind.client.get_transaction(&second_txid, None).unwrap();
464         let block_hash = tx_res.info.blockhash.unwrap();
465         let tx = tx_res.transaction().unwrap();
466         let prev_outpoint = tx.input.first().unwrap().previous_output;
467         let prev_tx = bitcoind.client.get_transaction(&prev_outpoint.txid, None).unwrap().transaction()
468                 .unwrap();
469         let prev_script_pubkey = prev_tx.output[prev_outpoint.vout as usize].script_pubkey.clone();
470         let output = WatchedOutput {
471                 block_hash: Some(block_hash),
472                 outpoint: OutPoint { txid: prev_outpoint.txid, index: prev_outpoint.vout as u16 },
473                 script_pubkey: prev_script_pubkey
474         };
475
476         tx_sync.register_output(output);
477         tx_sync.sync(vec![&confirmable]).unwrap();
478
479         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
480         assert_eq!(events.len(), 1);
481         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&second_txid));
482         assert_eq!(confirmable.confirmed_txs.lock().unwrap().len(), 2);
483         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
484
485         // Check previously confirmed transactions are marked unconfirmed when they are reorged.
486         let best_block_hash = bitcoind.client.get_best_block_hash().unwrap();
487         bitcoind.client.invalidate_block(&best_block_hash).unwrap();
488
489         // We're getting back to the previous height with a new tip, but best block shouldn't change.
490         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
491         assert_ne!(bitcoind.client.get_best_block_hash().unwrap(), best_block_hash);
492         tx_sync.sync(vec![&confirmable]).unwrap();
493         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
494         assert_eq!(events.len(), 0);
495
496         // Now we're surpassing previous height, getting new tip.
497         generate_blocks_and_wait(&bitcoind, &electrsd, 1);
498         assert_ne!(bitcoind.client.get_best_block_hash().unwrap(), best_block_hash);
499         tx_sync.sync(vec![&confirmable]).unwrap();
500
501         // Transactions still confirmed but under new tip.
502         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&txid));
503         assert!(confirmable.confirmed_txs.lock().unwrap().contains_key(&second_txid));
504         assert!(confirmable.unconfirmed_txs.lock().unwrap().is_empty());
505
506         // Check we got unconfirmed, then reconfirmed in the meantime.
507         let mut seen_txids = HashSet::new();
508         let events = std::mem::take(&mut *confirmable.events.lock().unwrap());
509         assert_eq!(events.len(), 5);
510
511         match events[0] {
512                 TestConfirmableEvent::Unconfirmed(t) => {
513                         assert!(t == txid || t == second_txid);
514                         assert!(seen_txids.insert(t));
515                 },
516                 _ => panic!("Unexpected event"),
517         }
518
519         match events[1] {
520                 TestConfirmableEvent::Unconfirmed(t) => {
521                         assert!(t == txid || t == second_txid);
522                         assert!(seen_txids.insert(t));
523                 },
524                 _ => panic!("Unexpected event"),
525         }
526
527         match events[2] {
528                 TestConfirmableEvent::BestBlockUpdated(..) => {},
529                 _ => panic!("Unexpected event"),
530         }
531
532         match events[3] {
533                 TestConfirmableEvent::Confirmed(t, _, _) => {
534                         assert!(t == txid || t == second_txid);
535                         assert!(seen_txids.remove(&t));
536                 },
537                 _ => panic!("Unexpected event"),
538         }
539
540         match events[4] {
541                 TestConfirmableEvent::Confirmed(t, _, _) => {
542                         assert!(t == txid || t == second_txid);
543                         assert!(seen_txids.remove(&t));
544                 },
545                 _ => panic!("Unexpected event"),
546         }
547
548         assert_eq!(seen_txids.len(), 0);
549 }