consensus: update state to prevote nil when proposal block does not match locked block.#6986
Conversation
|
Left some comments on the docs as I tried to understand the new change / check correspondence. Plz don't block merge of this on me / these comments. Just thought I'd review try to understand more of the consensus code while its being touched! |
Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
| */ | ||
| blockID, ok := cs.Votes.Prevotes(cs.Proposal.POLRound).TwoThirdsMajority() | ||
| if ok && cs.ProposalBlock.HashesTo(blockID.Hash) && cs.Proposal.POLRound >= 0 && cs.Proposal.POLRound < cs.Round { | ||
| if cs.LockedRound <= cs.Proposal.POLRound { |
There was a problem hiding this comment.
Why >= here? The log message states "round later than the locked round", so > will be more consistent with it.
There was a problem hiding this comment.
Well, it is true that the ArXiv algorithm uses this condition: lockedRound_p ≤ v_r.
There was a problem hiding this comment.
The code is implicitly assuming the following: if Proposal.POLRound == LockedRound AND Prevotes(Proposal.POLRound).TwoThirdsMajority() == id(ProposalBlock) THEN ProposalBlock == LockedBlock.
Which is very likely to be true. But since hashes are performed lots of times in this code, maybe is better to double check this in the following if.
There was a problem hiding this comment.
The code is implicitly assuming the following: if Proposal.POLRound == LockedRound AND Prevotes(Proposal.POLRound).TwoThirdsMajority() == id(ProposalBlock) THEN ProposalBlock == LockedBlock.
I'm not totally sure we make that assumption. We have 2/3 prevotes from some round round_p. Given that we received 2/3 prevotes for the block in some round round_p, and round_p >= locked_round then we are safe to prevote that block, whether it matches our locked block or not.
There was a problem hiding this comment.
If round_p == locked_round, then the block that received 2/3+ votes in round_p must be our locked block, mustn't it? I am assuming that <1/3 of the voting power is Byzantine... but I'm not sure if we should assume this.
There was a problem hiding this comment.
Definitely, there is no reason for it not to match our locked block. I'm more saying that from the perspective of the correctness of the algorithm, seeing 2/3 prevotes in a round >= to our locked round is enough for us to prevote the block. It absolutely should match the locked block, and from the current implementation I'm not sure why it ever would not (happy to be corrected here), but I think that keeping it in this notation allows us to match the arXiv paper. I think keeping it in the same notation as the arXiv paper is preferable so that we can more easily know we're making safe changes to it as we go forward.
There was a problem hiding this comment.
'v_r' is a round greater than our current locked round.
Agreed. But in this case I would make the comment consistent: v_r is not lesser/smaller than...
There was a problem hiding this comment.
Good point, fixed.
cason
left a comment
There was a problem hiding this comment.
Reviewed the implementation, not the tests yet.
|
Thanks @cason for the review! Looks like I missed a few comments while refactoring. Very appreciated. |
I see, so we would have missed 2/3 prevotes during the actual time that would have been actionable, but still retained them for a future POL check. Thanks for the info. |
|
We ran a few test scenarios around this change.
The outcome was that the first test case fails and the other two pass. This was the expected behaviour.
As expected, the other two test cases were successful as well. The test cases are described in more detail here - https://github.com/ds-test-framework/tendermint-test/blob/master/docs/report/Tendermint.md. Apologies for posting it late but please let me know if you have any comments or feedback. |
|
Thanks a lot @zeu5!! |
…atch locked block. (#6986) * add failing test * tweak comments in failing test * failing test comment * initial attempt at removing prevote locked block logic * comment out broken function * undo reset on prevotes * fixing TestProposeValidBlock test * update test for completed POL update * comment updates * further unlock testing * update comments * Update internal/consensus/state.go * spacing nit * comment cleanup * nil check in addVote * update unlock description * update precommit on relock comment * add ensure new timeout back * rename IsZero to IsNil and replace uses of block len check with helper * add testing.T to new assertions * begin removing unlock condition * fix TestStateProposerSelection2 to precommit for nil correctly * remove erroneous sleep * update TestStatePOL comment * update relock test to be more clear * add _ into test names * rename slashing * udpate no relock function to be cleaner * do not relock on old proposal test cleanup * con state name update * remove all references to unlock * update test comments to include new * add relock test * add ensureRelock to common_test * remove all event unlock * remove unlock checks * no lint add space * lint ++ * add test for nil prevote on different proposal * fix prevote nil condition * fix defaultDoPrevote * state_test.go fixes to accomodate prevoting for nil * add failing test for POL from previous round case * update prevote logic to prevote POL from previous round * state.go comment fixes * update validatePrevotes to correctly look for nil * update new test name and comment * update POLFromPreviousRound test * fixes post merge * fix spacing * make the linter happy * change prevote log message * update prevote nil debug line * update enterPrevote comment * lint * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * add english description of alg rules * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * comment fixes from review * fix comment * fix comment Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
…atch locked block. (#6986) * add failing test * tweak comments in failing test * failing test comment * initial attempt at removing prevote locked block logic * comment out broken function * undo reset on prevotes * fixing TestProposeValidBlock test * update test for completed POL update * comment updates * further unlock testing * update comments * Update internal/consensus/state.go * spacing nit * comment cleanup * nil check in addVote * update unlock description * update precommit on relock comment * add ensure new timeout back * rename IsZero to IsNil and replace uses of block len check with helper * add testing.T to new assertions * begin removing unlock condition * fix TestStateProposerSelection2 to precommit for nil correctly * remove erroneous sleep * update TestStatePOL comment * update relock test to be more clear * add _ into test names * rename slashing * udpate no relock function to be cleaner * do not relock on old proposal test cleanup * con state name update * remove all references to unlock * update test comments to include new * add relock test * add ensureRelock to common_test * remove all event unlock * remove unlock checks * no lint add space * lint ++ * add test for nil prevote on different proposal * fix prevote nil condition * fix defaultDoPrevote * state_test.go fixes to accomodate prevoting for nil * add failing test for POL from previous round case * update prevote logic to prevote POL from previous round * state.go comment fixes * update validatePrevotes to correctly look for nil * update new test name and comment * update POLFromPreviousRound test * fixes post merge * fix spacing * make the linter happy * change prevote log message * update prevote nil debug line * update enterPrevote comment * lint * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * add english description of alg rules * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * comment fixes from review * fix comment * fix comment Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
…not match locked block (tendermint#1203) * consensus: update state to prevote nil when proposal block does not match locked block. (tendermint#6986) * add failing test * tweak comments in failing test * failing test comment * initial attempt at removing prevote locked block logic * comment out broken function * undo reset on prevotes * fixing TestProposeValidBlock test * update test for completed POL update * comment updates * further unlock testing * update comments * Update internal/consensus/state.go * spacing nit * comment cleanup * nil check in addVote * update unlock description * update precommit on relock comment * add ensure new timeout back * rename IsZero to IsNil and replace uses of block len check with helper * add testing.T to new assertions * begin removing unlock condition * fix TestStateProposerSelection2 to precommit for nil correctly * remove erroneous sleep * update TestStatePOL comment * update relock test to be more clear * add _ into test names * rename slashing * udpate no relock function to be cleaner * do not relock on old proposal test cleanup * con state name update * remove all references to unlock * update test comments to include new * add relock test * add ensureRelock to common_test * remove all event unlock * remove unlock checks * no lint add space * lint ++ * add test for nil prevote on different proposal * fix prevote nil condition * fix defaultDoPrevote * state_test.go fixes to accomodate prevoting for nil * add failing test for POL from previous round case * update prevote logic to prevote POL from previous round * state.go comment fixes * update validatePrevotes to correctly look for nil * update new test name and comment * update POLFromPreviousRound test * fixes post merge * fix spacing * make the linter happy * change prevote log message * update prevote nil debug line * update enterPrevote comment * lint * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * add english description of alg rules * Update internal/consensus/state.go Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * comment fixes from review * fix comment * fix comment Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> * Fix UTs * Addressed comments * Add changelog * Update consensus/state.go Co-authored-by: Hernán Vanzetto <15466498+hvanz@users.noreply.github.com> --------- Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com> Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> Co-authored-by: Hernán Vanzetto <15466498+hvanz@users.noreply.github.com>
This change updates
state.goto modify the conditions under which a validator will issue prevote for a proposed block. This change attempts to bring the prevote logic in this go implementation more inline with the algorithm as described in the 2018 tendermint arXiv paper.The change adds a condition under which this code will issue a prevote. The code will now prevote if +2/3 prevotes were seen for a block in a previous round and that block is proposed in current round. This matches the condition on line 28 of the arXiv paper. Prevoting in this condition must not update the locked block. The locked block should only be updated if +2/3 prevotes were seen within the same round as the proposal.
TestState_PrevotePOLFromPreviousRoundwas added to check the correctness of this change.This change also removes a condition under which the code will issue a prevote. Previously, the code issued for the validator's locked block regardless of what the proposal was for. The code will now only issue a prevote for its locked block if it matches the currently proposed block.
TestStateLock_PrevoteNilWhenLockedAndMissProposalwas added to check the correctness of this change.Other tests were modified to ensure we correctly issue prevotes for
nilor the locked block as a result of this change.closes: #6850