types: CommitVotes struct as last step towards #1648#3298
Conversation
- new CommitVotes struct holds both the Commit and the ValidatorSet and implements VoteSetReader - ToVote takes a ValidatorSet
|
ebuchman
left a comment
There was a problem hiding this comment.
Still need to fix the tests :)
|
Wow, integration test caught a bug. We should write a unit test to catch it too - basically need to be able to validate commits where some of the precommits aren't for the committed BlockID; up to 1/3 of them could be for nil or even for a different blockID! This means we need the CommitSig to indicate which BlockID it signed! Alternatively, we could have the Commit contain two lists - one for those that signed the commit.BlockID, and one for those that did not |
Commits may include votes for a different BlockID, could be nil, or different altogether. This means we can't use `commit.BlockID` for reconstructing the sign bytes, since up to -1/3 of the commits might be for independent BlockIDs. This means CommitSig will need to include an indicator for what BlockID it signed - if it's not the committed one or nil, it will need to include it fully in order to be verified. This is unfortunate but unavoidable so long as we include votes for non-committed BlockIDs (which we do to track validator liveness)
Codecov Report
@@ Coverage Diff @@
## develop #3298 +/- ##
==========================================
Coverage ? 64.06%
==========================================
Files ? 213
Lines ? 17495
Branches ? 0
==========================================
Hits ? 11208
Misses ? 5353
Partials ? 934
|
|
What's left here? Adding a sleep #3298 (comment)? |
Of course updating the ADR should probably come first, and we probably actually need a new/better process altogether for making breaking changes to the block protocol (as opposed to architectural changes, which is what ADRs are for), but that's a separate issue. If #3485 decides we do need to include nil votes (presumably we won't need votes for the explicitly wrong blockID), then we need to determine how to track whether a vote is for the blockID or for nil. I see roughly three approaches:
|
|
Oh whoops, we don't actually need to solve all that before merging this. We can move forward with this PR and deal with the final changes in a new one :D |
|
Ok based on #3596 I think we want the CommitSig to have the ValidatorAddress, which simplifies this PR quite a bit. |
ebuchman
left a comment
There was a problem hiding this comment.
More feedback. Will fix
liamsi
left a comment
There was a problem hiding this comment.
The changes look good to me! Happy to help out with follow-up work in a separate PR
| return &v | ||
| } | ||
|
|
||
| //------------------------------------- |
There was a problem hiding this comment.
Potentially unpopular opinion: can we structure the code via files (and packages) instead of these ascii line separators? (Not blocking this PR)
|
|
||
| // Construct a VoteSet from the Commit and validator set. Panics | ||
| // if precommits from the commit can't be added to the voteset. | ||
| func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet { |
There was a problem hiding this comment.
These methods probably deserve tests to not decrease our test-coverage (?)
| const ( | ||
| BlockIDFlagAbsent BlockIDFlag = iota // vote is not included in the Commit.Precommits | ||
| BlockIDFlagCommit // voted for the Commit.BlockID | ||
| BlockIDFlagNil // voted for nil |
docs/architecture/adr-025-commit.md
Outdated
| to: | ||
| Note the need for an extra byte to indicate whether the signature is for the BlockID or for nil. | ||
| This byte can also be used to indicate an absent vote, rather than using a nil object like we currently do, | ||
| which has been [problematic for Amino](https://github.com/tendermint/go-amino/issues/260). |
There was a problem hiding this comment.
It rather is problematic for protobuf compatibility (but I think the linked issue is clear about this).
|
Ok added a test and fixed the note about amino |
…rmint#3298) * VoteSignBytes builds CanonicalVote * CommitVotes implements VoteSetReader - new CommitVotes struct holds both the Commit and the ValidatorSet and implements VoteSetReader - ToVote takes a ValidatorSet * fix TestCommit * use CommitSig.BlockID Commits may include votes for a different BlockID, could be nil, or different altogether. This means we can't use `commit.BlockID` for reconstructing the sign bytes, since up to -1/3 of the commits might be for independent BlockIDs. This means CommitSig will need to include an indicator for what BlockID it signed - if it's not the committed one or nil, it will need to include it fully in order to be verified. This is unfortunate but unavoidable so long as we include votes for non-committed BlockIDs (which we do to track validator liveness) * fixes from review * remove CommitVotes. CommitSig contains address * remove commit.canonicalVote method * toVote -> getVote, takes valIdx * update adr-025 * commit.ToVoteSet -> CommitToVoteSet * add test * fix from review
I believe this is the last commit necessary for #1648 before we make the actual breaking change.
That change will add
HeightandRoundfields directly in theCommitand change theCommitSigto be a struct with justTimestampandSignature.Wahoo!