@@ -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 ) ,
@@ -450,7 +452,7 @@ where
450
452
451
453
state_lock. persistent . outputs . push ( output_info) ;
452
454
}
453
- self . persist_state ( & state_lock) . map_err ( |e| {
455
+ self . flush_state ( & mut state_lock) . map_err ( |e| {
454
456
log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
455
457
} )
456
458
}
@@ -478,7 +480,19 @@ where
478
480
return Ok ( ( ) ) ;
479
481
}
480
482
481
- let result = self . regenerate_and_broadcast_spend_if_necessary_internal ( ) . await ;
483
+ let result = {
484
+ self . regenerate_and_broadcast_spend_if_necessary_internal ( ) . await ?;
485
+
486
+ // If there is still dirty state, we need to persist it.
487
+ let mut sweeper_state = self . sweeper_state . lock ( ) . unwrap ( ) ;
488
+ if sweeper_state. dirty {
489
+ self . flush_state ( & mut sweeper_state) . map_err ( |e| {
490
+ log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
491
+ } )
492
+ } else {
493
+ Ok ( ( ) )
494
+ }
495
+ } ;
482
496
483
497
// Release the pending sweep flag again, regardless of result.
484
498
self . pending_sweep . store ( false , Ordering :: Release ) ;
@@ -572,7 +586,7 @@ where
572
586
output_info. status . broadcast ( cur_hash, cur_height, spending_tx. clone ( ) ) ;
573
587
}
574
588
575
- self . persist_state ( & sweeper_state) . map_err ( |e| {
589
+ self . flush_state ( & mut sweeper_state) . map_err ( |e| {
576
590
log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
577
591
} ) ?;
578
592
@@ -600,9 +614,12 @@ where
600
614
}
601
615
true
602
616
} ) ;
617
+
618
+ sweeper_state. dirty = true ;
603
619
}
604
620
605
- fn persist_state ( & self , sweeper_state : & SweeperState ) -> Result < ( ) , io:: Error > {
621
+ /// Flushes the current state to the persistence layer and marks the state as clean.
622
+ fn flush_state ( & self , sweeper_state : & mut SweeperState ) -> Result < ( ) , io:: Error > {
606
623
self . kv_store
607
624
. write (
608
625
OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE ,
@@ -621,6 +638,9 @@ where
621
638
) ;
622
639
e
623
640
} )
641
+ . map ( |_| {
642
+ sweeper_state. dirty = false ;
643
+ } )
624
644
}
625
645
626
646
fn spend_outputs (
@@ -653,13 +673,17 @@ where
653
673
}
654
674
}
655
675
}
676
+
677
+ sweeper_state. dirty = true ;
656
678
}
657
679
658
680
fn best_block_updated_internal (
659
681
& self , sweeper_state : & mut SweeperState , header : & Header , height : u32 ,
660
682
) {
661
683
sweeper_state. persistent . best_block = BestBlock :: new ( header. block_hash ( ) , height) ;
662
684
self . prune_confirmed_outputs ( sweeper_state) ;
685
+
686
+ sweeper_state. dirty = true ;
663
687
}
664
688
}
665
689
@@ -683,12 +707,8 @@ where
683
707
assert_eq ! ( state_lock. persistent. best_block. height, height - 1 ,
684
708
"Blocks must be connected in chain-order - the connected block height must be one greater than the previous height" ) ;
685
709
686
- self . transactions_confirmed_internal ( & mut * state_lock, header, txdata, height) ;
687
- self . best_block_updated_internal ( & mut * state_lock, header, height) ;
688
-
689
- let _ = self . persist_state ( & * state_lock) . map_err ( |e| {
690
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
691
- } ) ;
710
+ self . transactions_confirmed_internal ( & mut state_lock, header, txdata, height) ;
711
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
692
712
}
693
713
694
714
fn block_disconnected ( & self , header : & Header , height : u32 ) {
@@ -710,9 +730,7 @@ where
710
730
}
711
731
}
712
732
713
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
714
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
715
- } ) ;
733
+ state_lock. dirty = true ;
716
734
}
717
735
}
718
736
@@ -732,9 +750,6 @@ where
732
750
) {
733
751
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
734
752
self . transactions_confirmed_internal ( & mut * state_lock, header, txdata, height) ;
735
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
736
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
737
- } ) ;
738
753
}
739
754
740
755
fn transaction_unconfirmed ( & self , txid : & Txid ) {
@@ -757,18 +772,13 @@ where
757
772
. filter ( |o| o. status . confirmation_height ( ) >= Some ( unconf_height) )
758
773
. for_each ( |o| o. status . unconfirmed ( ) ) ;
759
774
760
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
761
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
762
- } ) ;
775
+ state_lock. dirty = true ;
763
776
}
764
777
}
765
778
766
779
fn best_block_updated ( & self , header : & Header , height : u32 ) {
767
780
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
768
- self . best_block_updated_internal ( & mut * state_lock, header, height) ;
769
- let _ = self . persist_state ( & * state_lock) . map_err ( |e| {
770
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
771
- } ) ;
781
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
772
782
}
773
783
774
784
fn get_relevant_txids ( & self ) -> Vec < ( Txid , u32 , Option < BlockHash > ) > {
@@ -797,6 +807,7 @@ where
797
807
#[ derive( Debug ) ]
798
808
struct SweeperState {
799
809
persistent : PersistentSweeperState ,
810
+ dirty : bool ,
800
811
}
801
812
802
813
#[ derive( Debug , Clone ) ]
@@ -861,7 +872,7 @@ where
861
872
}
862
873
}
863
874
864
- let sweeper_state = Mutex :: new ( SweeperState { persistent : state } ) ;
875
+ let sweeper_state = Mutex :: new ( SweeperState { persistent : state, dirty : false } ) ;
865
876
Ok ( Self {
866
877
sweeper_state,
867
878
pending_sweep : AtomicBool :: new ( false ) ,
@@ -910,7 +921,7 @@ where
910
921
}
911
922
}
912
923
913
- let sweeper_state = Mutex :: new ( SweeperState { persistent : state } ) ;
924
+ let sweeper_state = Mutex :: new ( SweeperState { persistent : state, dirty : false } ) ;
914
925
Ok ( (
915
926
best_block,
916
927
OutputSweeper {
0 commit comments