@@ -382,8 +382,10 @@ where
382
382
output_spender : O , change_destination_source : D , kv_store : K , logger : L ,
383
383
) -> Self {
384
384
let outputs = Vec :: new ( ) ;
385
- let sweeper_state =
386
- Mutex :: new ( SweeperState { persistent : PersistentSweeperState { outputs, best_block } } ) ;
385
+ let sweeper_state = Mutex :: new ( SweeperState {
386
+ persistent : PersistentSweeperState { outputs, best_block } ,
387
+ dirty : false ,
388
+ } ) ;
387
389
Self {
388
390
sweeper_state,
389
391
pending_sweep : AtomicBool :: new ( false ) ,
@@ -445,9 +447,9 @@ where
445
447
446
448
state_lock. persistent . outputs . push ( output_info) ;
447
449
}
448
- self . persist_state ( & state_lock) . map_err ( |e| {
449
- log_error ! ( self . logger , "Error persisting OutputSweeper: {:?}" , e ) ;
450
- } )
450
+ self . persist_state ( & state_lock. persistent )
451
+ . inspect ( |_| state_lock . dirty = false )
452
+ . map_err ( |e| log_error ! ( self . logger , "Error persisting OutputSweeper: {:?}" , e ) )
451
453
}
452
454
453
455
/// Returns a list of the currently tracked spendable outputs.
@@ -504,12 +506,21 @@ where
504
506
505
507
// See if there is anything to sweep before requesting a change address.
506
508
{
507
- let sweeper_state = self . sweeper_state . lock ( ) . unwrap ( ) ;
509
+ let mut sweeper_state = self . sweeper_state . lock ( ) . unwrap ( ) ;
508
510
509
511
let cur_height = sweeper_state. persistent . best_block . height ;
510
512
let has_respends =
511
513
sweeper_state. persistent . outputs . iter ( ) . any ( |o| filter_fn ( o, cur_height) ) ;
512
514
if !has_respends {
515
+ // If there is nothing to sweep, we still persist the state if it is dirty.
516
+ if sweeper_state. dirty {
517
+ self . persist_state ( & sweeper_state. persistent )
518
+ . inspect ( |_| sweeper_state. dirty = false )
519
+ . map_err ( |e| {
520
+ log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e)
521
+ } ) ?;
522
+ }
523
+
513
524
return Ok ( ( ) ) ;
514
525
}
515
526
}
@@ -534,7 +545,8 @@ where
534
545
. collect ( ) ;
535
546
536
547
if respend_descriptors. is_empty ( ) {
537
- // It could be that a tx confirmed and there is now nothing to sweep anymore.
548
+ // It could be that a tx confirmed and there is now nothing to sweep anymore. If there is dirty state,
549
+ // we'll persist it in the next cycle.
538
550
return Ok ( ( ) ) ;
539
551
}
540
552
@@ -567,9 +579,9 @@ where
567
579
output_info. status . broadcast ( cur_hash, cur_height, spending_tx. clone ( ) ) ;
568
580
}
569
581
570
- self . persist_state ( & sweeper_state) . map_err ( |e| {
571
- log_error ! ( self . logger , "Error persisting OutputSweeper: {:?}" , e ) ;
572
- } ) ?;
582
+ self . persist_state ( & sweeper_state. persistent )
583
+ . inspect ( |_| sweeper_state . dirty = false )
584
+ . map_err ( |e| log_error ! ( self . logger , "Error persisting OutputSweeper: {:?}" , e ) ) ?;
573
585
574
586
self . broadcaster . broadcast_transactions ( & [ & spending_tx] ) ;
575
587
}
@@ -595,6 +607,8 @@ where
595
607
}
596
608
true
597
609
} ) ;
610
+
611
+ sweeper_state. dirty = true ;
598
612
}
599
613
600
614
fn persist_state ( & self , sweeper_state : & PersistentSweeperState ) -> Result < ( ) , io:: Error > {
@@ -648,13 +662,17 @@ where
648
662
}
649
663
}
650
664
}
665
+
666
+ sweeper_state. dirty = true ;
651
667
}
652
668
653
669
fn best_block_updated_internal (
654
670
& self , sweeper_state : & mut SweeperState , header : & Header , height : u32 ,
655
671
) {
656
672
sweeper_state. persistent . best_block = BestBlock :: new ( header. block_hash ( ) , height) ;
657
673
self . prune_confirmed_outputs ( sweeper_state) ;
674
+
675
+ sweeper_state. dirty = true ;
658
676
}
659
677
}
660
678
@@ -678,12 +696,8 @@ where
678
696
assert_eq ! ( state_lock. persistent. best_block. height, height - 1 ,
679
697
"Blocks must be connected in chain-order - the connected block height must be one greater than the previous height" ) ;
680
698
681
- self . transactions_confirmed_internal ( & mut * state_lock, header, txdata, height) ;
682
- self . best_block_updated_internal ( & mut * state_lock, header, height) ;
683
-
684
- let _ = self . persist_state ( & * state_lock) . map_err ( |e| {
685
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
686
- } ) ;
699
+ self . transactions_confirmed_internal ( & mut state_lock, header, txdata, height) ;
700
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
687
701
}
688
702
689
703
fn block_disconnected ( & self , header : & Header , height : u32 ) {
@@ -705,9 +719,7 @@ where
705
719
}
706
720
}
707
721
708
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
709
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
710
- } ) ;
722
+ state_lock. dirty = true ;
711
723
}
712
724
}
713
725
@@ -727,9 +739,6 @@ where
727
739
) {
728
740
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
729
741
self . transactions_confirmed_internal ( & mut * state_lock, header, txdata, height) ;
730
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
731
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
732
- } ) ;
733
742
}
734
743
735
744
fn transaction_unconfirmed ( & self , txid : & Txid ) {
@@ -752,18 +761,13 @@ where
752
761
. filter ( |o| o. status . confirmation_height ( ) >= Some ( unconf_height) )
753
762
. for_each ( |o| o. status . unconfirmed ( ) ) ;
754
763
755
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
756
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
757
- } ) ;
764
+ state_lock. dirty = true ;
758
765
}
759
766
}
760
767
761
768
fn best_block_updated ( & self , header : & Header , height : u32 ) {
762
769
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
763
- self . best_block_updated_internal ( & mut * state_lock, header, height) ;
764
- let _ = self . persist_state ( & * state_lock) . map_err ( |e| {
765
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
766
- } ) ;
770
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
767
771
}
768
772
769
773
fn get_relevant_txids ( & self ) -> Vec < ( Txid , u32 , Option < BlockHash > ) > {
@@ -792,6 +796,7 @@ where
792
796
#[ derive( Debug ) ]
793
797
struct SweeperState {
794
798
persistent : PersistentSweeperState ,
799
+ dirty : bool ,
795
800
}
796
801
797
802
#[ derive( Debug , Clone ) ]
@@ -856,7 +861,7 @@ where
856
861
}
857
862
}
858
863
859
- let sweeper_state = Mutex :: new ( SweeperState { persistent : state } ) ;
864
+ let sweeper_state = Mutex :: new ( SweeperState { persistent : state, dirty : false } ) ;
860
865
Ok ( Self {
861
866
sweeper_state,
862
867
pending_sweep : AtomicBool :: new ( false ) ,
@@ -905,7 +910,7 @@ where
905
910
}
906
911
}
907
912
908
- let sweeper_state = Mutex :: new ( SweeperState { persistent : state } ) ;
913
+ let sweeper_state = Mutex :: new ( SweeperState { persistent : state, dirty : false } ) ;
909
914
Ok ( (
910
915
best_block,
911
916
OutputSweeper {
0 commit comments