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" ) ) ]
2
4
use lightning_transaction_sync:: EsploraSyncClient ;
5
+ #[ cfg( feature = "electrum" ) ]
6
+ use lightning_transaction_sync:: ElectrumSyncClient ;
3
7
use lightning:: chain:: { Confirm , Filter , WatchedOutput } ;
4
8
use lightning:: chain:: transaction:: { OutPoint , TransactionData } ;
5
9
use lightning:: util:: test_utils:: TestLogger ;
@@ -10,7 +14,6 @@ use bitcoin::blockdata::constants::genesis_block;
10
14
use bitcoin:: network:: constants:: Network ;
11
15
use electrsd:: bitcoind:: bitcoincore_rpc:: bitcoincore_rpc_json:: AddressType ;
12
16
use bitcoind:: bitcoincore_rpc:: RpcApi ;
13
- use electrum_client:: ElectrumApi ;
14
17
15
18
use std:: env;
16
19
use std:: sync:: Mutex ;
@@ -49,6 +52,7 @@ pub fn generate_blocks_and_wait(bitcoind: &BitcoinD, electrsd: &ElectrsD, num: u
49
52
}
50
53
51
54
pub fn wait_for_block ( electrsd : & ElectrsD , min_height : usize ) {
55
+ use electrsd:: electrum_client:: ElectrumApi ;
52
56
let mut header = match electrsd. client . block_headers_subscribe ( ) {
53
57
Ok ( header) => header,
54
58
Err ( _) => {
@@ -407,3 +411,132 @@ async fn test_esplora_syncs() {
407
411
408
412
assert_eq ! ( seen_txids. len( ) , 0 ) ;
409
413
}
414
+
415
+ #[ test]
416
+ #[ cfg( feature = "electrum" ) ]
417
+ fn test_electrum_syncs ( ) {
418
+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
419
+ generate_blocks_and_wait ( & bitcoind, & electrsd, 101 ) ;
420
+ let mut logger = TestLogger :: new ( ) ;
421
+ let electrum_url = format ! ( "tcp://{}" , electrsd. electrum_url) ;
422
+ let tx_sync = match ElectrumSyncClient :: new ( electrum_url, & mut logger) {
423
+ Ok ( tx_sync) => tx_sync,
424
+ Err ( e) => {
425
+ eprintln ! ( "{:?}" , e) ;
426
+ panic ! ( "{:?}" , e) ;
427
+ }
428
+ } ;
429
+ let confirmable = TestConfirmable :: new ( ) ;
430
+
431
+ // Check we pick up on new best blocks
432
+ assert_eq ! ( confirmable. best_block. lock( ) . unwrap( ) . 1 , 0 ) ;
433
+
434
+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
435
+ assert_eq ! ( confirmable. best_block. lock( ) . unwrap( ) . 1 , 102 ) ;
436
+
437
+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
438
+ assert_eq ! ( events. len( ) , 1 ) ;
439
+
440
+ // Check registered confirmed transactions are marked confirmed
441
+ let new_address = bitcoind. client . get_new_address ( Some ( "test" ) ,
442
+ Some ( AddressType :: Legacy ) ) . unwrap ( ) ;
443
+ let txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None , None ,
444
+ None , None , None , None ) . unwrap ( ) ;
445
+ let second_txid = bitcoind. client . send_to_address ( & new_address, Amount :: from_sat ( 5000 ) , None ,
446
+ None , None , None , None , None ) . unwrap ( ) ;
447
+ tx_sync. register_tx ( & txid, & new_address. script_pubkey ( ) ) ;
448
+
449
+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
450
+
451
+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
452
+ assert_eq ! ( events. len( ) , 0 ) ;
453
+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
454
+ assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
455
+
456
+ generate_blocks_and_wait ( & bitcoind, & electrsd, 1 ) ;
457
+ tx_sync. sync ( vec ! [ & confirmable] ) . unwrap ( ) ;
458
+
459
+ let events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
460
+ assert_eq ! ( events. len( ) , 2 ) ;
461
+ assert ! ( confirmable. confirmed_txs. lock( ) . unwrap( ) . contains_key( & txid) ) ;
462
+ assert ! ( confirmable. unconfirmed_txs. lock( ) . unwrap( ) . is_empty( ) ) ;
463
+
464
+ // Now take a random output of the first transaction and check we'll confirm its spend.
465
+ let tx_res = bitcoind. client . get_transaction ( & second_txid, None ) . unwrap ( ) ;
466
+ let block_hash = tx_res. info . blockhash . unwrap ( ) ;
467
+ let tx = tx_res. transaction ( ) . unwrap ( ) ;
468
+ let prev_outpoint = tx. input . first ( ) . unwrap ( ) . previous_output ;
469
+ let prev_tx = bitcoind. client . get_transaction ( & prev_outpoint. txid ,
470
+ None ) . unwrap ( ) . transaction ( ) . unwrap ( ) ;
471
+ let prev_script_pubkey = prev_tx. output [ prev_outpoint. vout as usize ] . script_pubkey . clone ( ) ;
472
+ let output = WatchedOutput { block_hash : Some ( block_hash) , outpoint : OutPoint {
473
+ txid : prev_outpoint. txid , index : prev_outpoint. vout as u16 } ,
474
+ script_pubkey : prev_script_pubkey } ;
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 events = std:: mem:: take ( & mut * confirmable. events . lock ( ) . unwrap ( ) ) ;
508
+ assert_eq ! ( events. len( ) , 5 ) ;
509
+
510
+ match events[ 0 ] {
511
+ TestConfirmableEvent :: Unconfirmed ( t) => {
512
+ assert ! ( t == txid || t == second_txid) ;
513
+ } ,
514
+ _ => panic ! ( "Unexpected event" ) ,
515
+ }
516
+
517
+ match events[ 1 ] {
518
+ TestConfirmableEvent :: Unconfirmed ( t) => {
519
+ assert ! ( t == txid || t == second_txid) ;
520
+ } ,
521
+ _ => panic ! ( "Unexpected event" ) ,
522
+ }
523
+
524
+ match events[ 2 ] {
525
+ TestConfirmableEvent :: BestBlockUpdated ( ..) => { } ,
526
+ _ => panic ! ( "Unexpected event" ) ,
527
+ }
528
+
529
+ match events[ 3 ] {
530
+ TestConfirmableEvent :: Confirmed ( t, _, _) => {
531
+ assert ! ( t == txid || t == second_txid) ;
532
+ } ,
533
+ _ => panic ! ( "Unexpected event" ) ,
534
+ }
535
+
536
+ match events[ 4 ] {
537
+ TestConfirmableEvent :: Confirmed ( t, _, _) => {
538
+ assert ! ( t == txid || t == second_txid) ;
539
+ } ,
540
+ _ => panic ! ( "Unexpected event" ) ,
541
+ }
542
+ }
0 commit comments