Skip to content

types: CommitVotes struct as last step towards #1648#3298

Merged
liamsi merged 13 commits intodevelopfrom
bucky/1648-commit-votes
May 5, 2019
Merged

types: CommitVotes struct as last step towards #1648#3298
liamsi merged 13 commits intodevelopfrom
bucky/1648-commit-votes

Conversation

@ebuchman
Copy link
Contributor

I believe this is the last commit necessary for #1648 before we make the actual breaking change.

That change will add Height and Round fields directly in the Commit and change the CommitSig to be a struct with just Timestamp and Signature.

Wahoo!

  • Updated all relevant documentation in docs
  • Updated all code comments where relevant
  • Wrote tests
  • Updated CHANGELOG_PENDING.md

@ebuchman ebuchman requested a review from melekes as a code owner February 12, 2019 00:11
- new CommitVotes struct holds both the Commit and the ValidatorSet and
  implements VoteSetReader
- ToVote takes a ValidatorSet
Copy link
Contributor

@melekes melekes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏎

@melekes
Copy link
Contributor

melekes commented Feb 12, 2019

types/block_test.go:211:48: invalid operation: commit (variable of type *Commit) has no field or method GetByIndex (typecheck)
	assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0))

Copy link
Contributor Author

@ebuchman ebuchman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to fix the tests :)

@ebuchman
Copy link
Contributor Author

ebuchman commented Feb 13, 2019

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-io
Copy link

codecov-io commented Feb 13, 2019

Codecov Report

❗ No coverage uploaded for pull request base (develop@7b162f5). Click here to learn what that means.
The diff coverage is 0%.

@@            Coverage Diff             @@
##             develop    #3298   +/-   ##
==========================================
  Coverage           ?   64.06%           
==========================================
  Files              ?      213           
  Lines              ?    17495           
  Branches           ?        0           
==========================================
  Hits               ?    11208           
  Misses             ?     5353           
  Partials           ?      934
Impacted Files Coverage Δ
consensus/state.go 79.38% <0%> (ø)

@melekes
Copy link
Contributor

melekes commented Mar 26, 2019

What's left here? Adding a sleep #3298 (comment)?

@ebuchman
Copy link
Contributor Author

What's left here?

  1. Write tests for the current code (not the code in this PR) for the case where the block includes commits for nil or for the wrong block ID (this is supposed to be allowed, as long as +2/3 of the votes are for the right block ID) - types: test block commits with votes for the wrong blockID #3484
  2. Answer consensus: Do we need to allow votes in the commit for the wrong block ID? #3485 and change the block protocol accordingly. This should cause tests from (1) to fail, which should thus be updated.
  3. Update this PR according to the outcome of (2)
  4. Update the ADR-25 as necessary.

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:

  1. Don't track it, and when we verify the signature, if it fails for the right blockID then try verifying it against a nil vote. This requires no changes but is kind of hacky.

  2. Include a bool in the CommitSig, true if the vote is for the blockID, false if it's for nil

  3. Add an array to the Commit that is a list of validator indices that signed nil. If all votes are for the blockID, this would be empty

@ebuchman
Copy link
Contributor Author

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

@ebuchman
Copy link
Contributor Author

What's left here? Adding a sleep #3298 (comment)?

So yes, that's probably the only thing left here!

Thanks @melekes

@xla xla changed the title CommitVotes struct as last step towards #1648 types: CommitVotes struct as last step towards #1648 Mar 27, 2019
@ebuchman ebuchman requested a review from xla as a code owner April 26, 2019 04:35
@ebuchman
Copy link
Contributor Author

Ok based on #3596 I think we want the CommitSig to have the ValidatorAddress, which simplifies this PR quite a bit.

Copy link
Contributor Author

@ebuchman ebuchman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More feedback. Will fix

Copy link
Contributor

@liamsi liamsi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look good to me! Happy to help out with follow-up work in a separate PR

return &v
}

//-------------------------------------
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potentially unpopular opinion: can we structure the code via files (and packages) instead of these ascii line separators? (Not blocking this PR)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


// 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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods probably deserve tests to not decrease our test-coverage (?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you're right.

const (
BlockIDFlagAbsent BlockIDFlag = iota // vote is not included in the Commit.Precommits
BlockIDFlagCommit // voted for the Commit.BlockID
BlockIDFlagNil // voted for nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

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).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It rather is problematic for protobuf compatibility (but I think the linked issue is clear about this).

@ebuchman
Copy link
Contributor Author

ebuchman commented May 5, 2019

Ok added a test and fixed the note about amino

Copy link
Contributor

@liamsi liamsi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks 👍

@liamsi liamsi merged commit 4905640 into develop May 5, 2019
@ebuchman ebuchman deleted the bucky/1648-commit-votes branch May 5, 2019 16:20
@melekes melekes mentioned this pull request May 7, 2019
36 tasks
@melekes melekes mentioned this pull request May 30, 2019
44 tasks
brapse pushed a commit to brapse/tendermint that referenced this pull request Jun 5, 2019
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants