@@ -382,7 +382,7 @@ 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 = Mutex :: new ( SweeperState { outputs, best_block } ) ;
385
+ let sweeper_state = Mutex :: new ( SweeperState { outputs, best_block, dirty : false } ) ;
386
386
Self {
387
387
sweeper_state,
388
388
pending_sweep : AtomicBool :: new ( false ) ,
@@ -446,7 +446,10 @@ where
446
446
}
447
447
self . persist_state ( & * state_lock) . map_err ( |e| {
448
448
log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
449
- } )
449
+ } ) ?;
450
+ state_lock. dirty = false ;
451
+
452
+ Ok ( ( ) )
450
453
}
451
454
452
455
/// Returns a list of the currently tracked spendable outputs.
@@ -503,11 +506,19 @@ where
503
506
504
507
// See if there is anything to sweep before requesting a change address.
505
508
{
506
- let sweeper_state = self . sweeper_state . lock ( ) . unwrap ( ) ;
509
+ let mut sweeper_state = self . sweeper_state . lock ( ) . unwrap ( ) ;
507
510
508
511
let cur_height = sweeper_state. best_block . height ;
509
512
let has_respends = sweeper_state. outputs . iter ( ) . any ( |o| filter_fn ( o, cur_height) ) ;
510
513
if !has_respends {
514
+ // If there is nothing to sweep, we still persist the state if it is dirty.
515
+ if sweeper_state. dirty {
516
+ self . persist_state ( & sweeper_state) . map_err ( |e| {
517
+ log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
518
+ } ) ?;
519
+ sweeper_state. dirty = false ;
520
+ }
521
+
511
522
return Ok ( ( ) ) ;
512
523
}
513
524
}
@@ -531,7 +542,15 @@ where
531
542
. collect ( ) ;
532
543
533
544
if respend_descriptors. is_empty ( ) {
534
- // It could be that a tx confirmed and there is now nothing to sweep anymore.
545
+ // It could be that a tx confirmed and there is now nothing to sweep anymore. We still persist the state
546
+ // if it is dirty.
547
+ if sweeper_state. dirty {
548
+ self . persist_state ( & sweeper_state) . map_err ( |e| {
549
+ log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
550
+ } ) ?;
551
+ sweeper_state. dirty = false ;
552
+ }
553
+
535
554
return Ok ( ( ) ) ;
536
555
}
537
556
@@ -563,6 +582,7 @@ where
563
582
self . persist_state ( & sweeper_state) . map_err ( |e| {
564
583
log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
565
584
} ) ?;
585
+ sweeper_state. dirty = false ;
566
586
567
587
self . broadcaster . broadcast_transactions ( & [ & spending_tx] ) ;
568
588
}
@@ -588,6 +608,8 @@ where
588
608
}
589
609
true
590
610
} ) ;
611
+
612
+ sweeper_state. dirty = true ;
591
613
}
592
614
593
615
fn persist_state ( & self , sweeper_state : & SweeperState ) -> Result < ( ) , io:: Error > {
@@ -641,13 +663,17 @@ where
641
663
}
642
664
}
643
665
}
666
+
667
+ sweeper_state. dirty = true ;
644
668
}
645
669
646
670
fn best_block_updated_internal (
647
671
& self , sweeper_state : & mut SweeperState , header : & Header , height : u32 ,
648
672
) {
649
673
sweeper_state. best_block = BestBlock :: new ( header. block_hash ( ) , height) ;
650
674
self . prune_confirmed_outputs ( sweeper_state) ;
675
+
676
+ sweeper_state. dirty = true ;
651
677
}
652
678
}
653
679
@@ -671,12 +697,8 @@ where
671
697
assert_eq ! ( state_lock. best_block. height, height - 1 ,
672
698
"Blocks must be connected in chain-order - the connected block height must be one greater than the previous height" ) ;
673
699
674
- self . transactions_confirmed_internal ( & mut * state_lock, header, txdata, height) ;
675
- self . best_block_updated_internal ( & mut * state_lock, header, height) ;
676
-
677
- let _ = self . persist_state ( & * state_lock) . map_err ( |e| {
678
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
679
- } ) ;
700
+ self . transactions_confirmed_internal ( & mut state_lock, header, txdata, height) ;
701
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
680
702
}
681
703
682
704
fn block_disconnected ( & self , header : & Header , height : u32 ) {
@@ -698,9 +720,7 @@ where
698
720
}
699
721
}
700
722
701
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
702
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
703
- } ) ;
723
+ state_lock. dirty = true ;
704
724
}
705
725
}
706
726
@@ -720,9 +740,6 @@ where
720
740
) {
721
741
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
722
742
self . transactions_confirmed_internal ( & mut * state_lock, header, txdata, height) ;
723
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
724
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
725
- } ) ;
726
743
}
727
744
728
745
fn transaction_unconfirmed ( & self , txid : & Txid ) {
@@ -743,18 +760,13 @@ where
743
760
. filter ( |o| o. status . confirmation_height ( ) >= Some ( unconf_height) )
744
761
. for_each ( |o| o. status . unconfirmed ( ) ) ;
745
762
746
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
747
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
748
- } ) ;
763
+ state_lock. dirty = true ;
749
764
}
750
765
}
751
766
752
767
fn best_block_updated ( & self , header : & Header , height : u32 ) {
753
768
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
754
- self . best_block_updated_internal ( & mut * state_lock, header, height) ;
755
- let _ = self . persist_state ( & * state_lock) . map_err ( |e| {
756
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
757
- } ) ;
769
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
758
770
}
759
771
760
772
fn get_relevant_txids ( & self ) -> Vec < ( Txid , u32 , Option < BlockHash > ) > {
@@ -783,11 +795,13 @@ where
783
795
struct SweeperState {
784
796
outputs : Vec < TrackedSpendableOutput > ,
785
797
best_block : BestBlock ,
798
+ dirty : bool ,
786
799
}
787
800
788
801
impl_writeable_tlv_based ! ( SweeperState , {
789
802
( 0 , outputs, required_vec) ,
790
803
( 2 , best_block, required) ,
804
+ ( _unused, dirty, ( static_value, false ) ) ,
791
805
} ) ;
792
806
793
807
/// A `enum` signalling to the [`OutputSweeper`] that it should delay spending an output until a
0 commit comments