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:
V1 is started.
V1 becomes validator and calls ProduceBlock, getting back empty data = vec![] and data_hash = AAA..=.
V1 creates a block B = Block::new(0, generic_qc(), vec![], AAA..=).
V1 inserts B into its block tree.
V1 broadcasts a proposal for B.
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.
After a long time, V2 is started. At this point, V1's current view >> V2's.
V2 becomes validator and calls ProduceBlock, getting back empty data and data_hash.
V2 creates a block B = Block::new(0, generic_qc(), vec![], AAA..=). This is identical to the B produced in event 3.
V2 inserts B into its block tree.
V2 broadcasts a proposal for B.
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.
Eventually V1 and V2's views synchronize.
V1 becomes validator and proposes B again.
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:
A set of checks to decide whether the block is safe to vote for.
An additional set of checks to decide whether the block is safe to insert.
This current behavior can prevent the blockchain from growing in situations where the
App
instances in all replicas return identicaldata
anddata_hash
fromProduceBlock
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:
ProduceBlock
, getting back emptydata = vec![]
anddata_hash = AAA..=
.B = Block::new(0, generic_qc(), vec![], AAA..=)
.B
into its block tree.B
.ProduceBlock
, getting back emptydata
anddata_hash
.B = Block::new(0, generic_qc(), vec![], AAA..=)
. This is identical to theB
produced in event 3.B
into its block tree.B
.B
and votes for it, but because V1's current view >> V2's, not enough votes are cast to form a QC.B
again.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: