Skip to content

PBTS: do we need the Proposal when the proposed block received a Polka? #2119

@cason

Description

@cason

Originally posted by @cason in #2018 (comment):

  A note to remember: we are forcing a `Proposal` to be received to run the prevote logic. While this is necessary when POLRound == -1, it might not be otherwise.

The PBTS-enabled consensus code adds the requirement of receiving and accepting a Proposal to precommit a block:

if cs.Proposal == nil || cs.ProposalBlock == nil {
logger.Debug("precommit step; did not receive proposal, precommitting nil")
cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}, nil)

This requirement is not present in the original code, in the main branch, where the absence of a valid proposal (cs.Proposal) does not cause the node to precommit nil. The reason for which is that a node may realize that a proposal block has become valid, because it received a Polka, in the case the blockID in the following code:

if !cs.ProposalBlockParts.HasHeader(blockID.PartSetHeader) {
cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartSetHeader)
}

What happens here is that the node starts "looking" for this block, by updating its cs.ProposalBlockParts field. There are two possibilities to consider here:

  1. The node received a Proposal for a block that doesn't match the blockID that became valid. This happens when a Byzantine proposer produces multiple proposals in a round. This is not the case considered int this issue, since the cs.Proposal should be set, probably for a different block, but the code doesn't care.
  2. The node has not received any valid Proposal, so it is not building any block. This is the scenario addressed here.

The general point here is that if we received a Polka for a block, it does not matter the (first valid) Proposal we received, not even if we have not received any Proposal. This block has been deemed valid by 2/3+ validators, so there is no reason for not precommiting it. Note that we use the same rationale in PBTS when we receive a Proposal backed by a Polka in a POLRound: we don't check the block time again, as it was accepted by a quorum of validators.

With this in mind, this additional check added to the precommit round step does not make sense:

// If the proposal time does not match the block time, precommit nil.
if !cs.Proposal.Timestamp.Equal(cs.ProposalBlock.Header.Time) {
logger.Debug("precommit step: proposal timestamp not equal; precommitting nil")
cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}, nil)

While it is probably the only reason for requiring cs.Proposal != nil to get to this point. My proposal is then:

  • Remove the cs.Proposal != nil condition to precommit a block (cs.enterPrecommit)
  • Remove the cs.Proposal.Timestamp.Equal(cs.ProposalBlock.Header.Time) check at the same step

Metadata

Metadata

Assignees

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions