@@ -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 ) ;
@@ -571,7 +585,7 @@ where
571
585
output_info. status . broadcast ( cur_hash, cur_height, spending_tx. clone ( ) ) ;
572
586
}
573
587
574
- self . persist_state ( & sweeper_state) . map_err ( |e| {
588
+ self . flush_state ( & mut sweeper_state) . map_err ( |e| {
575
589
log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
576
590
} ) ?;
577
591
@@ -599,9 +613,12 @@ where
599
613
}
600
614
true
601
615
} ) ;
616
+
617
+ sweeper_state. dirty = true ;
602
618
}
603
619
604
- fn persist_state ( & self , sweeper_state : & SweeperState ) -> Result < ( ) , io:: Error > {
620
+ /// Flushes the current state to the persistence layer and marks the state as clean.
621
+ fn flush_state ( & self , sweeper_state : & mut SweeperState ) -> Result < ( ) , io:: Error > {
605
622
self . kv_store
606
623
. write (
607
624
OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE ,
@@ -620,6 +637,9 @@ where
620
637
) ;
621
638
e
622
639
} )
640
+ . map ( |_| {
641
+ sweeper_state. dirty = false ;
642
+ } )
623
643
}
624
644
625
645
fn spend_outputs (
@@ -652,13 +672,17 @@ where
652
672
}
653
673
}
654
674
}
675
+
676
+ sweeper_state. dirty = true ;
655
677
}
656
678
657
679
fn best_block_updated_internal (
658
680
& self , sweeper_state : & mut SweeperState , header : & Header , height : u32 ,
659
681
) {
660
682
sweeper_state. persistent . best_block = BestBlock :: new ( header. block_hash ( ) , height) ;
661
683
self . prune_confirmed_outputs ( sweeper_state) ;
684
+
685
+ sweeper_state. dirty = true ;
662
686
}
663
687
}
664
688
@@ -682,12 +706,8 @@ where
682
706
assert_eq ! ( state_lock. persistent. best_block. height, height - 1 ,
683
707
"Blocks must be connected in chain-order - the connected block height must be one greater than the previous height" ) ;
684
708
685
- self . transactions_confirmed_internal ( & mut * state_lock, header, txdata, height) ;
686
- self . best_block_updated_internal ( & mut * state_lock, header, height) ;
687
-
688
- let _ = self . persist_state ( & * state_lock) . map_err ( |e| {
689
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
690
- } ) ;
709
+ self . transactions_confirmed_internal ( & mut state_lock, header, txdata, height) ;
710
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
691
711
}
692
712
693
713
fn block_disconnected ( & self , header : & Header , height : u32 ) {
@@ -709,9 +729,7 @@ where
709
729
}
710
730
}
711
731
712
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
713
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
714
- } ) ;
732
+ state_lock. dirty = true ;
715
733
}
716
734
}
717
735
@@ -731,9 +749,6 @@ where
731
749
) {
732
750
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
733
751
self . transactions_confirmed_internal ( & mut * state_lock, header, txdata, height) ;
734
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
735
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
736
- } ) ;
737
752
}
738
753
739
754
fn transaction_unconfirmed ( & self , txid : & Txid ) {
@@ -756,18 +771,13 @@ where
756
771
. filter ( |o| o. status . confirmation_height ( ) >= Some ( unconf_height) )
757
772
. for_each ( |o| o. status . unconfirmed ( ) ) ;
758
773
759
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
760
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
761
- } ) ;
774
+ state_lock. dirty = true ;
762
775
}
763
776
}
764
777
765
778
fn best_block_updated ( & self , header : & Header , height : u32 ) {
766
779
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
767
- self . best_block_updated_internal ( & mut * state_lock, header, height) ;
768
- let _ = self . persist_state ( & * state_lock) . map_err ( |e| {
769
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
770
- } ) ;
780
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
771
781
}
772
782
773
783
fn get_relevant_txids ( & self ) -> Vec < ( Txid , u32 , Option < BlockHash > ) > {
@@ -796,6 +806,7 @@ where
796
806
#[ derive( Debug ) ]
797
807
struct SweeperState {
798
808
persistent : PersistentSweeperState ,
809
+ dirty : bool ,
799
810
}
800
811
801
812
#[ derive( Debug , Clone ) ]
@@ -860,7 +871,7 @@ where
860
871
}
861
872
}
862
873
863
- let sweeper_state = Mutex :: new ( SweeperState { persistent : state } ) ;
874
+ let sweeper_state = Mutex :: new ( SweeperState { persistent : state, dirty : false } ) ;
864
875
Ok ( Self {
865
876
sweeper_state,
866
877
pending_sweep : AtomicBool :: new ( false ) ,
@@ -909,7 +920,7 @@ where
909
920
}
910
921
}
911
922
912
- let sweeper_state = Mutex :: new ( SweeperState { persistent : state } ) ;
923
+ let sweeper_state = Mutex :: new ( SweeperState { persistent : state, dirty : false } ) ;
913
924
Ok ( (
914
925
best_block,
915
926
OutputSweeper {
0 commit comments