diff --git a/types/block.go b/types/block.go index a447cc39a..53fc6a811 100644 --- a/types/block.go +++ b/types/block.go @@ -252,7 +252,8 @@ type Commit struct { bitArray *cmn.BitArray } -// FirstPrecommit returns the first non-nil precommit in the commit +// FirstPrecommit returns the first non-nil precommit in the commit. +// If all precommits are nil, it returns an empty precommit with height 0. func (commit *Commit) FirstPrecommit() *Vote { if len(commit.Precommits) == 0 { return nil @@ -266,7 +267,9 @@ func (commit *Commit) FirstPrecommit() *Vote { return precommit } } - return nil + return &Vote{ + Type: VoteTypePrecommit, + } } // Height returns the height of the commit diff --git a/types/validator_set.go b/types/validator_set.go index 83d066ec1..714f47e70 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -252,6 +252,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height return fmt.Errorf("Invalid commit -- not precommit @ index %v", idx) } _, val := valSet.GetByIndex(idx) + fmt.Println("IDX", idx, val) // Validate signature precommitSignBytes := precommit.SignBytes(chainID) if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) { diff --git a/types/validator_set_test.go b/types/validator_set_test.go index e34c71533..b346be1be 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -6,8 +6,10 @@ import ( "strings" "testing" "testing/quick" + "time" "github.com/stretchr/testify/assert" + crypto "github.com/tendermint/go-crypto" wire "github.com/tendermint/tendermint/wire" cmn "github.com/tendermint/tmlibs/common" @@ -309,3 +311,61 @@ func TestSafeSubClip(t *testing.T) { assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, math.MaxInt64)) assert.EqualValues(t, math.MaxInt64, safeSubClip(math.MaxInt64, -10)) } + +//------------------------------------------------------------------- + +func TestValidatorSetVerifyCommit(t *testing.T) { + privKey := crypto.GenPrivKeyEd25519() + pubKey := privKey.PubKey() + v1 := NewValidator(pubKey, 1000) + vset := NewValidatorSet([]*Validator{v1}) + + chainID := "mychainID" + blockID := BlockID{Hash: []byte("hello")} + height := int64(5) + vote := &Vote{ + ValidatorAddress: v1.Address, + ValidatorIndex: 0, + Height: height, + Round: 0, + Timestamp: time.Now().UTC(), + Type: VoteTypePrecommit, + BlockID: blockID, + } + vote.Signature = privKey.Sign(vote.SignBytes(chainID)) + commit := &Commit{ + BlockID: blockID, + Precommits: []*Vote{vote}, + } + + badChainID := "notmychainID" + badBlockID := BlockID{Hash: []byte("goodbye")} + badHeight := height + 1 + badCommit := &Commit{ + BlockID: blockID, + Precommits: []*Vote{nil}, + } + + // test some error cases + // TODO: test more cases! + cases := []struct { + chainID string + blockID BlockID + height int64 + commit *Commit + }{ + {badChainID, blockID, height, commit}, + {chainID, badBlockID, height, commit}, + {chainID, blockID, badHeight, commit}, + {chainID, blockID, height, badCommit}, + } + + for i, c := range cases { + err := vset.VerifyCommit(c.chainID, c.blockID, c.height, c.commit) + assert.NotNil(t, err, i) + } + + // test a good one + err := vset.VerifyCommit(chainID, blockID, height, commit) + assert.Nil(t, err) +}