You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current implementation deletes pending validator set updates on commit. This ultimately causes BlockTree::safe_qc and/or QuorumCertificate::is_correct to evaluate to true when we really want it to evaluate to false, and to evaluate to false when we want it to evaluate to true.
Acceptable nudges on a validator-set-changing block will fail safe_qc predicate 3 if the block has been committed, since the pending validator set changes of a block are.
Problem 2 (Safety)
Proposals containing a generic QC that extend a validator-set-changing block will pass predicate 4 of safe_qc and be accepted if the block has been committed, again, since the pending validator set changes of a block are deleted on commit.
Problem 3 (Safety and Liveness)
QCs in blocks that extend validator-set-changing blocks are formed by the previous validator set.
Consider a scenario in a replica that has just inserted a block containing a commit QC, that is, the block this block extends is committed by the insertion.
Imagine that after this, the replica receives a proposal containing a new block but which contains the same commit QC. In this case, The replica will try to validate the commit QC on its current committed validator set, which is the new validator set instead of the previous validator set because it has committed the parent block. A similar scenario could also happen with nudges.
This mistake opens the door to safety and liveness violating scenarios:
Liveness: because proposals and nudges containing QCs produced (correctly) by the previous validator may fail to pass BlockTree::is_correct evaluated on the new validator set.
Safety: because proposals and nudges containing QCs produced (wrongly) by the new validator set may pass BlockTree::is_correct.
The text was updated successfully, but these errors were encountered:
First, a part that is easier to fix: in this lineblock should be replaced with b.
Note that this line is incorrect with respect to our intention, but in reality it should not cause much trouble, since among the blocks that are committed with a single call to commit_block, only block can have associated validator set updates.
Secondly, even with the fix mentioned above we can face a possibly liveness-threatening situation. On committing a block b, the pending validator set updates associated with b are deleted from the BlockTree. When a child block of b is proposed, safe_qc returns true, since the justify is a commit QC and there are validator set updates associated with b in the BlockTree. Then b is committed and its pending validator set updates deleted. However, if another child block of b is proposed, the safe_qc (and hence safe_block) check will fail because the validator set updates associated with b have already been deleted.
In case the first child of b that was proposed cannot be committed, for instance because the proposal was only broadcasted to selected validators by a byzantine node, the validators that have inserted this block cannot insert any other conflicting block, hence this is a potential liveness threat.
Suggested solution to problem 1
Introduce a new type, such that instead of Option<ValidatorSetUpdates>, a block hash should map to this type (or Option of this type):
Background
The current implementation deletes pending validator set updates on commit. This ultimately causes
BlockTree::safe_qc
and/orQuorumCertificate::is_correct
to evaluate totrue
when we really want it to evaluate tofalse
, and to evaluate tofalse
when we want it to evaluate totrue
.Safe QC
QuorumCertificate::is_correct
Problems
Problem 1 (Liveness)
Acceptable nudges on a validator-set-changing block will fail
safe_qc
predicate 3 if the block has been committed, since the pending validator set changes of a block are.Problem 2 (Safety)
Proposals containing a generic QC that extend a validator-set-changing block will pass predicate 4 of
safe_qc
and be accepted if the block has been committed, again, since the pending validator set changes of a block are deleted on commit.Problem 3 (Safety and Liveness)
QCs in blocks that extend validator-set-changing blocks are formed by the previous validator set.
Consider a scenario in a replica that has just inserted a block containing a commit QC, that is, the block this block extends is committed by the insertion.
Imagine that after this, the replica receives a proposal containing a new block but which contains the same commit QC. In this case, The replica will try to validate the commit QC on its current committed validator set, which is the new validator set instead of the previous validator set because it has committed the parent block. A similar scenario could also happen with nudges.
This mistake opens the door to safety and liveness violating scenarios:
BlockTree::is_correct
evaluated on the new validator set.BlockTree::is_correct
.The text was updated successfully, but these errors were encountered: