Skip to content

Commit 333307e

Browse files
committed
Check mutation of votes_received automatially
1 parent cbcec0b commit 333307e

File tree

1 file changed

+62
-22
lines changed

1 file changed

+62
-22
lines changed

core/src/consensus/tendermint/worker.rs

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use crate::error::{BlockError, Error};
5252
use crate::transaction::{SignedTransaction, UnverifiedTransaction};
5353
use crate::views::BlockView;
5454
use crate::BlockId;
55+
use std::cell::Cell;
5556

5657
type 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

Comments
 (0)