diff --git a/types/priv_validator.go b/types/priv_validator.go index 66f02a6f6..8834eb7cc 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -129,14 +129,14 @@ func LoadPrivValidatorFS(filePath string) *PrivValidatorFS { // LoadOrGenPrivValidatorFS loads a PrivValidatorFS from the given filePath // or else generates a new one and saves it to the filePath. func LoadOrGenPrivValidatorFS(filePath string) *PrivValidatorFS { - var PrivValidatorFS *PrivValidatorFS + var privVal *PrivValidatorFS if _, err := os.Stat(filePath); err == nil { - PrivValidatorFS = LoadPrivValidatorFS(filePath) + privVal = LoadPrivValidatorFS(filePath) } else { - PrivValidatorFS = GenPrivValidatorFS(filePath) - PrivValidatorFS.Save() + privVal = GenPrivValidatorFS(filePath) + privVal.Save() } - return PrivValidatorFS + return privVal } // LoadPrivValidatorWithSigner loads a PrivValidatorFS with a custom diff --git a/types/priv_validator_test.go b/types/priv_validator_test.go index 5b6026740..ac91de861 100644 --- a/types/priv_validator_test.go +++ b/types/priv_validator_test.go @@ -4,14 +4,44 @@ import ( "encoding/hex" "encoding/json" "fmt" + "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-wire/data" + cmn "github.com/tendermint/tmlibs/common" ) -func TestLoadValidator(t *testing.T) { +func TestGenLoadValidator(t *testing.T) { + assert := assert.New(t) + + _, tempFilePath := cmn.Tempfile("priv_validator_") + privVal := GenPrivValidatorFS(tempFilePath) + + height := 100 + privVal.LastHeight = height + privVal.Save() + addr := privVal.GetAddress() + + privVal = LoadPrivValidatorFS(tempFilePath) + assert.Equal(addr, privVal.GetAddress(), "expected privval addr to be the same") + assert.Equal(height, privVal.LastHeight, "expected privval.LastHeight to have been saved") +} + +func TestLoadOrGenValidator(t *testing.T) { + assert := assert.New(t) + + _, tempFilePath := cmn.Tempfile("priv_validator_") + os.Remove(tempFilePath) + privVal := LoadOrGenPrivValidatorFS(tempFilePath) + addr := privVal.GetAddress() + privVal = LoadOrGenPrivValidatorFS(tempFilePath) + assert.Equal(addr, privVal.GetAddress(), "expected privval addr to be the same") +} + +func TestUnmarshalValidator(t *testing.T) { assert, require := assert.New(t), require.New(t) // create some fixed values @@ -58,3 +88,89 @@ func TestLoadValidator(t *testing.T) { require.Nil(err, "%+v", err) assert.JSONEq(serialized, string(out)) } + +func TestSignVote(t *testing.T) { + assert := assert.New(t) + + _, tempFilePath := cmn.Tempfile("priv_validator_") + privVal := GenPrivValidatorFS(tempFilePath) + + block1 := BlockID{[]byte{1, 2, 3}, PartSetHeader{}} + block2 := BlockID{[]byte{3, 2, 1}, PartSetHeader{}} + height, round := 10, 1 + voteType := VoteTypePrevote + + // sign a vote for first time + vote := newVote(privVal.Address, 0, height, round, voteType, block1) + err := privVal.SignVote("mychainid", vote) + assert.NoError(err, "expected no error signing vote") + + // try to sign the same vote again; should be fine + err = privVal.SignVote("mychainid", vote) + assert.NoError(err, "expected no error on signing same vote") + + // now try some bad votes + cases := []*Vote{ + newVote(privVal.Address, 0, height, round-1, voteType, block1), // round regression + newVote(privVal.Address, 0, height-1, round, voteType, block1), // height regression + newVote(privVal.Address, 0, height-2, round+4, voteType, block1), // height regression and different round + newVote(privVal.Address, 0, height, round, voteType, block2), // different block + } + + for _, c := range cases { + err = privVal.SignVote("mychainid", c) + assert.Error(err, "expected error on signing conflicting vote") + } +} + +func TestSignProposal(t *testing.T) { + assert := assert.New(t) + + _, tempFilePath := cmn.Tempfile("priv_validator_") + privVal := GenPrivValidatorFS(tempFilePath) + + block1 := PartSetHeader{5, []byte{1, 2, 3}} + block2 := PartSetHeader{10, []byte{3, 2, 1}} + height, round := 10, 1 + + // sign a proposal for first time + proposal := newProposal(height, round, block1) + err := privVal.SignProposal("mychainid", proposal) + assert.NoError(err, "expected no error signing proposal") + + // try to sign the same proposal again; should be fine + err = privVal.SignProposal("mychainid", proposal) + assert.NoError(err, "expected no error on signing same proposal") + + // now try some bad Proposals + cases := []*Proposal{ + newProposal(height, round-1, block1), // round regression + newProposal(height-1, round, block1), // height regression + newProposal(height-2, round+4, block1), // height regression and different round + newProposal(height, round, block2), // different block + } + + for _, c := range cases { + err = privVal.SignProposal("mychainid", c) + assert.Error(err, "expected error on signing conflicting proposal") + } +} + +func newVote(addr data.Bytes, idx, height, round int, typ byte, blockID BlockID) *Vote { + return &Vote{ + ValidatorAddress: addr, + ValidatorIndex: idx, + Height: height, + Round: round, + Type: typ, + BlockID: blockID, + } +} + +func newProposal(height, round int, partsHeader PartSetHeader) *Proposal { + return &Proposal{ + Height: height, + Round: round, + BlockPartsHeader: partsHeader, + } +}