Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Add missing tests for L26 and invalid transitions #141

Merged
merged 2 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 109 additions & 3 deletions code/test/tests/driver_extra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use malachite_test::utils::*;
// - L28 in round 1, via L36 in round 0, with locked invalid value v.
// `driver_steps_polka_previous_invalid_proposal()`'
//
// - L23 in round 1, via L36 in round 0, with lockedValue != v.
// `driver_steps_polka_previous_new_proposal()`
//
// - L28 in round 1 with no locked value, via L36 in round 0 with step precommit.
// `driver_steps_polka_previous_with_no_locked()`
//
Expand Down Expand Up @@ -465,7 +468,7 @@ fn driver_steps_polka_previous_with_locked() {
// L37 - v1 and v2 prevote for v, v3 gets +2/3 prevotes, start timeout prevote (step prevote)
// L55 - Receive f+1 vote for round 1 from v2, start new round (step new_round)
// L21 - v3 is not proposer starts timeout propose (step propose)
// L28 - v2 receives invalid proposal and has 2f+1 prevotes from round 0 and:
// L28 - v3 receives invalid proposal and has 2f+1 prevotes from round 0 and:
// L29 - with invalid proposal
// L32 - v2 sends prevote(nil, round=1) (step prevote)
#[test]
Expand Down Expand Up @@ -512,7 +515,7 @@ fn driver_steps_polka_previous_invalid_proposal() {
new_state: prevote_state(Round::new(0)),
},
TestStep {
desc: "Receive f+1 vote for round 1 from v3",
desc: "Receive f+1 vote for round 1 from v2",
input: prevote_input_at(Round::new(1), &v2.address),
expected_output: new_round_output(Round::new(1)),
expected_round: Round::new(1),
Expand All @@ -526,7 +529,7 @@ fn driver_steps_polka_previous_invalid_proposal() {
new_state: propose_state(Round::new(1)),
},
TestStep {
desc: "receive an invalid proposal for round 0",
desc: "receive an invalid proposal for POL round 0",
input: proposal_input(Round::new(1), value, Round::new(0), Validity::Invalid),
expected_output: prevote_nil_output(Round::new(1), &my_addr),
expected_round: Round::new(1),
Expand All @@ -537,6 +540,109 @@ fn driver_steps_polka_previous_invalid_proposal() {
run_steps(&mut driver, steps);
}

// Arrive at L36 in round 0, with step precommit and then L23 in round 1 with lockedValue != v.
//
// Ev: NewRound(0) Proposal <polka> <honest precommit(round=1)>
// State: NewRound ------------> Propose ---------> Prevote -----------> Precommit ---------------------------> NewRound -->
// Msg: propose_timer prevote(v) precommit(v) new_round(1)
// Alg: L21 L24 L37 L56
//
// Ev: NewRound(1) Proposal(other_value, pol_round=0)
// State: NewRound ---------------> Propose ----------------------------------> Prevote
// Msg: propose_timer prevote(nil,round=1)
// Alg: L21 L26
//
// v1=2, v2=3, v3=2, we are v3
// L21 - v3 is not proposer starts timeout propose (step propose)
// L24 - v3 receives proposal, prevotes for value (step prevote)
// L37 - v1 and v2 prevote for v, v3 gets +2/3 prevotes (step precommit)
// L56 - Receive f+1 vote for round 1 from v2, start new round (step new_round)
// L21 - v3 is not proposer starts timeout propose (step propose)
// L22 - v3 receives proposal for a different value and no POL round:
// L23 - valid(v) and lockedValue != v
// L26 - v2 sends prevote(nil, round=1) (step prevote)
#[test]
fn driver_steps_polka_previous_new_proposal() {
let value = Value::new(9999);
let other_value = Value::new(8888);

let [(v1, _sk1), (v2, _sk2), (v3, sk3)] = make_validators([2, 3, 2]);
let (my_sk, my_addr) = (sk3, v3.address);

let height = Height::new(1);
let ctx = TestContext::new(my_sk.clone());
let sel = RotateProposer;
let vs = ValidatorSet::new(vec![v1.clone(), v2.clone(), v3.clone()]);

let mut driver = Driver::new(ctx, height, sel, vs, my_addr, Default::default());

let steps = vec![
TestStep {
desc: "Start round 0, we, v3, are not the proposer, start timeout propose",
input: new_round_input(Round::new(0)),
expected_output: start_propose_timer_output(Round::new(0)),
expected_round: Round::new(0),
new_state: propose_state(Round::new(0)),
},
TestStep {
desc: "receive a valid proposal for round 0",
input: proposal_input(Round::new(0), value, Round::Nil, Validity::Valid),
expected_output: prevote_output(Round::new(0), &my_addr),
expected_round: Round::new(0),
new_state: prevote_state(Round::new(0)),
},
TestStep {
desc: "v1 prevotes the proposal",
input: prevote_input(&v1.address),
expected_output: None,
expected_round: Round::new(0),
new_state: prevote_state(Round::new(0)),
},
TestStep {
desc: "v2 prevotes for same proposal, we get +2/3 prevotes, precommit",
input: prevote_input(&v2.address),
expected_output: precommit_output(Round::new(0), value, &my_addr),
expected_round: Round::new(0),
new_state: precommit_state_with_proposal_and_locked_and_valid(
Round::new(0),
Proposal::new(Height::new(1), Round::new(0), value, Round::Nil),
),
},
TestStep {
desc: "Receive f+1 vote for round 1 from v2",
input: prevote_input_at(Round::new(1), &v2.address),
expected_output: new_round_output(Round::new(1)),
expected_round: Round::new(1),
new_state: new_round_with_proposal_and_locked_and_valid(
Round::new(1),
Proposal::new(Height::new(1), Round::new(0), value, Round::Nil),
),
},
TestStep {
desc: "start round 1, we, v3, are not the proposer, start timeout propose",
input: new_round_input(Round::new(1)),
expected_output: start_propose_timer_output(Round::new(1)),
expected_round: Round::new(1),
new_state: propose_state_with_proposal_and_locked_and_valid(
Round::new(1),
Proposal::new(Height::new(1), Round::new(0), value, Round::Nil),
),
},
TestStep {
desc: "receive a valid proposal for round 1 with different value",
input: proposal_input(Round::new(1), other_value, Round::Nil, Validity::Valid),
expected_output: prevote_nil_output(Round::new(1), &my_addr),
expected_round: Round::new(1),
new_state: prevote_state_with_proposal_and_locked_and_valid(
Round::new(1),
Proposal::new(Height::new(1), Round::new(1), value, Round::new(0)),
),
},
];

run_steps(&mut driver, steps);
}

// Arrive at L36 in round 0, with step precommit and then L28 in round 1 with no locked value.
//
// Ev: NewRound(0) Timeout(propose) <polka> Timeout(prevote)
Expand Down
36 changes: 36 additions & 0 deletions code/test/tests/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,39 @@ fn test_prevote() {
)
);
}

#[test]
fn test_input_message_while_commit_step() {
let value = Value::new(42);
let height = Height::new(1);
let round = Round::new(1);

let state: State<TestContext> = State {
height,
round,
..Default::default()
};

let proposal = Proposal::new(Height::new(1), Round::new(1), value, Round::Nil);

let data = Info::new(round, &ADDRESS, &OTHER_ADDRESS);

let mut transition = apply(state, &data, Input::NewRound(round));
let mut state = transition.next_state;

// Go to Commit step via L49
transition = apply(
state,
&data,
Input::ProposalAndPrecommitValue(proposal.clone()),
);
state = transition.next_state;
assert_eq!(state.step, Step::Commit);

// Send a proposal message while in Commit step, transition should be invalid
transition = apply(state, &data, Input::Proposal(proposal));
state = transition.next_state;

assert_eq!(state.step, Step::Commit);
assert!(!transition.valid);
}
Loading