Skip to content

Commit 6313ff8

Browse files
committed
Check mutation of votes_received automatially
1 parent f805518 commit 6313ff8

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
@@ -53,6 +53,7 @@ use crate::error::{BlockError, Error};
5353
use crate::transaction::{SignedTransaction, UnverifiedTransaction};
5454
use crate::views::BlockView;
5555
use crate::BlockId;
56+
use std::cell::Cell;
5657

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

Comments
 (0)