@@ -52,6 +52,7 @@ use crate::error::{BlockError, Error};
5252use crate :: transaction:: { SignedTransaction , UnverifiedTransaction } ;
5353use crate :: views:: BlockView ;
5454use crate :: BlockId ;
55+ use std:: cell:: Cell ;
5556
5657type SpawnResult = (
5758 JoinHandle < ( ) > ,
@@ -74,9 +75,7 @@ struct Worker {
7475 /// Consensus step.
7576 step : TendermintState ,
7677 /// Record current round's received votes as bit set
77- votes_received : BitSet ,
78- /// The votes_received field is changed after last state broadcast.
79- votes_received_changed : bool ,
78+ votes_received : MutTrigger < BitSet > ,
8079 /// Vote accumulator.
8180 votes : VoteCollector ,
8281 /// Used to sign messages and proposals.
@@ -192,8 +191,7 @@ impl Worker {
192191 last_confirmed_view : 0 ,
193192 validators,
194193 extension,
195- votes_received : BitSet :: new ( ) ,
196- votes_received_changed : false ,
194+ votes_received : MutTrigger :: new ( BitSet :: new ( ) ) ,
197195 time_gap_params,
198196 timeout_token_nonce : ENGINE_TIMEOUT_TOKEN_NONCE_BASE ,
199197 }
@@ -576,13 +574,13 @@ impl Worker {
576574 . unwrap ( ) ;
577575 }
578576
579- fn broadcast_state ( & self , vote_step : VoteStep , proposal : Option < H256 > , lock_view : Option < View > , votes : BitSet ) {
577+ fn broadcast_state ( & self , vote_step : VoteStep , proposal : Option < H256 > , lock_view : Option < View > , votes : & BitSet ) {
580578 self . extension
581579 . send ( network:: Event :: BroadcastState {
582580 vote_step,
583581 proposal,
584582 lock_view,
585- votes,
583+ votes : * votes ,
586584 } )
587585 . unwrap ( ) ;
588586 }
@@ -617,7 +615,7 @@ impl Worker {
617615 cinfo ! ( ENGINE , "increment_view: New view." ) ;
618616 self . view += n;
619617 self . proposal = Proposal :: None ;
620- self . votes_received = BitSet :: new ( ) ;
618+ self . votes_received = MutTrigger :: new ( BitSet :: new ( ) ) ;
621619 }
622620
623621 fn move_to_height ( & mut self , height : Height ) {
@@ -627,7 +625,7 @@ impl Worker {
627625 self . height = height;
628626 self . view = 0 ;
629627 self . proposal = Proposal :: None ;
630- self . votes_received = BitSet :: new ( ) ;
628+ self . votes_received = MutTrigger :: new ( BitSet :: new ( ) ) ;
631629 }
632630
633631 #[ allow( clippy:: cognitive_complexity) ]
@@ -654,15 +652,15 @@ impl Worker {
654652 // Also, when moving to the commit step,
655653 // keep `votes_received` for gossiping.
656654 if prev_step. to_step ( ) != state. to_step ( ) && !state. is_commit ( ) {
657- self . votes_received = BitSet :: new ( ) ;
655+ self . votes_received = MutTrigger :: new ( BitSet :: new ( ) ) ;
658656 }
659657
660658 // need to reset vote
661659 self . broadcast_state (
662660 vote_step,
663661 self . proposal . block_hash ( ) ,
664662 self . last_two_thirds_majority . view ( ) ,
665- self . votes_received ,
663+ self . votes_received . borrow_anyway ( ) ,
666664 ) ;
667665 match state. to_step ( ) {
668666 Step :: Propose => {
@@ -929,10 +927,6 @@ impl Worker {
929927 return
930928 }
931929 }
932-
933- // self.move_to_step() calls self.broadcast_state()
934- // If self.move_to_step() is not called, call self.broadcast_state() in here.
935- self . votes_received_changed = true ;
936930 }
937931
938932 pub fn on_imported_proposal ( & mut self , proposal : & Header ) {
@@ -1273,13 +1267,12 @@ impl Worker {
12731267 }
12741268
12751269 if token == ENGINE_TIMEOUT_BROADCAST_STEP_STATE {
1276- if self . votes_received_changed {
1277- self . votes_received_changed = false ;
1270+ if let Some ( votes_received) = self . votes_received . borrow_if_mutated ( ) {
12781271 self . broadcast_state (
12791272 self . vote_step ( ) ,
12801273 self . proposal . block_hash ( ) ,
12811274 self . last_two_thirds_majority . view ( ) ,
1282- self . votes_received ,
1275+ votes_received,
12831276 ) ;
12841277 }
12851278 return
@@ -1776,7 +1769,7 @@ impl Worker {
17761769 VoteStep :: new ( self . height , self . view , self . step . to_step ( ) ) ,
17771770 self . proposal . block_hash ( ) ,
17781771 self . last_two_thirds_majority . view ( ) ,
1779- self . votes_received ,
1772+ self . votes_received . borrow_anyway ( ) ,
17801773 ) ;
17811774 }
17821775
@@ -1851,8 +1844,7 @@ impl Worker {
18511844 BitSet :: new ( )
18521845 } ;
18531846
1854- let current_votes = self . votes_received ;
1855- let difference = & peer_known_votes - & current_votes;
1847+ let difference = & peer_known_votes - & self . votes_received ;
18561848 if !difference. is_empty ( ) {
18571849 self . send_request_messages ( token, current_vote_step, difference, & result) ;
18581850 }
@@ -2122,7 +2114,7 @@ impl Worker {
21222114 // Since we don't have proposal vote, set proposal = None
21232115 self . proposal = Proposal :: None ;
21242116 self . view = commit_view;
2125- self . votes_received = vote_bitset;
2117+ self . votes_received = MutTrigger :: new ( vote_bitset) ;
21262118 self . last_two_thirds_majority = TwoThirdsMajority :: Empty ;
21272119
21282120 self . move_to_step (
@@ -2148,3 +2140,51 @@ fn calculate_score(height: Height, view: View) -> U256 {
21482140 let height = U256 :: from ( height) ;
21492141 u256_from_u128 ( std:: u128:: MAX ) * height - view
21502142}
2143+
2144+ /// Sets internal trigger on deref_mut (taking mutable reference to internal value)
2145+ /// trigger is reset on borrowing
2146+ struct MutTrigger < T > {
2147+ target : T ,
2148+ deref_mut_triggered : Cell < bool > ,
2149+ }
2150+
2151+ impl < T > MutTrigger < T > {
2152+ fn new ( target : T ) -> Self {
2153+ Self {
2154+ target,
2155+ deref_mut_triggered : Cell :: new ( true ) ,
2156+ }
2157+ }
2158+
2159+ /// Get the reference if triggered (mutable reference is taken after last borrowing)
2160+ /// When it is not triggered, returns None
2161+ fn borrow_if_mutated ( & self ) -> Option < & T > {
2162+ if self . deref_mut_triggered . get ( ) {
2163+ self . deref_mut_triggered . set ( false ) ;
2164+ Some ( & self . target )
2165+ } else {
2166+ None
2167+ }
2168+ }
2169+
2170+ /// Reset the trigger and take a reference
2171+ fn borrow_anyway ( & self ) -> & T {
2172+ self . deref_mut_triggered . set ( false ) ;
2173+ & self . target
2174+ }
2175+ }
2176+
2177+ impl < T > std:: ops:: Deref for MutTrigger < T > {
2178+ type Target = T ;
2179+
2180+ fn deref ( & self ) -> & Self :: Target {
2181+ & self . target
2182+ }
2183+ }
2184+
2185+ impl < T > std:: ops:: DerefMut for MutTrigger < T > {
2186+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
2187+ self . deref_mut_triggered . set ( true ) ;
2188+ & mut self . target
2189+ }
2190+ }
0 commit comments