parallelchain-io / hotstuff_rs

Rust implementation of the HotStuff consensus algorithm.
34 stars 4 forks source link

A validator will not vote on a proposal if an identical block is already in its block tree #4

Open lyulka opened 1 year ago

lyulka commented 1 year ago

This current behavior can prevent the blockchain from growing in situations where the App instances in all replicas return identical data and data_hash from ProduceBlock for an extended period of time.

Example scenario

Consider a network with two validators, "V1", and "V2". Assume that the validator set never changes and both validators have equal power, and thus votes from both validators are needed to form a QC.

The following events happen in sequence:

  1. V1 is started.
  2. V1 becomes validator and calls ProduceBlock, getting back empty data = vec![] and data_hash = AAA..=.
  3. V1 creates a block B = Block::new(0, generic_qc(), vec![], AAA..=).
  4. V1 inserts B into its block tree.
  5. V1 broadcasts a proposal for B.
  6. V1 receives its own proposal and votes for it, but because V2 is not yet started, not enough votes are cast to form a QC.
  7. After a long time, V2 is started. At this point, V1's current view >> V2's.
  8. V2 becomes validator and calls ProduceBlock, getting back empty data and data_hash.
  9. V2 creates a block B = Block::new(0, generic_qc(), vec![], AAA..=). This is identical to the B produced in event 3.
  10. V2 inserts B into its block tree.
  11. V2 broadcasts a proposal for B.
  12. V2 receives its own proposal for B and votes for it, but because V1's current view >> V2's, not enough votes are cast to form a QC.
  13. Eventually V1 and V2's views synchronize.
  14. V1 becomes validator and proposes B again.
  15. This time, both validators receive it, but they do not vote for it since B is already in their respective block trees.

After 15, the blockchain will cease to grow until apps start producing different blocks. This is even though all validators are on the same view.

Proposed solution

Split up safe_block into:

  1. A set of checks to decide whether the block is safe to vote for.
  2. An additional set of checks to decide whether the block is safe to insert.