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 ( _)  => { 
@@ -379,3 +383,126 @@ async fn test_esplora_syncs() {
379383		_ => panic ! ( "Unexpected event" ) , 
380384	} 
381385} 
386+ 
387+ #[ test]  
388+ #[ cfg( feature = "electrum" ) ]  
389+ fn  test_electrum_syncs ( )  { 
390+ 	let  ( bitcoind,  electrsd)  = setup_bitcoind_and_electrsd ( ) ; 
391+ 	generate_blocks_and_wait ( & bitcoind,  & electrsd,  101 ) ; 
392+ 	let  mut  logger = TestLogger :: new ( ) ; 
393+ 	let  electrum_url = format ! ( "tcp://{}" ,  electrsd. electrum_url) ; 
394+ 	let  tx_sync = match  ElectrumSyncClient :: new ( electrum_url,  & mut  logger)  { 
395+ 		Ok ( tx_sync)  => tx_sync, 
396+ 		Err ( e)  => { 
397+ 			eprintln ! ( "{:?}" ,  e) ; 
398+ 			panic ! ( "{:?}" ,  e) ; 
399+ 		} 
400+ 	} ; 
401+ 	let  confirmable = TestConfirmable :: new ( ) ; 
402+ 
403+ 	// Check we pick up on new best blocks 
404+ 	assert_eq ! ( confirmable. best_block. lock( ) . unwrap( ) . 1 ,  0 ) ; 
405+ 
406+ 	tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ; 
407+ 	assert_eq ! ( confirmable. best_block. lock( ) . unwrap( ) . 1 ,  102 ) ; 
408+ 
409+ 	let  events = std:: mem:: take ( & mut  * confirmable. events . lock ( ) . unwrap ( ) ) ; 
410+ 	assert_eq ! ( events. len( ) ,  1 ) ; 
411+ 
412+ 	// Check registered confirmed transactions are marked confirmed 
413+ 	let  new_address = bitcoind. client . get_new_address ( Some ( "test" ) ,  Some ( AddressType :: Legacy ) ) . unwrap ( ) ; 
414+ 	let  txid = bitcoind. client . send_to_address ( & new_address,  Amount :: from_sat ( 5000 ) ,  None ,  None ,  None ,  None ,  None ,  None ) . unwrap ( ) ; 
415+ 	let  second_txid = bitcoind. client . send_to_address ( & new_address,  Amount :: from_sat ( 5000 ) ,  None ,  None ,  None ,  None ,  None ,  None ) . unwrap ( ) ; 
416+ 	tx_sync. register_tx ( & txid,  & new_address. script_pubkey ( ) ) ; 
417+ 
418+ 	tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ; 
419+ 
420+ 	let  events = std:: mem:: take ( & mut  * confirmable. events . lock ( ) . unwrap ( ) ) ; 
421+ 	assert_eq ! ( events. len( ) ,  0 ) ; 
422+ 	assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ; 
423+ 	assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ; 
424+ 
425+ 	generate_blocks_and_wait ( & bitcoind,  & electrsd,  1 ) ; 
426+ 	tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ; 
427+ 
428+ 	let  events = std:: mem:: take ( & mut  * confirmable. events . lock ( ) . unwrap ( ) ) ; 
429+ 	assert_eq ! ( events. len( ) ,  2 ) ; 
430+ 	assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ; 
431+ 	assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ; 
432+ 
433+ 	// Now take a random output of the first transaction and check we'll confirm its spend. 
434+ 	let  tx_res = bitcoind. client . get_transaction ( & second_txid,  None ) . unwrap ( ) ; 
435+ 	let  block_hash = tx_res. info . blockhash . unwrap ( ) ; 
436+ 	let  tx = tx_res. transaction ( ) . unwrap ( ) ; 
437+ 	let  prev_outpoint = tx. input . first ( ) . unwrap ( ) . previous_output ; 
438+ 	let  prev_tx = bitcoind. client . get_transaction ( & prev_outpoint. txid ,  None ) . unwrap ( ) . transaction ( ) . unwrap ( ) ; 
439+ 	let  prev_script_pubkey = prev_tx. output [ prev_outpoint. vout  as  usize ] . script_pubkey . clone ( ) ; 
440+ 	let  output = WatchedOutput  {  block_hash :  Some ( block_hash) ,  outpoint :  OutPoint  {  txid :  prev_outpoint. txid ,  index :  prev_outpoint. vout  as  u16  } ,  script_pubkey :  prev_script_pubkey } ; 
441+ 
442+ 	tx_sync. register_output ( output) ; 
443+ 	tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ; 
444+ 
445+ 	let  events = std:: mem:: take ( & mut  * confirmable. events . lock ( ) . unwrap ( ) ) ; 
446+ 	assert_eq ! ( events. len( ) ,  1 ) ; 
447+ 	assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ; 
448+ 	assert_eq ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . len( ) ,  2 ) ; 
449+ 	assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ; 
450+ 
451+ 	// Check previously confirmed transactions are marked unconfirmed when they are reorged. 
452+ 	let  best_block_hash = bitcoind. client . get_best_block_hash ( ) . unwrap ( ) ; 
453+ 	bitcoind. client . invalidate_block ( & best_block_hash) . unwrap ( ) ; 
454+ 
455+ 	// We're getting back to the previous height with a new tip, but best block shouldn't change. 
456+ 	generate_blocks_and_wait ( & bitcoind,  & electrsd,  1 ) ; 
457+ 	assert_ne ! ( bitcoind. client. get_best_block_hash( ) . unwrap( ) ,  best_block_hash) ; 
458+ 	tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ; 
459+ 	let  events = std:: mem:: take ( & mut  * confirmable. events . lock ( ) . unwrap ( ) ) ; 
460+ 	assert_eq ! ( events. len( ) ,  0 ) ; 
461+ 
462+ 	// Now we're surpassing previous height, getting new tip. 
463+ 	generate_blocks_and_wait ( & bitcoind,  & electrsd,  1 ) ; 
464+ 	assert_ne ! ( bitcoind. client. get_best_block_hash( ) . unwrap( ) ,  best_block_hash) ; 
465+ 	tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ; 
466+ 
467+ 	// Transactions still confirmed but under new tip. 
468+ 	assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ; 
469+ 	assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & second_txid) ) ; 
470+ 	assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ; 
471+ 
472+ 	// Check we got unconfirmed, then reconfirmed in the meantime. 
473+ 	let  events = std:: mem:: take ( & mut  * confirmable. events . lock ( ) . unwrap ( ) ) ; 
474+ 	assert_eq ! ( events. len( ) ,  5 ) ; 
475+ 
476+ 	match  events[ 0 ]  { 
477+ 		TestConfirmableEvent :: Unconfirmed ( t)  => { 
478+ 			assert ! ( t == txid || t == second_txid) ; 
479+ 		} , 
480+ 		_ => panic ! ( "Unexpected event" ) , 
481+ 	} 
482+ 
483+ 	match  events[ 1 ]  { 
484+ 		TestConfirmableEvent :: Unconfirmed ( t)  => { 
485+ 			assert ! ( t == txid || t == second_txid) ; 
486+ 		} , 
487+ 		_ => panic ! ( "Unexpected event" ) , 
488+ 	} 
489+ 
490+ 	match  events[ 2 ]  { 
491+ 		TestConfirmableEvent :: BestBlockUpdated ( ..)  => { } , 
492+ 		_ => panic ! ( "Unexpected event" ) , 
493+ 	} 
494+ 
495+ 	match  events[ 3 ]  { 
496+ 		TestConfirmableEvent :: Confirmed ( t,  _,  _)  => { 
497+ 			assert ! ( t == txid || t == second_txid) ; 
498+ 		} , 
499+ 		_ => panic ! ( "Unexpected event" ) , 
500+ 	} 
501+ 
502+ 	match  events[ 4 ]  { 
503+ 		TestConfirmableEvent :: Confirmed ( t,  _,  _)  => { 
504+ 			assert ! ( t == txid || t == second_txid) ; 
505+ 		} , 
506+ 		_ => panic ! ( "Unexpected event" ) , 
507+ 	} 
508+ } 
0 commit comments