Skip to content

Commit

Permalink
Add liveness tests (BFT-387) (#46)
Browse files Browse the repository at this point in the history
Adding new protocol liveness tests for when the network becomes idle in
various stages.
  • Loading branch information
moshababo authored Dec 6, 2023
1 parent aa5c0dc commit f25f078
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 30 deletions.
16 changes: 5 additions & 11 deletions node/actors/bft/src/leader/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ use zksync_consensus_roles::validator::{
async fn replica_prepare_sanity() {
let mut util = UTHarness::new_many().await;

util.set_view(util.owner_as_view_leader());

let replica_prepare = util.new_current_replica_prepare(|_| {}).cast().unwrap().msg;
util.dispatch_replica_prepare_many(
vec![replica_prepare; util.consensus_threshold()],
Expand Down Expand Up @@ -60,8 +58,6 @@ async fn replica_prepare_sanity_yield_leader_prepare() {
async fn replica_prepare_sanity_yield_leader_prepare_reproposal() {
let mut util = UTHarness::new_many().await;

util.set_view(util.owner_as_view_leader());

let replica_prepare: ReplicaPrepare =
util.new_unfinalized_replica_prepare().cast().unwrap().msg;
util.dispatch_replica_prepare_many(
Expand Down Expand Up @@ -176,7 +172,7 @@ async fn replica_prepare_during_commit() {
async fn replica_prepare_not_leader_in_view() {
let mut util = UTHarness::new_with(2).await;

let current_view_leader = util.view_leader(util.current_replica_view());
let current_view_leader = util.view_leader(util.replica_view());
assert_ne!(current_view_leader, util.owner_key().public());

let replica_prepare = util.new_current_replica_prepare(|_| {});
Expand Down Expand Up @@ -293,8 +289,6 @@ async fn replica_prepare_high_qc_of_future_view() {
async fn replica_commit_sanity() {
let mut util = UTHarness::new_many().await;

util.set_view(util.owner_as_view_leader());

let replica_commit = util
.new_procedural_replica_commit_many()
.await
Expand Down Expand Up @@ -381,7 +375,7 @@ async fn replica_commit_old() {
.cast::<ReplicaCommit>()
.unwrap()
.msg;
replica_commit.view = util.current_replica_view().prev();
replica_commit.view = util.replica_view().prev();
let replica_commit = util
.owner_key()
.sign_msg(ConsensusMsg::ReplicaCommit(replica_commit));
Expand All @@ -390,8 +384,8 @@ async fn replica_commit_old() {
assert_matches!(
res,
Err(ReplicaCommitError::Old { current_view, current_phase }) => {
assert_eq!(current_view, util.current_replica_view());
assert_eq!(current_phase, util.current_replica_phase());
assert_eq!(current_view, util.replica_view());
assert_eq!(current_phase, util.replica_phase());
}
);
}
Expand All @@ -400,7 +394,7 @@ async fn replica_commit_old() {
async fn replica_commit_not_leader_in_view() {
let mut util = UTHarness::new_with(2).await;

let current_view_leader = util.view_leader(util.current_replica_view());
let current_view_leader = util.view_leader(util.replica_view());
assert_ne!(current_view_leader, util.owner_key().public());

let replica_commit = util.new_current_replica_commit(|_| {});
Expand Down
16 changes: 4 additions & 12 deletions node/actors/bft/src/replica/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ use zksync_consensus_roles::validator::{
async fn leader_prepare_sanity() {
let mut util = UTHarness::new_many().await;

util.set_view(util.owner_as_view_leader());

let leader_prepare = util.new_procedural_leader_prepare_many().await;
util.dispatch_leader_prepare(leader_prepare).await.unwrap();
}
Expand All @@ -24,8 +22,6 @@ async fn leader_prepare_sanity() {
async fn leader_prepare_reproposal_sanity() {
let mut util = UTHarness::new_many().await;

util.set_view(util.owner_as_view_leader());

let replica_prepare: ReplicaPrepare =
util.new_unfinalized_replica_prepare().cast().unwrap().msg;
util.dispatch_replica_prepare_many(
Expand Down Expand Up @@ -154,7 +150,7 @@ async fn leader_prepare_old_view() {
.cast::<LeaderPrepare>()
.unwrap()
.msg;
leader_prepare.view = util.current_replica_view().prev();
leader_prepare.view = util.replica_view().prev();
let leader_prepare = util
.owner_key()
.sign_msg(ConsensusMsg::LeaderPrepare(leader_prepare));
Expand All @@ -163,8 +159,8 @@ async fn leader_prepare_old_view() {
assert_matches!(
res,
Err(LeaderPrepareError::Old { current_view, current_phase }) => {
assert_eq!(current_view, util.current_replica_view());
assert_eq!(current_phase, util.current_replica_phase());
assert_eq!(current_view, util.replica_view());
assert_eq!(current_phase, util.replica_phase());
}
);
}
Expand Down Expand Up @@ -393,8 +389,6 @@ async fn leader_prepare_proposal_non_sequential_number() {
async fn leader_prepare_reproposal_without_quorum() {
let mut util = UTHarness::new_many().await;

util.set_view(util.owner_as_view_leader());

let mut leader_prepare = util
.new_procedural_leader_prepare_many()
.await
Expand Down Expand Up @@ -464,8 +458,6 @@ async fn leader_prepare_reproposal_invalid_block() {
async fn leader_commit_sanity() {
let mut util = UTHarness::new_many().await;

util.set_view(util.owner_as_view_leader());

let leader_commit = util.new_procedural_leader_commit_many().await;
util.dispatch_leader_commit(leader_commit).await.unwrap();
}
Expand Down Expand Up @@ -525,7 +517,7 @@ async fn leader_commit_incompatible_protocol_version() {
async fn leader_commit_invalid_leader() {
let mut util = UTHarness::new_with(2).await;

let current_view_leader = util.view_leader(util.current_replica_view());
let current_view_leader = util.view_leader(util.replica_view());
assert_ne!(current_view_leader, util.owner_key().public());

let leader_commit = util.new_rnd_leader_commit(|_| {});
Expand Down
66 changes: 60 additions & 6 deletions node/actors/bft/src/testonly/ut_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ impl UTHarness {
pub(crate) async fn new_one() -> UTHarness {
UTHarness::new_with(1).await
}

/// Creates a new `UTHarness` with minimally-significant validator set size.
pub(crate) async fn new_many() -> UTHarness {
let num_validators = 6;
assert_matches!(crate::misc::faulty_replicas(num_validators), res if res > 0);
UTHarness::new_with(num_validators).await
let mut util = UTHarness::new_with(num_validators).await;
util.set_view(util.owner_as_view_leader_current_or_next());
util
}

/// Creates a new `UTHarness` with the specified validator set size.
Expand All @@ -67,6 +68,47 @@ impl UTHarness {
}
}

pub(crate) async fn iterate_next(&mut self) {
let leader_commit = self.new_procedural_leader_commit_many().await;
self.dispatch_leader_commit(leader_commit).await.unwrap();
self.recv_signed()
.await
.unwrap()
.cast::<ReplicaPrepare>()
.unwrap();
}

/// Validate protocol liveness in the aftermath of a timeout.
///
/// Params refer to the expected values in the next produced `ReplicaPrepare`
/// messages for the new iteration.
///
/// * `view` - the expected view of the next `ReplicaPrepare`.
/// * `high_vote_view` - the expected view of the high vote of the next `ReplicaPrepare`.
/// * `high_qc_view` - the expected view of the high qc of the next `ReplicaPrepare`.
///
pub(crate) async fn check_recovery_after_timeout(
&mut self,
view: ViewNumber,
high_vote_view: ViewNumber,
high_qc_view: ViewNumber,
) {
let replica_prepare = self
.recv_signed()
.await
.unwrap()
.cast::<ReplicaPrepare>()
.unwrap()
.msg;

assert_eq!(replica_prepare.view, view);
assert_eq!(replica_prepare.high_vote.view, high_vote_view);
assert_eq!(replica_prepare.high_qc.message.view, high_qc_view);

self.set_replica_view(self.owner_as_view_leader_current_or_next());
self.iterate_next().await;
}

pub(crate) fn consensus_threshold(&self) -> usize {
crate::misc::consensus_threshold(self.keys.len())
}
Expand All @@ -83,8 +125,8 @@ impl UTHarness {
&self.consensus.inner.secret_key
}

pub(crate) fn owner_as_view_leader(&self) -> ViewNumber {
let mut view = self.current_replica_view();
pub(crate) fn owner_as_view_leader_current_or_next(&self) -> ViewNumber {
let mut view = self.replica_view();
while self.view_leader(view) != self.owner_key().public() {
view = view.next();
}
Expand Down Expand Up @@ -389,6 +431,14 @@ impl UTHarness {
.unwrap()
}

pub(crate) async fn sim_timeout(&mut self) {
self.consensus
.replica
.process_input(&self.ctx, &self.consensus.inner, None)
.await
.unwrap()
}

pub(crate) async fn dispatch_leader_commit(
&mut self,
msg: Signed<ConsensusMsg>,
Expand Down Expand Up @@ -419,14 +469,18 @@ impl UTHarness {
})
}

pub(crate) fn current_replica_view(&self) -> ViewNumber {
pub(crate) fn replica_view(&self) -> ViewNumber {
self.consensus.replica.view
}

pub(crate) fn current_replica_phase(&self) -> Phase {
pub(crate) fn replica_phase(&self) -> Phase {
self.consensus.replica.phase
}

pub(crate) fn leader_phase(&self) -> Phase {
self.consensus.leader.phase
}

pub(crate) fn view_leader(&self, view: ViewNumber) -> validator::PublicKey {
self.consensus.inner.view_leader(view)
}
Expand Down
Loading

0 comments on commit f25f078

Please sign in to comment.