mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-03 14:47:16 +00:00
types: change Commit to consist of just signatures (#4146)
* types: change `Commit` to consist of just signatures These are final changes towards removing votes from commit and leaving only signatures (see ADR-25) Fixes #1648 * bring back TestCommitToVoteSetWithVotesForAnotherBlockOrNilBlock + add absent flag to Vote to indicate that it's for another block * encode nil votes as CommitSig with BlockIDFlagAbsent + make Commit#Precommits array of non-pointers because precommit will never be nil * add NewCommitSigAbsent and Absent() funcs * uncomment validation in CommitSig#ValidateBasic * add comments to ValidatorSet funcs * add a changelog entry * break instead of continue continue does not make sense in these cases * types: rename Commit#Precommits to Signatures * swagger: fix /commit response * swagger: change block_id_flag type * fix merge conflicts
This commit is contained in:
+181
-127
@@ -73,7 +73,7 @@ func (b *Block) ValidateBasic() error {
|
||||
return errors.New("nil LastCommit")
|
||||
}
|
||||
if err := b.LastCommit.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("wrong LastCommit")
|
||||
return fmt.Errorf("wrong LastCommit: %v", err)
|
||||
}
|
||||
}
|
||||
if err := ValidateHash(b.LastCommitHash); err != nil {
|
||||
@@ -434,27 +434,112 @@ func (h *Header) StringIndented(indent string) string {
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
// CommitSig is a vote included in a Commit.
|
||||
// For now, it is identical to a vote,
|
||||
// but in the future it will contain fewer fields
|
||||
// to eliminate the redundancy in commits.
|
||||
// See https://github.com/tendermint/tendermint/issues/1648.
|
||||
type CommitSig Vote
|
||||
// BlockIDFlag indicates which BlockID the signature is for.
|
||||
type BlockIDFlag byte
|
||||
|
||||
// String returns the underlying Vote.String()
|
||||
func (cs *CommitSig) String() string {
|
||||
return cs.toVote().String()
|
||||
const (
|
||||
// BlockIDFlagAbsent - no vote was received from a validator.
|
||||
BlockIDFlagAbsent BlockIDFlag = iota + 1
|
||||
// BlockIDFlagCommit - voted for the Commit.BlockID.
|
||||
BlockIDFlagCommit
|
||||
// BlockIDFlagNil - voted for nil.
|
||||
BlockIDFlagNil
|
||||
)
|
||||
|
||||
// CommitSig is a part of the Vote included in a Commit.
|
||||
type CommitSig struct {
|
||||
BlockIDFlag BlockIDFlag `json:"block_id_flag"`
|
||||
ValidatorAddress Address `json:"validator_address"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Signature []byte `json:"signature"`
|
||||
}
|
||||
|
||||
// toVote converts the CommitSig to a vote.
|
||||
// TODO: deprecate for #1648. Converting to Vote will require
|
||||
// access to ValidatorSet.
|
||||
func (cs *CommitSig) toVote() *Vote {
|
||||
if cs == nil {
|
||||
return nil
|
||||
// NewCommitSigForBlock returns new CommitSig with BlockIDFlagCommit.
|
||||
func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) CommitSig {
|
||||
return CommitSig{
|
||||
BlockIDFlag: BlockIDFlagCommit,
|
||||
ValidatorAddress: valAddr,
|
||||
Timestamp: ts,
|
||||
Signature: signature,
|
||||
}
|
||||
v := Vote(*cs)
|
||||
return &v
|
||||
}
|
||||
|
||||
// NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other
|
||||
// fields are all empty.
|
||||
func NewCommitSigAbsent() CommitSig {
|
||||
return CommitSig{
|
||||
BlockIDFlag: BlockIDFlagAbsent,
|
||||
}
|
||||
}
|
||||
|
||||
// Absent returns true if CommitSig is absent.
|
||||
func (cs CommitSig) Absent() bool {
|
||||
return cs.BlockIDFlag == BlockIDFlagAbsent
|
||||
}
|
||||
|
||||
func (cs CommitSig) String() string {
|
||||
return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}",
|
||||
cmn.Fingerprint(cs.Signature),
|
||||
cmn.Fingerprint(cs.ValidatorAddress),
|
||||
cs.BlockIDFlag,
|
||||
CanonicalTime(cs.Timestamp))
|
||||
}
|
||||
|
||||
// BlockID returns the Commit's BlockID if CommitSig indicates signing,
|
||||
// otherwise - empty BlockID.
|
||||
func (cs CommitSig) BlockID(commitBlockID BlockID) BlockID {
|
||||
var blockID BlockID
|
||||
switch cs.BlockIDFlag {
|
||||
case BlockIDFlagAbsent:
|
||||
blockID = BlockID{}
|
||||
case BlockIDFlagCommit:
|
||||
blockID = commitBlockID
|
||||
case BlockIDFlagNil:
|
||||
blockID = BlockID{}
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown BlockIDFlag: %v", cs.BlockIDFlag))
|
||||
}
|
||||
return blockID
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation.
|
||||
func (cs CommitSig) ValidateBasic() error {
|
||||
switch cs.BlockIDFlag {
|
||||
case BlockIDFlagAbsent:
|
||||
case BlockIDFlagCommit:
|
||||
case BlockIDFlagNil:
|
||||
default:
|
||||
return fmt.Errorf("unknown BlockIDFlag: %v", cs.BlockIDFlag)
|
||||
}
|
||||
|
||||
switch cs.BlockIDFlag {
|
||||
case BlockIDFlagAbsent:
|
||||
if len(cs.ValidatorAddress) != 0 {
|
||||
return errors.New("validator address is present")
|
||||
}
|
||||
if !cs.Timestamp.IsZero() {
|
||||
return errors.New("time is present")
|
||||
}
|
||||
if len(cs.Signature) != 0 {
|
||||
return errors.New("signature is present")
|
||||
}
|
||||
default:
|
||||
if len(cs.ValidatorAddress) != crypto.AddressSize {
|
||||
return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
|
||||
crypto.AddressSize,
|
||||
len(cs.ValidatorAddress),
|
||||
)
|
||||
}
|
||||
// NOTE: Timestamp validation is subtle and handled elsewhere.
|
||||
if len(cs.Signature) == 0 {
|
||||
return errors.New("signature is missing")
|
||||
}
|
||||
if len(cs.Signature) > MaxSignatureSize {
|
||||
return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
@@ -462,40 +547,40 @@ func (cs *CommitSig) toVote() *Vote {
|
||||
// Commit contains the evidence that a block was committed by a set of validators.
|
||||
// NOTE: Commit is empty for height 1, but never nil.
|
||||
type Commit struct {
|
||||
// NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
|
||||
// Any peer with a block can gossip precommits by index with a peer without recalculating the
|
||||
// active ValidatorSet.
|
||||
BlockID BlockID `json:"block_id"`
|
||||
Precommits []*CommitSig `json:"precommits"`
|
||||
// NOTE: The signatures are in order of address to preserve the bonded
|
||||
// ValidatorSet order.
|
||||
// Any peer with a block can gossip signatures by index with a peer without
|
||||
// recalculating the active ValidatorSet.
|
||||
Height int64 `json:"height"`
|
||||
Round int `json:"round"`
|
||||
BlockID BlockID `json:"block_id"`
|
||||
Signatures []CommitSig `json:"signatures"`
|
||||
|
||||
// memoized in first call to corresponding method
|
||||
// NOTE: can't memoize in constructor because constructor
|
||||
// isn't used for unmarshaling
|
||||
height int64
|
||||
round int
|
||||
// Memoized in first call to corresponding method.
|
||||
// NOTE: can't memoize in constructor because constructor isn't used for
|
||||
// unmarshaling.
|
||||
hash cmn.HexBytes
|
||||
bitArray *cmn.BitArray
|
||||
}
|
||||
|
||||
// NewCommit returns a new Commit with the given blockID and precommits.
|
||||
// TODO: memoize ValidatorSet in constructor so votes can be easily reconstructed
|
||||
// from CommitSig after #1648.
|
||||
func NewCommit(blockID BlockID, precommits []*CommitSig) *Commit {
|
||||
// NewCommit returns a new Commit.
|
||||
func NewCommit(height int64, round int, blockID BlockID, commitSigs []CommitSig) *Commit {
|
||||
return &Commit{
|
||||
Height: height,
|
||||
Round: round,
|
||||
BlockID: blockID,
|
||||
Precommits: precommits,
|
||||
Signatures: commitSigs,
|
||||
}
|
||||
}
|
||||
|
||||
// Construct a VoteSet from the Commit and validator set. Panics
|
||||
// if precommits from the commit can't be added to the voteset.
|
||||
// CommitToVoteSet constructs a VoteSet from the Commit and validator set.
|
||||
// Panics if signatures from the commit can't be added to the voteset.
|
||||
// Inverse of VoteSet.MakeCommit().
|
||||
func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet {
|
||||
height, round, typ := commit.Height(), commit.Round(), PrecommitType
|
||||
voteSet := NewVoteSet(chainID, height, round, typ, vals)
|
||||
for idx, precommit := range commit.Precommits {
|
||||
if precommit == nil {
|
||||
continue
|
||||
voteSet := NewVoteSet(chainID, commit.Height, commit.Round, PrecommitType, vals)
|
||||
for idx, commitSig := range commit.Signatures {
|
||||
if commitSig.Absent() {
|
||||
continue // OK, some precommits can be missing.
|
||||
}
|
||||
added, err := voteSet.AddVote(commit.GetVote(idx))
|
||||
if !added || err != nil {
|
||||
@@ -509,21 +594,12 @@ func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSe
|
||||
// Returns nil if the precommit at valIdx is nil.
|
||||
// Panics if valIdx >= commit.Size().
|
||||
func (commit *Commit) GetVote(valIdx int) *Vote {
|
||||
commitSig := commit.Precommits[valIdx]
|
||||
if commitSig == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NOTE: this commitSig might be for a nil blockID,
|
||||
// so we can't just use commit.BlockID here.
|
||||
// For #1648, CommitSig will need to indicate what BlockID it's for !
|
||||
blockID := commitSig.BlockID
|
||||
commit.memoizeHeightRound()
|
||||
commitSig := commit.Signatures[valIdx]
|
||||
return &Vote{
|
||||
Type: PrecommitType,
|
||||
Height: commit.height,
|
||||
Round: commit.round,
|
||||
BlockID: blockID,
|
||||
Height: commit.Height,
|
||||
Round: commit.Round,
|
||||
BlockID: commitSig.BlockID(commit.BlockID),
|
||||
Timestamp: commitSig.Timestamp,
|
||||
ValidatorAddress: commitSig.ValidatorAddress,
|
||||
ValidatorIndex: valIdx,
|
||||
@@ -539,58 +615,42 @@ func (commit *Commit) VoteSignBytes(chainID string, valIdx int) []byte {
|
||||
return commit.GetVote(valIdx).SignBytes(chainID)
|
||||
}
|
||||
|
||||
// memoizeHeightRound memoizes the height and round of the commit using
|
||||
// the first non-nil vote.
|
||||
// Should be called before any attempt to access `commit.height` or `commit.round`.
|
||||
func (commit *Commit) memoizeHeightRound() {
|
||||
if len(commit.Precommits) == 0 {
|
||||
return
|
||||
}
|
||||
if commit.height > 0 {
|
||||
return
|
||||
}
|
||||
for _, precommit := range commit.Precommits {
|
||||
if precommit != nil {
|
||||
commit.height = precommit.Height
|
||||
commit.round = precommit.Round
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Height returns the height of the commit
|
||||
func (commit *Commit) Height() int64 {
|
||||
commit.memoizeHeightRound()
|
||||
return commit.height
|
||||
}
|
||||
|
||||
// Round returns the round of the commit
|
||||
func (commit *Commit) Round() int {
|
||||
commit.memoizeHeightRound()
|
||||
return commit.round
|
||||
}
|
||||
|
||||
// Type returns the vote type of the commit, which is always VoteTypePrecommit
|
||||
// Implements VoteSetReader.
|
||||
func (commit *Commit) Type() byte {
|
||||
return byte(PrecommitType)
|
||||
}
|
||||
|
||||
// Size returns the number of votes in the commit
|
||||
// GetHeight returns height of the commit.
|
||||
// Implements VoteSetReader.
|
||||
func (commit *Commit) GetHeight() int64 {
|
||||
return commit.Height
|
||||
}
|
||||
|
||||
// GetRound returns height of the commit.
|
||||
// Implements VoteSetReader.
|
||||
func (commit *Commit) GetRound() int {
|
||||
return commit.Round
|
||||
}
|
||||
|
||||
// Size returns the number of signatures in the commit.
|
||||
// Implements VoteSetReader.
|
||||
func (commit *Commit) Size() int {
|
||||
if commit == nil {
|
||||
return 0
|
||||
}
|
||||
return len(commit.Precommits)
|
||||
return len(commit.Signatures)
|
||||
}
|
||||
|
||||
// BitArray returns a BitArray of which validators voted in this commit
|
||||
// BitArray returns a BitArray of which validators voted for BlockID or nil in this commit.
|
||||
// Implements VoteSetReader.
|
||||
func (commit *Commit) BitArray() *cmn.BitArray {
|
||||
if commit.bitArray == nil {
|
||||
commit.bitArray = cmn.NewBitArray(len(commit.Precommits))
|
||||
for i, precommit := range commit.Precommits {
|
||||
commit.bitArray = cmn.NewBitArray(len(commit.Signatures))
|
||||
for i, commitSig := range commit.Signatures {
|
||||
// TODO: need to check the BlockID otherwise we could be counting conflicts,
|
||||
// not just the one with +2/3 !
|
||||
commit.bitArray.SetIndex(i, precommit != nil)
|
||||
commit.bitArray.SetIndex(i, !commitSig.Absent())
|
||||
}
|
||||
}
|
||||
return commit.bitArray
|
||||
@@ -603,44 +663,35 @@ func (commit *Commit) GetByIndex(valIdx int) *Vote {
|
||||
return commit.GetVote(valIdx)
|
||||
}
|
||||
|
||||
// IsCommit returns true if there is at least one vote.
|
||||
// IsCommit returns true if there is at least one signature.
|
||||
// Implements VoteSetReader.
|
||||
func (commit *Commit) IsCommit() bool {
|
||||
return len(commit.Precommits) != 0
|
||||
return len(commit.Signatures) != 0
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation that doesn't involve state data.
|
||||
// Does not actually check the cryptographic signatures.
|
||||
func (commit *Commit) ValidateBasic() error {
|
||||
if commit.Height < 0 {
|
||||
return errors.New("negative Height")
|
||||
}
|
||||
if commit.Round < 0 {
|
||||
return errors.New("negative Round")
|
||||
}
|
||||
|
||||
if commit.BlockID.IsZero() {
|
||||
return errors.New("commit cannot be for nil block")
|
||||
}
|
||||
if len(commit.Precommits) == 0 {
|
||||
return errors.New("no precommits in commit")
|
||||
}
|
||||
height, round := commit.Height(), commit.Round()
|
||||
|
||||
// Validate the precommits.
|
||||
for _, precommit := range commit.Precommits {
|
||||
// It's OK for precommits to be missing.
|
||||
if precommit == nil {
|
||||
continue
|
||||
}
|
||||
// Ensure that all votes are precommits.
|
||||
if precommit.Type != PrecommitType {
|
||||
return fmt.Errorf("invalid commit vote. Expected precommit, got %v",
|
||||
precommit.Type)
|
||||
}
|
||||
// Ensure that all heights are the same.
|
||||
if precommit.Height != height {
|
||||
return fmt.Errorf("invalid commit precommit height. Expected %v, got %v",
|
||||
height, precommit.Height)
|
||||
}
|
||||
// Ensure that all rounds are the same.
|
||||
if precommit.Round != round {
|
||||
return fmt.Errorf("invalid commit precommit round. Expected %v, got %v",
|
||||
round, precommit.Round)
|
||||
if len(commit.Signatures) == 0 {
|
||||
return errors.New("no signatures in commit")
|
||||
}
|
||||
for i, commitSig := range commit.Signatures {
|
||||
if err := commitSig.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("wrong CommitSig #%d: %v", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -650,9 +701,9 @@ func (commit *Commit) Hash() cmn.HexBytes {
|
||||
return nil
|
||||
}
|
||||
if commit.hash == nil {
|
||||
bs := make([][]byte, len(commit.Precommits))
|
||||
for i, precommit := range commit.Precommits {
|
||||
bs[i] = cdcEncode(precommit)
|
||||
bs := make([][]byte, len(commit.Signatures))
|
||||
for i, commitSig := range commit.Signatures {
|
||||
bs[i] = cdcEncode(commitSig)
|
||||
}
|
||||
commit.hash = merkle.SimpleHashFromByteSlices(bs)
|
||||
}
|
||||
@@ -664,18 +715,22 @@ func (commit *Commit) StringIndented(indent string) string {
|
||||
if commit == nil {
|
||||
return "nil-Commit"
|
||||
}
|
||||
precommitStrings := make([]string, len(commit.Precommits))
|
||||
for i, precommit := range commit.Precommits {
|
||||
precommitStrings[i] = precommit.String()
|
||||
commitSigStrings := make([]string, len(commit.Signatures))
|
||||
for i, commitSig := range commit.Signatures {
|
||||
commitSigStrings[i] = commitSig.String()
|
||||
}
|
||||
return fmt.Sprintf(`Commit{
|
||||
%s Height: %d
|
||||
%s Round: %d
|
||||
%s BlockID: %v
|
||||
%s Precommits:
|
||||
%s Signatures:
|
||||
%s %v
|
||||
%s}#%v`,
|
||||
indent, commit.Height,
|
||||
indent, commit.Round,
|
||||
indent, commit.BlockID,
|
||||
indent,
|
||||
indent, strings.Join(precommitStrings, "\n"+indent+" "),
|
||||
indent, strings.Join(commitSigStrings, "\n"+indent+" "),
|
||||
indent, commit.hash)
|
||||
}
|
||||
|
||||
@@ -695,7 +750,6 @@ type SignedHeader struct {
|
||||
// sure to use a Verifier to validate the signatures actually provide a
|
||||
// significantly strong proof for this header's validity.
|
||||
func (sh SignedHeader) ValidateBasic(chainID string) error {
|
||||
|
||||
// Make sure the header is consistent with the commit.
|
||||
if sh.Header == nil {
|
||||
return errors.New("signedHeader missing header")
|
||||
@@ -710,9 +764,9 @@ func (sh SignedHeader) ValidateBasic(chainID string) error {
|
||||
sh.ChainID, chainID)
|
||||
}
|
||||
// Check Height.
|
||||
if sh.Commit.Height() != sh.Height {
|
||||
if sh.Commit.Height != sh.Height {
|
||||
return fmt.Errorf("signedHeader header and commit height mismatch: %v vs %v",
|
||||
sh.Height, sh.Commit.Height())
|
||||
sh.Height, sh.Commit.Height)
|
||||
}
|
||||
// Check Hash.
|
||||
hhash := sh.Hash()
|
||||
|
||||
+31
-29
@@ -70,7 +70,7 @@ func TestBlockValidateBasic(t *testing.T) {
|
||||
{"Make Block w/ proposer Addr", func(blk *Block) { blk.ProposerAddress = valSet.GetProposer().Address }, false},
|
||||
{"Negative Height", func(blk *Block) { blk.Height = -1 }, true},
|
||||
{"Remove 1/2 the commits", func(blk *Block) {
|
||||
blk.LastCommit.Precommits = commit.Precommits[:commit.Size()/2]
|
||||
blk.LastCommit.Signatures = commit.Signatures[:commit.Size()/2]
|
||||
blk.LastCommit.hash = nil // clear hash or change wont be noticed
|
||||
}, true},
|
||||
{"Remove LastCommitHash", func(blk *Block) { blk.LastCommitHash = []byte("something else") }, true},
|
||||
@@ -124,7 +124,7 @@ func TestBlockMakePartSetWithEvidence(t *testing.T) {
|
||||
ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address)
|
||||
evList := []Evidence{ev}
|
||||
|
||||
partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(1024)
|
||||
partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(512)
|
||||
assert.NotNil(t, partSet)
|
||||
assert.Equal(t, 3, partSet.Total())
|
||||
}
|
||||
@@ -167,23 +167,29 @@ func TestBlockString(t *testing.T) {
|
||||
}
|
||||
|
||||
func makeBlockIDRandom() BlockID {
|
||||
blockHash := make([]byte, tmhash.Size)
|
||||
partSetHash := make([]byte, tmhash.Size)
|
||||
var (
|
||||
blockHash = make([]byte, tmhash.Size)
|
||||
partSetHash = make([]byte, tmhash.Size)
|
||||
)
|
||||
rand.Read(blockHash) //nolint: gosec
|
||||
rand.Read(partSetHash) //nolint: gosec
|
||||
blockPartsHeader := PartSetHeader{123, partSetHash}
|
||||
return BlockID{blockHash, blockPartsHeader}
|
||||
return BlockID{blockHash, PartSetHeader{123, partSetHash}}
|
||||
}
|
||||
|
||||
func makeBlockID(hash []byte, partSetSize int, partSetHash []byte) BlockID {
|
||||
var (
|
||||
h = make([]byte, tmhash.Size)
|
||||
psH = make([]byte, tmhash.Size)
|
||||
)
|
||||
copy(h, hash)
|
||||
copy(psH, partSetHash)
|
||||
return BlockID{
|
||||
Hash: hash,
|
||||
Hash: h,
|
||||
PartsHeader: PartSetHeader{
|
||||
Total: partSetSize,
|
||||
Hash: partSetHash,
|
||||
Hash: psH,
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var nilBytes []byte
|
||||
@@ -205,8 +211,8 @@ func TestCommit(t *testing.T) {
|
||||
commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, h-1, commit.Height())
|
||||
assert.Equal(t, 1, commit.Round())
|
||||
assert.Equal(t, h-1, commit.Height)
|
||||
assert.Equal(t, 1, commit.Round)
|
||||
assert.Equal(t, PrecommitType, SignedMsgType(commit.Type()))
|
||||
if commit.Size() <= 0 {
|
||||
t.Fatalf("commit %v has a zero or negative size: %d", commit, commit.Size())
|
||||
@@ -226,11 +232,9 @@ func TestCommitValidateBasic(t *testing.T) {
|
||||
expectErr bool
|
||||
}{
|
||||
{"Random Commit", func(com *Commit) {}, false},
|
||||
{"Nil precommit", func(com *Commit) { com.Precommits[0] = nil }, false},
|
||||
{"Incorrect signature", func(com *Commit) { com.Precommits[0].Signature = []byte{0} }, false},
|
||||
{"Incorrect type", func(com *Commit) { com.Precommits[0].Type = PrevoteType }, true},
|
||||
{"Incorrect height", func(com *Commit) { com.Precommits[0].Height = int64(100) }, true},
|
||||
{"Incorrect round", func(com *Commit) { com.Precommits[0].Round = 100 }, true},
|
||||
{"Incorrect signature", func(com *Commit) { com.Signatures[0].Signature = []byte{0} }, false},
|
||||
{"Incorrect height", func(com *Commit) { com.Height = int64(-100) }, true},
|
||||
{"Incorrect round", func(com *Commit) { com.Round = -100 }, true},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
@@ -444,13 +448,13 @@ func TestCommitToVoteSet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitToVoteSetWithVotesForAnotherBlockOrNilBlock(t *testing.T) {
|
||||
func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) {
|
||||
blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
|
||||
blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
|
||||
blockID3 := makeBlockID([]byte("blockhash3"), 10000, []byte("partshash"))
|
||||
|
||||
height := int64(3)
|
||||
round := 1
|
||||
const (
|
||||
height = int64(3)
|
||||
round = 0
|
||||
)
|
||||
|
||||
type commitVoteTest struct {
|
||||
blockIDs []BlockID
|
||||
@@ -460,16 +464,11 @@ func TestCommitToVoteSetWithVotesForAnotherBlockOrNilBlock(t *testing.T) {
|
||||
}
|
||||
|
||||
testCases := []commitVoteTest{
|
||||
{[]BlockID{blockID, blockID2, blockID3}, []int{8, 1, 1}, 10, true},
|
||||
{[]BlockID{blockID, blockID2, blockID3}, []int{67, 20, 13}, 100, true},
|
||||
{[]BlockID{blockID, blockID2, blockID3}, []int{1, 1, 1}, 3, false},
|
||||
{[]BlockID{blockID, blockID2, blockID3}, []int{3, 1, 1}, 5, false},
|
||||
{[]BlockID{blockID, {}}, []int{67, 33}, 100, true},
|
||||
{[]BlockID{blockID, blockID2, {}}, []int{10, 5, 5}, 20, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
voteSet, valSet, vals := randVoteSet(height-1, 1, PrecommitType, tc.numValidators, 1)
|
||||
voteSet, valSet, vals := randVoteSet(height-1, round, PrecommitType, tc.numValidators, 1)
|
||||
|
||||
vi := 0
|
||||
for n := range tc.blockIDs {
|
||||
@@ -485,11 +484,14 @@ func TestCommitToVoteSetWithVotesForAnotherBlockOrNilBlock(t *testing.T) {
|
||||
Timestamp: tmtime.Now(),
|
||||
}
|
||||
|
||||
_, err := signAddVote(vals[vi], vote, voteSet)
|
||||
added, err := signAddVote(vals[vi], vote, voteSet)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, added)
|
||||
|
||||
vi++
|
||||
}
|
||||
}
|
||||
|
||||
if tc.valid {
|
||||
commit := voteSet.MakeCommit() // panics without > 2/3 valid votes
|
||||
assert.NotNil(t, commit)
|
||||
@@ -508,7 +510,7 @@ func TestSignedHeaderValidateBasic(t *testing.T) {
|
||||
h := Header{
|
||||
Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64},
|
||||
ChainID: chainID,
|
||||
Height: commit.Height(),
|
||||
Height: commit.Height,
|
||||
Time: timestamp,
|
||||
LastBlockID: commit.BlockID,
|
||||
LastCommitHash: commit.Hash(),
|
||||
|
||||
+6
-6
@@ -10,9 +10,9 @@ type (
|
||||
Actual int64
|
||||
}
|
||||
|
||||
// ErrInvalidCommitPrecommits is returned when we encounter a commit where
|
||||
// the number of precommits doesn't match the number of validators.
|
||||
ErrInvalidCommitPrecommits struct {
|
||||
// ErrInvalidCommitSignatures is returned when we encounter a commit where
|
||||
// the number of signatures doesn't match the number of validators.
|
||||
ErrInvalidCommitSignatures struct {
|
||||
Expected int
|
||||
Actual int
|
||||
}
|
||||
@@ -29,13 +29,13 @@ func (e ErrInvalidCommitHeight) Error() string {
|
||||
return fmt.Sprintf("Invalid commit -- wrong height: %v vs %v", e.Expected, e.Actual)
|
||||
}
|
||||
|
||||
func NewErrInvalidCommitPrecommits(expected, actual int) ErrInvalidCommitPrecommits {
|
||||
return ErrInvalidCommitPrecommits{
|
||||
func NewErrInvalidCommitSignatures(expected, actual int) ErrInvalidCommitSignatures {
|
||||
return ErrInvalidCommitSignatures{
|
||||
Expected: expected,
|
||||
Actual: actual,
|
||||
}
|
||||
}
|
||||
|
||||
func (e ErrInvalidCommitPrecommits) Error() string {
|
||||
func (e ErrInvalidCommitSignatures) Error() string {
|
||||
return fmt.Sprintf("Invalid commit -- wrong set size: %v vs %v", e.Expected, e.Actual)
|
||||
}
|
||||
|
||||
+55
-69
@@ -14,18 +14,17 @@ import (
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
)
|
||||
|
||||
// MaxTotalVotingPower - the maximum allowed total voting power.
|
||||
// It needs to be sufficiently small to, in all cases:
|
||||
// 1. prevent clipping in incrementProposerPriority()
|
||||
// 2. let (diff+diffMax-1) not overflow in IncrementProposerPriority()
|
||||
// (Proof of 1 is tricky, left to the reader).
|
||||
// It could be higher, but this is sufficiently large for our purposes,
|
||||
// and leaves room for defensive purposes.
|
||||
// PriorityWindowSizeFactor - is a constant that when multiplied with the total voting power gives
|
||||
// the maximum allowed distance between validator priorities.
|
||||
|
||||
const (
|
||||
MaxTotalVotingPower = int64(math.MaxInt64) / 8
|
||||
// MaxTotalVotingPower - the maximum allowed total voting power.
|
||||
// It needs to be sufficiently small to, in all cases:
|
||||
// 1. prevent clipping in incrementProposerPriority()
|
||||
// 2. let (diff+diffMax-1) not overflow in IncrementProposerPriority()
|
||||
// (Proof of 1 is tricky, left to the reader).
|
||||
// It could be higher, but this is sufficiently large for our purposes,
|
||||
// and leaves room for defensive purposes.
|
||||
MaxTotalVotingPower = int64(math.MaxInt64) / 8
|
||||
// PriorityWindowSizeFactor - is a constant that when multiplied with the total voting power gives
|
||||
// the maximum allowed distance between validator priorities.
|
||||
PriorityWindowSizeFactor = 2
|
||||
)
|
||||
|
||||
@@ -67,12 +66,13 @@ func NewValidatorSet(valz []*Validator) *ValidatorSet {
|
||||
return vals
|
||||
}
|
||||
|
||||
// Nil or empty validator sets are invalid.
|
||||
// IsNilOrEmpty returns true if validator set is nil or empty.
|
||||
func (vals *ValidatorSet) IsNilOrEmpty() bool {
|
||||
return vals == nil || len(vals.Validators) == 0
|
||||
}
|
||||
|
||||
// Increment ProposerPriority and update the proposer on a copy, and return it.
|
||||
// CopyIncrementProposerPriority increments ProposerPriority and update the
|
||||
// proposer on a copy, and return it.
|
||||
func (vals *ValidatorSet) CopyIncrementProposerPriority(times int) *ValidatorSet {
|
||||
copy := vals.Copy()
|
||||
copy.IncrementProposerPriority(times)
|
||||
@@ -106,6 +106,7 @@ func (vals *ValidatorSet) IncrementProposerPriority(times int) {
|
||||
vals.Proposer = proposer
|
||||
}
|
||||
|
||||
// RescalePriorities ...
|
||||
func (vals *ValidatorSet) RescalePriorities(diffMax int64) {
|
||||
if vals.IsNilOrEmpty() {
|
||||
panic("empty validator set")
|
||||
@@ -177,9 +178,8 @@ func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 {
|
||||
diff := max - min
|
||||
if diff < 0 {
|
||||
return -1 * diff
|
||||
} else {
|
||||
return diff
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
func (vals *ValidatorSet) getValWithMostPriority() *Validator {
|
||||
@@ -594,22 +594,21 @@ func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error {
|
||||
return vals.updateWithChangeSet(changes, true)
|
||||
}
|
||||
|
||||
// VerifyCommit verifies that +2/3 of the validator set signed this commit.
|
||||
func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height int64, commit *Commit) error {
|
||||
if vals.Size() != len(commit.Precommits) {
|
||||
return NewErrInvalidCommitPrecommits(vals.Size(), len(commit.Precommits))
|
||||
// VerifyCommit verifies +2/3 of the set had signed the given commit.
|
||||
func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID,
|
||||
height int64, commit *Commit) error {
|
||||
|
||||
if vals.Size() != len(commit.Signatures) {
|
||||
return NewErrInvalidCommitSignatures(vals.Size(), len(commit.Signatures))
|
||||
}
|
||||
if err := vals.verifyCommitBasic(commit, height, blockID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
talliedVotingPower := int64(0)
|
||||
for idx, precommit := range commit.Precommits {
|
||||
// skip absent and nil votes
|
||||
// NOTE: do we want to check the validity of votes
|
||||
// for nil?
|
||||
if precommit == nil {
|
||||
continue // OK, some precommits can be missing.
|
||||
for idx, commitSig := range commit.Signatures {
|
||||
if commitSig.Absent() {
|
||||
continue // OK, some signatures can be absent.
|
||||
}
|
||||
|
||||
// The vals and commit have a 1-to-1 correspondance.
|
||||
@@ -617,17 +616,17 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i
|
||||
val := vals.Validators[idx]
|
||||
|
||||
// Validate signature.
|
||||
precommitSignBytes := commit.VoteSignBytes(chainID, idx)
|
||||
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
||||
return fmt.Errorf("invalid commit -- invalid signature: %v", precommit)
|
||||
voteSignBytes := commit.VoteSignBytes(chainID, idx)
|
||||
if !val.PubKey.VerifyBytes(voteSignBytes, commitSig.Signature) {
|
||||
return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature)
|
||||
}
|
||||
// Good precommit!
|
||||
if blockID.Equals(precommit.BlockID) {
|
||||
// Good!
|
||||
if blockID.Equals(commitSig.BlockID(commit.BlockID)) {
|
||||
talliedVotingPower += val.VotingPower
|
||||
}
|
||||
// else {
|
||||
// It's OK that the BlockID doesn't match. We include stray
|
||||
// precommits to measure validator availability.
|
||||
// signatures (~votes for nil) to measure validator availability.
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -680,40 +679,31 @@ func (vals *ValidatorSet) VerifyFutureCommit(newSet *ValidatorSet, chainID strin
|
||||
// Check old voting power.
|
||||
oldVotingPower := int64(0)
|
||||
seen := map[int]bool{}
|
||||
round := commit.Round()
|
||||
|
||||
for idx, precommit := range commit.Precommits {
|
||||
if precommit == nil {
|
||||
continue
|
||||
}
|
||||
if precommit.Height != height {
|
||||
return errors.Errorf("blocks don't match - %d vs %d", round, precommit.Round)
|
||||
}
|
||||
if precommit.Round != round {
|
||||
return errors.Errorf("invalid commit -- wrong round: %v vs %v", round, precommit.Round)
|
||||
}
|
||||
if precommit.Type != PrecommitType {
|
||||
return errors.Errorf("invalid commit -- not precommit @ index %v", idx)
|
||||
for idx, commitSig := range commit.Signatures {
|
||||
if commitSig.Absent() {
|
||||
continue // OK, some signatures can be absent.
|
||||
}
|
||||
|
||||
// See if this validator is in oldVals.
|
||||
oldIdx, val := oldVals.GetByAddress(precommit.ValidatorAddress)
|
||||
oldIdx, val := oldVals.GetByAddress(commitSig.ValidatorAddress)
|
||||
if val == nil || seen[oldIdx] {
|
||||
continue // missing or double vote...
|
||||
}
|
||||
seen[oldIdx] = true
|
||||
|
||||
// Validate signature.
|
||||
precommitSignBytes := commit.VoteSignBytes(chainID, idx)
|
||||
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
||||
return errors.Errorf("invalid commit -- invalid signature: %v", precommit)
|
||||
voteSignBytes := commit.VoteSignBytes(chainID, idx)
|
||||
if !val.PubKey.VerifyBytes(voteSignBytes, commitSig.Signature) {
|
||||
return errors.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature)
|
||||
}
|
||||
// Good precommit!
|
||||
if blockID.Equals(precommit.BlockID) {
|
||||
// Good!
|
||||
if blockID.Equals(commitSig.BlockID(commit.BlockID)) {
|
||||
oldVotingPower += val.VotingPower
|
||||
}
|
||||
// else {
|
||||
// It's OK that the BlockID doesn't match. We include stray
|
||||
// precommits to measure validator availability.
|
||||
// signatures (~votes for nil) to measure validator availability.
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -740,31 +730,28 @@ func (vals *ValidatorSet) VerifyCommitTrusting(chainID string, blockID BlockID,
|
||||
}
|
||||
|
||||
talliedVotingPower := int64(0)
|
||||
for idx, precommit := range commit.Precommits {
|
||||
// skip absent and nil votes
|
||||
// NOTE: do we want to check the validity of votes
|
||||
// for nil?
|
||||
if precommit == nil {
|
||||
continue
|
||||
for idx, commitSig := range commit.Signatures {
|
||||
if commitSig.Absent() {
|
||||
continue // OK, some signatures can be absent.
|
||||
}
|
||||
|
||||
// We don't know the validators that committed this block, so we have to
|
||||
// check for each vote if its validator is already known.
|
||||
_, val := vals.GetByAddress(precommit.ValidatorAddress)
|
||||
_, val := vals.GetByAddress(commitSig.ValidatorAddress)
|
||||
if val != nil {
|
||||
// Validate signature.
|
||||
precommitSignBytes := commit.VoteSignBytes(chainID, idx)
|
||||
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
||||
return fmt.Errorf("invalid commit -- invalid signature: %v", precommit)
|
||||
voteSignBytes := commit.VoteSignBytes(chainID, idx)
|
||||
if !val.PubKey.VerifyBytes(voteSignBytes, commitSig.Signature) {
|
||||
return errors.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature)
|
||||
}
|
||||
|
||||
// Good precommit!
|
||||
if blockID.Equals(precommit.BlockID) {
|
||||
// Good!
|
||||
if blockID.Equals(commitSig.BlockID(commit.BlockID)) {
|
||||
talliedVotingPower += val.VotingPower
|
||||
}
|
||||
// else {
|
||||
// It's OK that the BlockID doesn't match. We include stray
|
||||
// precommits to measure validator availability.
|
||||
// signatures (~votes for nil) to measure validator availability.
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -782,8 +769,8 @@ func (vals *ValidatorSet) verifyCommitBasic(commit *Commit, height int64, blockI
|
||||
if err := commit.ValidateBasic(); err != nil {
|
||||
return err
|
||||
}
|
||||
if height != commit.Height() {
|
||||
return NewErrInvalidCommitHeight(height, commit.Height())
|
||||
if height != commit.Height {
|
||||
return NewErrInvalidCommitHeight(height, commit.Height)
|
||||
}
|
||||
if !blockID.Equals(commit.BlockID) {
|
||||
return fmt.Errorf("invalid commit -- wrong block ID: want %v, got %v",
|
||||
@@ -797,7 +784,6 @@ func (vals *ValidatorSet) verifyCommitBasic(commit *Commit, height int64, blockI
|
||||
|
||||
// IsErrTooMuchChange returns true if err is related to changes in validator
|
||||
// set exceeding max limit.
|
||||
// TODO: remove
|
||||
func IsErrTooMuchChange(err error) bool {
|
||||
_, ok := errors.Cause(err).(ErrTooMuchChange)
|
||||
return ok
|
||||
@@ -819,7 +805,7 @@ func (vals *ValidatorSet) String() string {
|
||||
return vals.StringIndented("")
|
||||
}
|
||||
|
||||
// String
|
||||
// StringIndented returns an intended string representation of ValidatorSet.
|
||||
func (vals *ValidatorSet) StringIndented(indent string) string {
|
||||
if vals == nil {
|
||||
return "nil-ValidatorSet"
|
||||
@@ -844,7 +830,7 @@ func (vals *ValidatorSet) StringIndented(indent string) string {
|
||||
//-------------------------------------
|
||||
// Implements sort for sorting validators by address.
|
||||
|
||||
// Sort validators by address.
|
||||
// ValidatorsByAddress is used to sort validators by address.
|
||||
type ValidatorsByAddress []*Validator
|
||||
|
||||
func (valz ValidatorsByAddress) Len() int {
|
||||
|
||||
@@ -602,9 +602,12 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
||||
v1 := NewValidator(pubKey, 1000)
|
||||
vset := NewValidatorSet([]*Validator{v1})
|
||||
|
||||
chainID := "mychainID"
|
||||
blockID := BlockID{Hash: []byte("hello")}
|
||||
height := int64(5)
|
||||
// good
|
||||
var (
|
||||
chainID = "mychainID"
|
||||
blockID = makeBlockIDRandom()
|
||||
height = int64(5)
|
||||
)
|
||||
vote := &Vote{
|
||||
ValidatorAddress: v1.Address,
|
||||
ValidatorIndex: 0,
|
||||
@@ -617,12 +620,15 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
||||
sig, err := privKey.Sign(vote.SignBytes(chainID))
|
||||
assert.NoError(t, err)
|
||||
vote.Signature = sig
|
||||
commit := NewCommit(blockID, []*CommitSig{vote.CommitSig()})
|
||||
commit := NewCommit(vote.Height, vote.Round, blockID, []CommitSig{vote.CommitSig()})
|
||||
|
||||
badChainID := "notmychainID"
|
||||
badBlockID := BlockID{Hash: []byte("goodbye")}
|
||||
badHeight := height + 1
|
||||
badCommit := NewCommit(blockID, []*CommitSig{nil})
|
||||
// bad
|
||||
var (
|
||||
badChainID = "notmychainID"
|
||||
badBlockID = BlockID{Hash: []byte("goodbye")}
|
||||
badHeight = height + 1
|
||||
badCommit = NewCommit(badHeight, 0, blockID, []CommitSig{{BlockIDFlag: BlockIDFlagAbsent}})
|
||||
)
|
||||
|
||||
// test some error cases
|
||||
// TODO: test more cases!
|
||||
|
||||
+20
-5
@@ -57,13 +57,27 @@ type Vote struct {
|
||||
}
|
||||
|
||||
// CommitSig converts the Vote to a CommitSig.
|
||||
// If the Vote is nil, the CommitSig will be nil.
|
||||
func (vote *Vote) CommitSig() *CommitSig {
|
||||
func (vote *Vote) CommitSig() CommitSig {
|
||||
if vote == nil {
|
||||
return nil
|
||||
return NewCommitSigAbsent()
|
||||
}
|
||||
|
||||
var blockIDFlag BlockIDFlag
|
||||
switch {
|
||||
case vote.BlockID.IsComplete():
|
||||
blockIDFlag = BlockIDFlagCommit
|
||||
case vote.BlockID.IsZero():
|
||||
blockIDFlag = BlockIDFlagNil
|
||||
default:
|
||||
panic(fmt.Sprintf("Invalid vote %v - expected BlockID to be either empty or complete", vote))
|
||||
}
|
||||
|
||||
return CommitSig{
|
||||
BlockIDFlag: blockIDFlag,
|
||||
ValidatorAddress: vote.ValidatorAddress,
|
||||
Timestamp: vote.Timestamp,
|
||||
Signature: vote.Signature,
|
||||
}
|
||||
cs := CommitSig(*vote)
|
||||
return &cs
|
||||
}
|
||||
|
||||
func (vote *Vote) SignBytes(chainID string) []byte {
|
||||
@@ -83,6 +97,7 @@ func (vote *Vote) String() string {
|
||||
if vote == nil {
|
||||
return nilVoteStr
|
||||
}
|
||||
|
||||
var typeString string
|
||||
switch vote.Type {
|
||||
case PrevoteType:
|
||||
|
||||
+14
-6
@@ -98,20 +98,23 @@ func (voteSet *VoteSet) ChainID() string {
|
||||
return voteSet.chainID
|
||||
}
|
||||
|
||||
func (voteSet *VoteSet) Height() int64 {
|
||||
// Implements VoteSetReader.
|
||||
func (voteSet *VoteSet) GetHeight() int64 {
|
||||
if voteSet == nil {
|
||||
return 0
|
||||
}
|
||||
return voteSet.height
|
||||
}
|
||||
|
||||
func (voteSet *VoteSet) Round() int {
|
||||
// Implements VoteSetReader.
|
||||
func (voteSet *VoteSet) GetRound() int {
|
||||
if voteSet == nil {
|
||||
return -1
|
||||
}
|
||||
return voteSet.round
|
||||
}
|
||||
|
||||
// Implements VoteSetReader.
|
||||
func (voteSet *VoteSet) Type() byte {
|
||||
if voteSet == nil {
|
||||
return 0x00
|
||||
@@ -119,6 +122,7 @@ func (voteSet *VoteSet) Type() byte {
|
||||
return byte(voteSet.type_)
|
||||
}
|
||||
|
||||
// Implements VoteSetReader.
|
||||
func (voteSet *VoteSet) Size() int {
|
||||
if voteSet == nil {
|
||||
return 0
|
||||
@@ -335,6 +339,7 @@ func (voteSet *VoteSet) SetPeerMaj23(peerID P2PID, blockID BlockID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implements VoteSetReader.
|
||||
func (voteSet *VoteSet) BitArray() *cmn.BitArray {
|
||||
if voteSet == nil {
|
||||
return nil
|
||||
@@ -358,6 +363,7 @@ func (voteSet *VoteSet) BitArrayByBlockID(blockID BlockID) *cmn.BitArray {
|
||||
}
|
||||
|
||||
// NOTE: if validator has conflicting votes, returns "canonical" vote
|
||||
// Implements VoteSetReader.
|
||||
func (voteSet *VoteSet) GetByIndex(valIndex int) *Vote {
|
||||
if voteSet == nil {
|
||||
return nil
|
||||
@@ -389,6 +395,7 @@ func (voteSet *VoteSet) HasTwoThirdsMajority() bool {
|
||||
return voteSet.maj23 != nil
|
||||
}
|
||||
|
||||
// Implements VoteSetReader.
|
||||
func (voteSet *VoteSet) IsCommit() bool {
|
||||
if voteSet == nil {
|
||||
return false
|
||||
@@ -556,11 +563,12 @@ func (voteSet *VoteSet) MakeCommit() *Commit {
|
||||
}
|
||||
|
||||
// For every validator, get the precommit
|
||||
commitSigs := make([]*CommitSig, len(voteSet.votes))
|
||||
commitSigs := make([]CommitSig, len(voteSet.votes))
|
||||
for i, v := range voteSet.votes {
|
||||
commitSigs[i] = v.CommitSig()
|
||||
}
|
||||
return NewCommit(*voteSet.maj23, commitSigs)
|
||||
|
||||
return NewCommit(voteSet.GetHeight(), voteSet.GetRound(), *voteSet.maj23, commitSigs)
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
@@ -607,8 +615,8 @@ func (vs *blockVotes) getByIndex(index int) *Vote {
|
||||
|
||||
// Common interface between *consensus.VoteSet and types.Commit
|
||||
type VoteSetReader interface {
|
||||
Height() int64
|
||||
Round() int
|
||||
GetHeight() int64
|
||||
GetRound() int
|
||||
Type() byte
|
||||
Size() int
|
||||
BitArray() *cmn.BitArray
|
||||
|
||||
+15
-4
@@ -522,16 +522,27 @@ func TestMakeCommit(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// The 9th voted for nil.
|
||||
{
|
||||
addr := privValidators[8].GetPubKey().Address()
|
||||
vote := withValidator(voteProto, addr, 8)
|
||||
vote.BlockID = BlockID{}
|
||||
|
||||
_, err := signAddVote(privValidators[8], vote, voteSet)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
commit := voteSet.MakeCommit()
|
||||
|
||||
// Commit should have 10 elements
|
||||
if len(commit.Precommits) != 10 {
|
||||
t.Errorf("commit Precommits should have the same number of precommits as validators")
|
||||
if len(commit.Signatures) != 10 {
|
||||
t.Errorf("expected commit to include %d elems, got %d", 10, len(commit.Signatures))
|
||||
}
|
||||
|
||||
// Ensure that Commit precommits are ordered.
|
||||
// Ensure that Commit is good.
|
||||
if err := commit.ValidateBasic(); err != nil {
|
||||
t.Errorf("error in Commit.ValidateBasic(): %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
amino "github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
@@ -45,19 +44,6 @@ func exampleVote(t byte) *Vote {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that Vote and CommitSig have the same encoding.
|
||||
// This ensures using CommitSig isn't a breaking change.
|
||||
// This test will fail and can be removed once CommitSig contains only sigs and
|
||||
// timestamps.
|
||||
func TestVoteEncoding(t *testing.T) {
|
||||
vote := examplePrecommit()
|
||||
commitSig := vote.CommitSig()
|
||||
cdc := amino.NewCodec()
|
||||
bz1 := cdc.MustMarshalBinaryBare(vote)
|
||||
bz2 := cdc.MustMarshalBinaryBare(commitSig)
|
||||
assert.Equal(t, bz1, bz2)
|
||||
}
|
||||
|
||||
func TestVoteSignable(t *testing.T) {
|
||||
vote := examplePrecommit()
|
||||
signBytes := vote.SignBytes("test_chain_id")
|
||||
|
||||
Reference in New Issue
Block a user