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 ; 
@@ -11,7 +15,6 @@ use bitcoin::blockdata::constants::genesis_block;
1115use  bitcoin:: network:: constants:: Network ; 
1216use  electrsd:: bitcoind:: bitcoincore_rpc:: bitcoincore_rpc_json:: AddressType ; 
1317use  bitcoind:: bitcoincore_rpc:: RpcApi ; 
14- use  electrsd:: electrum_client:: ElectrumApi ; 
1518
1619use  std:: env; 
1720use  std:: sync:: Mutex ; 
@@ -51,6 +54,7 @@ pub fn generate_blocks_and_wait(bitcoind: &BitcoinD, electrsd: &ElectrsD, num: u
5154} 
5255
5356pub  fn  wait_for_block ( electrsd :  & ElectrsD ,  min_height :  usize )  { 
57+ 	use  electrsd:: electrum_client:: ElectrumApi ; 
5458	let  mut  header = match  electrsd. client . block_headers_subscribe_raw ( )  { 
5559		Ok ( header)  => header, 
5660		Err ( _)  => { 
@@ -411,3 +415,135 @@ async fn test_esplora_syncs() {
411415
412416	assert_eq ! ( seen_txids. len( ) ,  0 ) ; 
413417} 
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+ } 
0 commit comments