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

Add unit tests for zksync_consensus_bft (BFT-360) #39

Merged
merged 44 commits into from
Nov 30, 2023
Merged

Conversation

moshababo
Copy link
Contributor

@moshababo moshababo commented Nov 20, 2023

Adding new unit tests coverage for zksync_consensus_bft crate.

Notes

  • Tests are located at the leader/replica mods level.
  • testonly::ut_harness::UTHarness struct was added to encapsulate all testing operations, and moreover to minimize redundancy of test code.

Coverage

  • replica prepare

    • replica_prepare_sanity
    • replica_prepare_sanity_yield_leader_prepare
    • replica_prepare_sanity_yield_leader_prepare_reproposal
    • replica_prepare_old_view
    • replica_prepare_during_commit
    • replica_prepare_not_leader_in_view
    • replica_prepare_already_exists
    • replica_prepare_num_received_below_threshold
    • replica_prepare_invalid_sig
    • replica_prepare_invalid_commit_qc
    • replica_prepare_high_qc_of_current_view
    • replica_prepare_high_qc_of_future_view
    • replica_prepare_non_validator_signer // FAILS
  • leader prepare

    • leader_prepare_sanity
    • leader_prepare_reproposal_sanity
    • leader_prepare_sanity_yield_replica_commit
    • leader_prepare_invalid_leader
    • leader_prepare_old_view
    • leader_prepare_invalid_sig
    • leader_prepare_invalid_prepare_qc
    • leader_prepare_invalid_high_qc
    • leader_prepare_proposal_oversized_payload
    • leader_prepare_proposal_mismatched_payload
    • leader_prepare_proposal_when_previous_not_finalized
    • leader_prepare_proposal_invalid_parent_hash
    • leader_prepare_proposal_non_sequential_number
    • leader_prepare_reproposal_without_quorum
    • leader_prepare_reproposal_when_finalized
    • leader_prepare_reproposal_invalid_block
  • replica commit

    • replica_commit_sanity
    • replica_commit_sanity_yield_leader_commit
    • replica_commit_old
    • replica_commit_not_leader_in_view
    • replica_commit_already_exists
    • replica_commit_num_received_below_threshold
    • replica_commit_invalid_sig
    • replica_commit_unexpected_proposal
    • replica_commit_protocol_version_mismatch // FAILS
  • leader commit

    • leader_commit_sanity
    • leader_commit_sanity_yield_replica_prepare
    • leader_commit_invalid_leader
    • leader_commit_old
    • leader_commit_invalid_sig
    • leader_commit_invalid_commit_qc

Copy link
Member

@brunoffranca brunoffranca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The direction looks good. I would just ask you to eventually move the utils to the testonly folder.

node/libs/crypto/src/bn254/error.rs Outdated Show resolved Hide resolved
node/actors/bft/src/tests/unit_tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/tests/unit_tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/tests/unit_tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/tests/unit_tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/tests/unit_tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/tests/mod.rs Outdated Show resolved Hide resolved
node/actors/bft/src/replica/leader_prepare.rs Outdated Show resolved Hide resolved
node/actors/bft/src/tests/unit_tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/tests/unit_tests.rs Outdated Show resolved Hide resolved
@moshababo
Copy link
Contributor Author

The replica_prepare and replica_commit message processing triggers a panic if the creation of the respective prepare/commit quorum certificate fails. This occurs after completing all checks and updating the local state. While it shouldn't be reproducible, I added two tests that demonstrate it:

  • replica_commit_protocol_version_mismatch
  • replica_prepare_non_validator_signer

The first is protected against during top-level processing, but I couldn't find safeguards for the latter.

@brunoffranca
Copy link
Member

brunoffranca commented Nov 24, 2023

Regarding the first test, we indeed do check the protocol version earlier. But its placement is not ideal, it's separate from all the other checks. And it only produces a tracing warning, it never produces an error that we can actually test. So I would move that check to later in the flow, so that we do all the checks for the message in the same place.
The second test shows an actual bug, we never check that the replica that is sending us a message belongs to the current validator set, we need to check it. Add that extra check for both the prepare and commit phases and we're good.

@brunoffranca
Copy link
Member

Another point is if failing to create a QC should panic. Technically we could have that method just return an error, but I'm not sure how we could recover from it. By that time, the only thing we could do is discard all the replica prepare messages we got and let our turn timeout. Which I guess is better than panicking but it would still let an attacker stop the chain anyway.

@moshababo
Copy link
Contributor Author

Another point is if failing to create a QC should panic. Technically we could have that method just return an error, but I'm not sure how we could recover from it. By that time, the only thing we could do is discard all the replica prepare messages we got and let our turn timeout. Which I guess is better than panicking but it would still let an attacker stop the chain anyway.

Does the current implementation support liveness in the event of a leader's timeout?

@moshababo
Copy link
Contributor Author

Since all shared util code is now located in testonly mod, the tests can be moved to replica/leader mods, closer to the tested code. Any opinions?

@moshababo moshababo changed the title [WIP] Add unit tests for zksync_consensus_bft (BFT-360) Add unit tests for zksync_consensus_bft (BFT-360) Nov 27, 2023
@moshababo moshababo marked this pull request as ready for review November 27, 2023 01:50
@pompon0
Copy link
Contributor

pompon0 commented Nov 27, 2023

Does the current implementation support liveness in the event of a leader's timeout?

Yes, and we should write tests for that.

Since all shared util code is now located in testonly mod, the tests can be moved to replica/leader mods, closer to the tested code. Any opinions?

+1, tests should be as close to the code under test as possible.

node/actors/bft/src/leader/tests.rs Show resolved Hide resolved
node/actors/bft/src/leader/tests.rs Show resolved Hide resolved
node/actors/bft/src/leader/tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/leader/tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/leader/mod.rs Outdated Show resolved Hide resolved
node/actors/bft/src/replica/tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/replica/tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/testonly/ut_harness.rs Outdated Show resolved Hide resolved
node/actors/bft/src/testonly/ut_harness.rs Outdated Show resolved Hide resolved
.unwrap()
}

pub(crate) async fn recv_signed(&mut self) -> Option<Signed<ConsensusMsg>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method seems to always return Some; could it be simplified to return Signed<_> instead of an Option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, originally it had None which turned out to be unnecessary, but the method signature remained.

I changed it now to return Result which will propagate the error type from self.pipe.recv instead of just unwrapping it: aa85e36

node/actors/bft/src/testonly/ut_harness.rs Outdated Show resolved Hide resolved
node/actors/bft/src/testonly/ut_harness.rs Outdated Show resolved Hide resolved
node/actors/bft/src/leader/tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/leader/tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/leader/tests.rs Show resolved Hide resolved
node/actors/bft/src/leader/tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/replica/tests.rs Outdated Show resolved Hide resolved
node/actors/bft/src/replica/tests.rs Outdated Show resolved Hide resolved
Copy link
Member

@brunoffranca brunoffranca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. There's only one change that needs to be committed. Approved!

node/actors/bft/src/testonly/ut_harness.rs Outdated Show resolved Hide resolved
@brunoffranca brunoffranca merged commit 4acf065 into main Nov 30, 2023
4 checks passed
@brunoffranca brunoffranca deleted the bft_unit_tests branch November 30, 2023 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants