1- #![ cfg( any( feature = "esplora-blocking" , feature = "esplora-async" ) ) ]
1+ #![ cfg( any( feature = "esplora-blocking" , feature = "esplora-async" , feature = "electrum" ) ) ]
2+
3+ #[ cfg( any( feature = "esplora-blocking" , feature = "esplora-async" ) ) ]
24use lightning_transaction_sync:: EsploraSyncClient ;
5+ #[ cfg( feature = "electrum" ) ]
6+ use lightning_transaction_sync:: ElectrumSyncClient ;
37use lightning:: chain:: { Confirm , Filter , WatchedOutput } ;
48use lightning:: chain:: transaction:: { OutPoint , TransactionData } ;
59use lightning:: util:: test_utils:: TestLogger ;
@@ -10,7 +14,6 @@ use bitcoin::blockdata::constants::genesis_block;
1014use bitcoin:: network:: constants:: Network ;
1115use electrsd:: bitcoind:: bitcoincore_rpc:: bitcoincore_rpc_json:: AddressType ;
1216use bitcoind:: bitcoincore_rpc:: RpcApi ;
13- use electrum_client:: ElectrumApi ;
1417
1518use std:: env;
1619use std:: sync:: Mutex ;
@@ -49,6 +52,7 @@ pub fn generate_blocks_and_wait(bitcoind: &BitcoinD, electrsd: &ElectrsD, num: u
4952}
5053
5154pub fn wait_for_block ( electrsd : & ElectrsD , min_height : usize ) {
55+ use electrsd:: electrum_client:: ElectrumApi ;
5256 let mut header = match electrsd. client . block_headers_subscribe ( ) {
5357 Ok ( header) => header,
5458 Err ( _) => {
@@ -391,3 +395,132 @@ async fn test_esplora_syncs() {
391395 _ => panic ! ( "Unexpected event" ) ,
392396 }
393397}
398+
399+ #[ test]
400+ #[ cfg( feature = "electrum" ) ]
401+ fn test_electrum_syncs ( ) {
402+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
403+ generate_blocks_and_wait ( & bitcoind, & electrsd, 101 ) ;
404+ let mut logger = TestLogger :: new ( ) ;
405+ let electrum_url = format ! ( "tcp://{}" , electrsd. electrum_url) ;
406+ let tx_sync = match ElectrumSyncClient :: new ( electrum_url, & mut logger) {
407+ Ok ( tx_sync) => tx_sync,
408+ Err ( e) => {
409+ eprintln ! ( "{:?}" , e) ;
410+ panic ! ( "{:?}" , e) ;
411+ }
412+ } ;
413+ let confirmable = TestConfirmable :: new ( ) ;
414+
415+ // Check we pick up on new best blocks
416+ assert_eq ! ( confirmable. best_block. lock( ) . unwrap( ) . 1 , 0 ) ;
417+
418+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
419+ assert_eq ! ( confirmable. best_block. lock( ) . unwrap( ) . 1 , 102 ) ;
420+
421+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
422+ assert_eq ! ( events. len( ) , 1 ) ;
423+
424+ // Check registered confirmed transactions are marked confirmed
425+ let new_address = bitcoind. client . get_new_address ( Some ( "test" ) ,
426+ Some ( AddressType :: Legacy ) ) . unwrap ( ) ;
427+ let txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None , None ,
428+ None , None , None , None ) . unwrap ( ) ;
429+ let second_txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None ,
430+ None , None , None , None , None ) . unwrap ( ) ;
431+ tx_sync. register_tx ( & txid, & new_address. script_pubkey ( ) ) ;
432+
433+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
434+
435+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
436+ assert_eq ! ( events. len( ) , 0 ) ;
437+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
438+ assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
439+
440+ generate_blocks_and_wait ( & bitcoind, & electrsd, 1 ) ;
441+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
442+
443+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
444+ assert_eq ! ( events. len( ) , 2 ) ;
445+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
446+ assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
447+
448+ // Now take a random output of the first transaction and check we'll confirm its spend.
449+ let tx_res = bitcoind. client . get_transaction ( & second_txid, None ) . unwrap ( ) ;
450+ let block_hash = tx_res. info . blockhash . unwrap ( ) ;
451+ let tx = tx_res. transaction ( ) . unwrap ( ) ;
452+ let prev_outpoint = tx. input . first ( ) . unwrap ( ) . previous_output ;
453+ let prev_tx = bitcoind. client . get_transaction ( & prev_outpoint. txid ,
454+ None ) . unwrap ( ) . transaction ( ) . unwrap ( ) ;
455+ let prev_script_pubkey = prev_tx. output [ prev_outpoint. vout as usize ] . script_pubkey . clone ( ) ;
456+ let output = WatchedOutput { block_hash : Some ( block_hash) , outpoint : OutPoint {
457+ txid : prev_outpoint. txid , index : prev_outpoint. vout as u16 } ,
458+ script_pubkey : prev_script_pubkey } ;
459+
460+ tx_sync. register_output ( output) ;
461+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
462+
463+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
464+ assert_eq ! ( events. len( ) , 1 ) ;
465+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ;
466+ assert_eq ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . len( ) , 2 ) ;
467+ assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
468+
469+ // Check previously confirmed transactions are marked unconfirmed when they are reorged.
470+ let best_block_hash = bitcoind. client . get_best_block_hash ( ) . unwrap ( ) ;
471+ bitcoind. client . invalidate_block ( & best_block_hash) . unwrap ( ) ;
472+
473+ // We're getting back to the previous height with a new tip, but best block shouldn't change.
474+ generate_blocks_and_wait ( & bitcoind, & electrsd, 1 ) ;
475+ assert_ne ! ( bitcoind. client. get_best_block_hash( ) . unwrap( ) , best_block_hash) ;
476+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
477+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
478+ assert_eq ! ( events. len( ) , 0 ) ;
479+
480+ // Now we're surpassing previous height, getting new tip.
481+ generate_blocks_and_wait ( & bitcoind, & electrsd, 1 ) ;
482+ assert_ne ! ( bitcoind. client. get_best_block_hash( ) . unwrap( ) , best_block_hash) ;
483+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
484+
485+ // Transactions still confirmed but under new tip.
486+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
487+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ;
488+ assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
489+
490+ // Check we got unconfirmed, then reconfirmed in the meantime.
491+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
492+ assert_eq ! ( events. len( ) , 5 ) ;
493+
494+ match events[ 0 ] {
495+ TestConfirmableEvent :: Unconfirmed ( t) => {
496+ assert ! ( t == txid || t == second_txid) ;
497+ } ,
498+ _ => panic ! ( "Unexpected event" ) ,
499+ }
500+
501+ match events[ 1 ] {
502+ TestConfirmableEvent :: Unconfirmed ( t) => {
503+ assert ! ( t == txid || t == second_txid) ;
504+ } ,
505+ _ => panic ! ( "Unexpected event" ) ,
506+ }
507+
508+ match events[ 2 ] {
509+ TestConfirmableEvent :: BestBlockUpdated ( ..) => { } ,
510+ _ => panic ! ( "Unexpected event" ) ,
511+ }
512+
513+ match events[ 3 ] {
514+ TestConfirmableEvent :: Confirmed ( t, _, _) => {
515+ assert ! ( t == txid || t == second_txid) ;
516+ } ,
517+ _ => panic ! ( "Unexpected event" ) ,
518+ }
519+
520+ match events[ 4 ] {
521+ TestConfirmableEvent :: Confirmed ( t, _, _) => {
522+ assert ! ( t == txid || t == second_txid) ;
523+ } ,
524+ _ => panic ! ( "Unexpected event" ) ,
525+ }
526+ }
0 commit comments