@@ -53,6 +53,7 @@ use crate::error::{BlockError, Error};
5353use  crate :: transaction:: { SignedTransaction ,  UnverifiedTransaction } ; 
5454use  crate :: views:: BlockView ; 
5555use  crate :: BlockId ; 
56+ use  std:: cell:: Cell ; 
5657
5758type  SpawnResult  = ( 
5859    JoinHandle < ( ) > , 
@@ -75,9 +76,7 @@ struct Worker {
7576    /// Consensus step. 
7677     step :  TendermintState , 
7778    /// Record current round's received votes as bit set 
78-      votes_received :  BitSet , 
79-     /// The votes_received field is changed after last state broadcast. 
80-      votes_received_changed :  bool , 
79+      votes_received :  MutTrigger < BitSet > , 
8180    /// Vote accumulator. 
8281     votes :  VoteCollector , 
8382    /// Used to sign messages and proposals. 
@@ -193,8 +192,7 @@ impl Worker {
193192            last_confirmed_view :  0 , 
194193            validators, 
195194            extension, 
196-             votes_received :  BitSet :: new ( ) , 
197-             votes_received_changed :  false , 
195+             votes_received :  MutTrigger :: new ( BitSet :: new ( ) ) , 
198196            time_gap_params, 
199197            timeout_token_nonce :  ENGINE_TIMEOUT_TOKEN_NONCE_BASE , 
200198        } 
@@ -577,13 +575,13 @@ impl Worker {
577575            . unwrap ( ) ; 
578576    } 
579577
580-     fn  broadcast_state ( & self ,  vote_step :  VoteStep ,  proposal :  Option < H256 > ,  lock_view :  Option < View > ,  votes :  BitSet )  { 
578+     fn  broadcast_state ( & self ,  vote_step :  VoteStep ,  proposal :  Option < H256 > ,  lock_view :  Option < View > ,  votes :  & BitSet )  { 
581579        self . extension 
582580            . send ( network:: Event :: BroadcastState  { 
583581                vote_step, 
584582                proposal, 
585583                lock_view, 
586-                 votes, 
584+                 votes :   * votes , 
587585            } ) 
588586            . unwrap ( ) ; 
589587    } 
@@ -618,7 +616,7 @@ impl Worker {
618616        cinfo ! ( ENGINE ,  "increment_view: New view." ) ; 
619617        self . view  += n; 
620618        self . proposal  = Proposal :: None ; 
621-         self . votes_received  = BitSet :: new ( ) ; 
619+         self . votes_received  = MutTrigger :: new ( BitSet :: new ( ) ) ; 
622620    } 
623621
624622    fn  move_to_height ( & mut  self ,  height :  Height )  { 
@@ -628,7 +626,7 @@ impl Worker {
628626        self . height  = height; 
629627        self . view  = 0 ; 
630628        self . proposal  = Proposal :: None ; 
631-         self . votes_received  = BitSet :: new ( ) ; 
629+         self . votes_received  = MutTrigger :: new ( BitSet :: new ( ) ) ; 
632630    } 
633631
634632    #[ allow( clippy:: cognitive_complexity) ]  
@@ -655,15 +653,15 @@ impl Worker {
655653        // Also, when moving to the commit step, 
656654        // keep `votes_received` for gossiping. 
657655        if  prev_step. to_step ( )  != state. to_step ( )  && !state. is_commit ( )  { 
658-             self . votes_received  = BitSet :: new ( ) ; 
656+             self . votes_received  = MutTrigger :: new ( BitSet :: new ( ) ) ; 
659657        } 
660658
661659        // need to reset vote 
662660        self . broadcast_state ( 
663661            vote_step, 
664662            self . proposal . block_hash ( ) , 
665663            self . last_two_thirds_majority . view ( ) , 
666-             self . votes_received , 
664+             self . votes_received . borrow_anyway ( ) , 
667665        ) ; 
668666        match  state. to_step ( )  { 
669667            Step :: Propose  => { 
@@ -931,10 +929,6 @@ impl Worker {
931929                return 
932930            } 
933931        } 
934- 
935-         // self.move_to_step() calls self.broadcast_state() 
936-         // If self.move_to_step() is not called, call self.broadcast_state() in here. 
937-         self . votes_received_changed  = true ; 
938932    } 
939933
940934    pub  fn  on_imported_proposal ( & mut  self ,  proposal :  & Header )  { 
@@ -1248,13 +1242,12 @@ impl Worker {
12481242        } 
12491243
12501244        if  token == ENGINE_TIMEOUT_BROADCAST_STEP_STATE  { 
1251-             if  self . votes_received_changed  { 
1252-                 self . votes_received_changed  = false ; 
1245+             if  let  Some ( votes_received)  = self . votes_received . borrow_if_mutated ( )  { 
12531246                self . broadcast_state ( 
12541247                    self . vote_step ( ) , 
12551248                    self . proposal . block_hash ( ) , 
12561249                    self . last_two_thirds_majority . view ( ) , 
1257-                     self . votes_received , 
1250+                     votes_received, 
12581251                ) ; 
12591252            } 
12601253            return 
@@ -1749,7 +1742,7 @@ impl Worker {
17491742                    VoteStep :: new ( self . height ,  self . view ,  self . step . to_step ( ) ) , 
17501743                    self . proposal . block_hash ( ) , 
17511744                    self . last_two_thirds_majority . view ( ) , 
1752-                     self . votes_received , 
1745+                     self . votes_received . borrow_anyway ( ) , 
17531746                ) ; 
17541747            } 
17551748
@@ -1824,8 +1817,7 @@ impl Worker {
18241817                BitSet :: new ( ) 
18251818            } ; 
18261819
1827-             let  current_votes = self . votes_received ; 
1828-             let  difference = & peer_known_votes - & current_votes; 
1820+             let  difference = & peer_known_votes - & self . votes_received ; 
18291821            if  !difference. is_empty ( )  { 
18301822                self . send_request_messages ( token,  current_vote_step,  difference,  & result) ; 
18311823            } 
@@ -2095,7 +2087,7 @@ impl Worker {
20952087        // Since we don't have proposal vote, set proposal = None 
20962088        self . proposal  = Proposal :: None ; 
20972089        self . view  = commit_view; 
2098-         self . votes_received  = vote_bitset; 
2090+         self . votes_received  = MutTrigger :: new ( vote_bitset) ; 
20992091        self . last_two_thirds_majority  = TwoThirdsMajority :: Empty ; 
21002092
21012093        self . move_to_step ( 
@@ -2121,3 +2113,51 @@ fn calculate_score(height: Height, view: View) -> U256 {
21212113    let  height = U256 :: from ( height) ; 
21222114    u256_from_u128 ( std:: u128:: MAX )  *  height - view
21232115} 
2116+ 
2117+ /// Sets internal trigger on deref_mut (taking mutable reference to internal value) 
2118+ /// trigger is reset on borrowing 
2119+ struct  MutTrigger < T >  { 
2120+     target :  T , 
2121+     deref_mut_triggered :  Cell < bool > , 
2122+ } 
2123+ 
2124+ impl < T >  MutTrigger < T >  { 
2125+     fn  new ( target :  T )  -> Self  { 
2126+         Self  { 
2127+             target, 
2128+             deref_mut_triggered :  Cell :: new ( true ) , 
2129+         } 
2130+     } 
2131+ 
2132+     /// Get the reference if triggered (mutable reference is taken after last borrowing) 
2133+      /// When it is not triggered, returns None 
2134+      fn  borrow_if_mutated ( & self )  -> Option < & T >  { 
2135+         if  self . deref_mut_triggered . get ( )  { 
2136+             self . deref_mut_triggered . set ( false ) ; 
2137+             Some ( & self . target ) 
2138+         }  else  { 
2139+             None 
2140+         } 
2141+     } 
2142+ 
2143+     /// Reset the trigger and take a reference 
2144+      fn  borrow_anyway ( & self )  -> & T  { 
2145+         self . deref_mut_triggered . set ( false ) ; 
2146+         & self . target 
2147+     } 
2148+ } 
2149+ 
2150+ impl < T >  std:: ops:: Deref  for  MutTrigger < T >  { 
2151+     type  Target  = T ; 
2152+ 
2153+     fn  deref ( & self )  -> & Self :: Target  { 
2154+         & self . target 
2155+     } 
2156+ } 
2157+ 
2158+ impl < T >  std:: ops:: DerefMut  for  MutTrigger < T >  { 
2159+     fn  deref_mut ( & mut  self )  -> & mut  Self :: Target  { 
2160+         self . deref_mut_triggered . set ( true ) ; 
2161+         & mut  self . target 
2162+     } 
2163+ } 
0 commit comments