@@ -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,7 +447,7 @@ where
445
447
446
448
state_lock. persistent . outputs . push ( output_info) ;
447
449
}
448
- self . persist_state ( & state_lock) . map_err ( |e| {
450
+ self . flush_state ( & mut state_lock) . map_err ( |e| {
449
451
log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
450
452
} )
451
453
}
@@ -473,7 +475,19 @@ where
473
475
return Ok ( ( ) ) ;
474
476
}
475
477
476
- let result = self . regenerate_and_broadcast_spend_if_necessary_internal ( ) . await ;
478
+ let result = {
479
+ self . regenerate_and_broadcast_spend_if_necessary_internal ( ) . await ?;
480
+
481
+ // If there is still dirty state, we need to persist it.
482
+ let mut sweeper_state = self . sweeper_state . lock ( ) . unwrap ( ) ;
483
+ if sweeper_state. dirty {
484
+ self . flush_state ( & mut sweeper_state) . map_err ( |e| {
485
+ log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
486
+ } )
487
+ } else {
488
+ Ok ( ( ) )
489
+ }
490
+ } ;
477
491
478
492
// Release the pending sweep flag again, regardless of result.
479
493
self . pending_sweep . store ( false , Ordering :: Release ) ;
@@ -567,7 +581,7 @@ where
567
581
output_info. status . broadcast ( cur_hash, cur_height, spending_tx. clone ( ) ) ;
568
582
}
569
583
570
- self . persist_state ( & sweeper_state) . map_err ( |e| {
584
+ self . flush_state ( & mut sweeper_state) . map_err ( |e| {
571
585
log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
572
586
} ) ?;
573
587
@@ -595,9 +609,12 @@ where
595
609
}
596
610
true
597
611
} ) ;
612
+
613
+ sweeper_state. dirty = true ;
598
614
}
599
615
600
- fn persist_state ( & self , sweeper_state : & SweeperState ) -> Result < ( ) , io:: Error > {
616
+ /// Flushes the current state to the persistence layer and marks the state as clean.
617
+ fn flush_state ( & self , sweeper_state : & mut SweeperState ) -> Result < ( ) , io:: Error > {
601
618
self . kv_store
602
619
. write (
603
620
OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE ,
@@ -616,6 +633,9 @@ where
616
633
) ;
617
634
e
618
635
} )
636
+ . map ( |_| {
637
+ sweeper_state. dirty = false ;
638
+ } )
619
639
}
620
640
621
641
fn spend_outputs (
@@ -648,13 +668,17 @@ where
648
668
}
649
669
}
650
670
}
671
+
672
+ sweeper_state. dirty = true ;
651
673
}
652
674
653
675
fn best_block_updated_internal (
654
676
& self , sweeper_state : & mut SweeperState , header : & Header , height : u32 ,
655
677
) {
656
678
sweeper_state. persistent . best_block = BestBlock :: new ( header. block_hash ( ) , height) ;
657
679
self . prune_confirmed_outputs ( sweeper_state) ;
680
+
681
+ sweeper_state. dirty = true ;
658
682
}
659
683
}
660
684
@@ -678,12 +702,8 @@ where
678
702
assert_eq ! ( state_lock. persistent. best_block. height, height - 1 ,
679
703
"Blocks must be connected in chain-order - the connected block height must be one greater than the previous height" ) ;
680
704
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
- } ) ;
705
+ self . transactions_confirmed_internal ( & mut state_lock, header, txdata, height) ;
706
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
687
707
}
688
708
689
709
fn block_disconnected ( & self , header : & Header , height : u32 ) {
@@ -705,9 +725,7 @@ where
705
725
}
706
726
}
707
727
708
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
709
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
710
- } ) ;
728
+ state_lock. dirty = true ;
711
729
}
712
730
}
713
731
@@ -727,9 +745,6 @@ where
727
745
) {
728
746
let mut state_lock = self . sweeper_state . lock ( ) . unwrap ( ) ;
729
747
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
748
}
734
749
735
750
fn transaction_unconfirmed ( & self , txid : & Txid ) {
@@ -752,18 +767,13 @@ where
752
767
. filter ( |o| o. status . confirmation_height ( ) >= Some ( unconf_height) )
753
768
. for_each ( |o| o. status . unconfirmed ( ) ) ;
754
769
755
- self . persist_state ( & * state_lock) . unwrap_or_else ( |e| {
756
- log_error ! ( self . logger, "Error persisting OutputSweeper: {:?}" , e) ;
757
- } ) ;
770
+ state_lock. dirty = true ;
758
771
}
759
772
}
760
773
761
774
fn best_block_updated ( & self , header : & Header , height : u32 ) {
762
775
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
- } ) ;
776
+ self . best_block_updated_internal ( & mut state_lock, header, height) ;
767
777
}
768
778
769
779
fn get_relevant_txids ( & self ) -> Vec < ( Txid , u32 , Option < BlockHash > ) > {
@@ -792,6 +802,7 @@ where
792
802
#[ derive( Debug ) ]
793
803
struct SweeperState {
794
804
persistent : PersistentSweeperState ,
805
+ dirty : bool ,
795
806
}
796
807
797
808
#[ derive( Debug , Clone ) ]
@@ -856,7 +867,7 @@ where
856
867
}
857
868
}
858
869
859
- let sweeper_state = Mutex :: new ( SweeperState { persistent : state } ) ;
870
+ let sweeper_state = Mutex :: new ( SweeperState { persistent : state, dirty : false } ) ;
860
871
Ok ( Self {
861
872
sweeper_state,
862
873
pending_sweep : AtomicBool :: new ( false ) ,
@@ -905,7 +916,7 @@ where
905
916
}
906
917
}
907
918
908
- let sweeper_state = Mutex :: new ( SweeperState { persistent : state } ) ;
919
+ let sweeper_state = Mutex :: new ( SweeperState { persistent : state, dirty : false } ) ;
909
920
Ok ( (
910
921
best_block,
911
922
OutputSweeper {
0 commit comments