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