Browse Source

privval: return error on getpubkey (#4534)

closes #3602

Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
pull/4560/head
Marko 5 years ago
committed by GitHub
parent
commit
48f073d796
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 501 additions and 216 deletions
  1. +2
    -0
      CHANGELOG_PENDING.md
  2. +19
    -11
      blockchain/v1/reactor_test.go
  3. +8
    -3
      cmd/tendermint/commands/init.go
  4. +7
    -1
      cmd/tendermint/commands/show_validator.go
  5. +8
    -3
      cmd/tendermint/commands/testnet.go
  6. +29
    -7
      consensus/common_test.go
  7. +19
    -10
      consensus/reactor_test.go
  8. +32
    -10
      consensus/replay_test.go
  9. +80
    -28
      consensus/state.go
  10. +48
    -16
      consensus/state_test.go
  11. +7
    -3
      consensus/types/height_vote_set_test.go
  12. +10
    -8
      node/node.go
  13. +2
    -2
      privval/file.go
  14. +3
    -1
      privval/file_deprecated_test.go
  15. +7
    -5
      privval/signer_client.go
  16. +10
    -5
      privval/signer_client_test.go
  17. +7
    -3
      privval/signer_requestHandler.go
  18. +3
    -1
      scripts/privValUpgrade_test.go
  19. +2
    -1
      state/state_test.go
  20. +5
    -1
      state/validation_test.go
  21. +22
    -5
      tools/tm-signer-harness/internal/test_harness.go
  22. +3
    -2
      types/block_test.go
  23. +33
    -30
      types/evidence_test.go
  24. +15
    -7
      types/priv_validator.go
  25. +6
    -4
      types/proposal_test.go
  26. +5
    -3
      types/protobuf_test.go
  27. +13
    -4
      types/test_util.go
  28. +4
    -1
      types/validator.go
  29. +86
    -37
      types/vote_set_test.go
  30. +6
    -4
      types/vote_test.go

+ 2
- 0
CHANGELOG_PENDING.md View File

@ -18,4 +18,6 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
### IMPROVEMENTS: ### IMPROVEMENTS:
- [privval] \#4534 Add `error` as a return value on`GetPubKey()`
### BUG FIXES: ### BUG FIXES:

+ 19
- 11
blockchain/v1/reactor_test.go View File

@ -10,6 +10,8 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
@ -46,15 +48,19 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G
} }
func makeVote( func makeVote(
t *testing.T,
header *types.Header, header *types.Header,
blockID types.BlockID, blockID types.BlockID,
valset *types.ValidatorSet, valset *types.ValidatorSet,
privVal types.PrivValidator) *types.Vote { privVal types.PrivValidator) *types.Vote {
addr := privVal.GetPubKey().Address()
idx, _ := valset.GetByAddress(addr)
pubKey, err := privVal.GetPubKey()
require.NoError(t, err)
valIdx, _ := valset.GetByAddress(pubKey.Address())
vote := &types.Vote{ vote := &types.Vote{
ValidatorAddress: addr,
ValidatorIndex: idx,
ValidatorAddress: pubKey.Address(),
ValidatorIndex: valIdx,
Height: header.Height, Height: header.Height,
Round: 1, Round: 1,
Timestamp: tmtime.Now(), Timestamp: tmtime.Now(),
@ -73,6 +79,7 @@ type BlockchainReactorPair struct {
} }
func newBlockchainReactor( func newBlockchainReactor(
t *testing.T,
logger log.Logger, logger log.Logger,
genDoc *types.GenesisDoc, genDoc *types.GenesisDoc,
privVals []types.PrivValidator, privVals []types.PrivValidator,
@ -114,7 +121,7 @@ func newBlockchainReactor(
lastBlockMeta := blockStore.LoadBlockMeta(blockHeight - 1) lastBlockMeta := blockStore.LoadBlockMeta(blockHeight - 1)
lastBlock := blockStore.LoadBlock(blockHeight - 1) lastBlock := blockStore.LoadBlock(blockHeight - 1)
vote := makeVote(&lastBlock.Header, lastBlockMeta.BlockID, state.Validators, privVals[0])
vote := makeVote(t, &lastBlock.Header, lastBlockMeta.BlockID, state.Validators, privVals[0])
lastCommit = types.NewCommit(vote.Height, vote.Round, lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()}) lastCommit = types.NewCommit(vote.Height, vote.Round, lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()})
} }
@ -138,6 +145,7 @@ func newBlockchainReactor(
} }
func newBlockchainReactorPair( func newBlockchainReactorPair(
t *testing.T,
logger log.Logger, logger log.Logger,
genDoc *types.GenesisDoc, genDoc *types.GenesisDoc,
privVals []types.PrivValidator, privVals []types.PrivValidator,
@ -147,7 +155,7 @@ func newBlockchainReactorPair(
consensusReactor.BaseReactor = *p2p.NewBaseReactor("Consensus reactor", consensusReactor) consensusReactor.BaseReactor = *p2p.NewBaseReactor("Consensus reactor", consensusReactor)
return BlockchainReactorPair{ return BlockchainReactorPair{
newBlockchainReactor(logger, genDoc, privVals, maxBlockHeight),
newBlockchainReactor(t, logger, genDoc, privVals, maxBlockHeight),
consensusReactor} consensusReactor}
} }
@ -174,8 +182,8 @@ func TestFastSyncNoBlockResponse(t *testing.T) {
reactorPairs := make([]BlockchainReactorPair, 2) reactorPairs := make([]BlockchainReactorPair, 2)
logger := log.TestingLogger() logger := log.TestingLogger()
reactorPairs[0] = newBlockchainReactorPair(logger, genDoc, privVals, maxBlockHeight)
reactorPairs[1] = newBlockchainReactorPair(logger, genDoc, privVals, 0)
reactorPairs[0] = newBlockchainReactorPair(t, logger, genDoc, privVals, maxBlockHeight)
reactorPairs[1] = newBlockchainReactorPair(t, logger, genDoc, privVals, 0)
p2p.MakeConnectedSwitches(config.P2P, 2, func(i int, s *p2p.Switch) *p2p.Switch { p2p.MakeConnectedSwitches(config.P2P, 2, func(i int, s *p2p.Switch) *p2p.Switch {
s.AddReactor("BLOCKCHAIN", reactorPairs[i].bcR) s.AddReactor("BLOCKCHAIN", reactorPairs[i].bcR)
@ -239,7 +247,7 @@ func TestFastSyncBadBlockStopsPeer(t *testing.T) {
defer os.RemoveAll(config.RootDir) defer os.RemoveAll(config.RootDir)
genDoc, privVals := randGenesisDoc(1, false, 30) genDoc, privVals := randGenesisDoc(1, false, 30)
otherChain := newBlockchainReactorPair(log.TestingLogger(), genDoc, privVals, maxBlockHeight)
otherChain := newBlockchainReactorPair(t, log.TestingLogger(), genDoc, privVals, maxBlockHeight)
defer func() { defer func() {
_ = otherChain.bcR.Stop() _ = otherChain.bcR.Stop()
_ = otherChain.conR.Stop() _ = otherChain.conR.Stop()
@ -254,7 +262,7 @@ func TestFastSyncBadBlockStopsPeer(t *testing.T) {
if i == 0 { if i == 0 {
height = maxBlockHeight height = maxBlockHeight
} }
reactorPairs[i] = newBlockchainReactorPair(logger[i], genDoc, privVals, height)
reactorPairs[i] = newBlockchainReactorPair(t, logger[i], genDoc, privVals, height)
} }
switches := p2p.MakeConnectedSwitches(config.P2P, numNodes, func(i int, s *p2p.Switch) *p2p.Switch { switches := p2p.MakeConnectedSwitches(config.P2P, numNodes, func(i int, s *p2p.Switch) *p2p.Switch {
@ -296,7 +304,7 @@ outerFor:
reactorPairs[numNodes-1].bcR.store = otherChain.bcR.store reactorPairs[numNodes-1].bcR.store = otherChain.bcR.store
lastLogger := log.TestingLogger() lastLogger := log.TestingLogger()
lastReactorPair := newBlockchainReactorPair(lastLogger, genDoc, privVals, 0)
lastReactorPair := newBlockchainReactorPair(t, lastLogger, genDoc, privVals, 0)
reactorPairs = append(reactorPairs, lastReactorPair) reactorPairs = append(reactorPairs, lastReactorPair)
switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(i int, s *p2p.Switch) *p2p.Switch { switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(i int, s *p2p.Switch) *p2p.Switch {


+ 8
- 3
cmd/tendermint/commands/init.go View File

@ -3,7 +3,9 @@ package commands
import ( import (
"fmt" "fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
tmos "github.com/tendermint/tendermint/libs/os" tmos "github.com/tendermint/tendermint/libs/os"
tmrand "github.com/tendermint/tendermint/libs/rand" tmrand "github.com/tendermint/tendermint/libs/rand"
@ -60,10 +62,13 @@ func initFilesWithConfig(config *cfg.Config) error {
GenesisTime: tmtime.Now(), GenesisTime: tmtime.Now(),
ConsensusParams: types.DefaultConsensusParams(), ConsensusParams: types.DefaultConsensusParams(),
} }
key := pv.GetPubKey()
pubKey, err := pv.GetPubKey()
if err != nil {
return errors.Wrap(err, "can't get pubkey")
}
genDoc.Validators = []types.GenesisValidator{{ genDoc.Validators = []types.GenesisValidator{{
Address: key.Address(),
PubKey: key,
Address: pubKey.Address(),
PubKey: pubKey,
Power: 10, Power: 10,
}} }}


+ 7
- 1
cmd/tendermint/commands/show_validator.go View File

@ -24,7 +24,13 @@ func showValidator(cmd *cobra.Command, args []string) error {
} }
pv := privval.LoadFilePV(keyFilePath, config.PrivValidatorStateFile()) pv := privval.LoadFilePV(keyFilePath, config.PrivValidatorStateFile())
bz, err := cdc.MarshalJSON(pv.GetPubKey())
pubKey, err := pv.GetPubKey()
if err != nil {
return errors.Wrap(err, "can't get pubkey")
}
bz, err := cdc.MarshalJSON(pubKey)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to marshal private validator pubkey") return errors.Wrap(err, "failed to marshal private validator pubkey")
} }


+ 8
- 3
cmd/tendermint/commands/testnet.go View File

@ -7,6 +7,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -137,11 +138,15 @@ func testnetFiles(cmd *cobra.Command, args []string) error {
pvKeyFile := filepath.Join(nodeDir, config.BaseConfig.PrivValidatorKey) pvKeyFile := filepath.Join(nodeDir, config.BaseConfig.PrivValidatorKey)
pvStateFile := filepath.Join(nodeDir, config.BaseConfig.PrivValidatorState) pvStateFile := filepath.Join(nodeDir, config.BaseConfig.PrivValidatorState)
pv := privval.LoadFilePV(pvKeyFile, pvStateFile) pv := privval.LoadFilePV(pvKeyFile, pvStateFile)
pubKey, err := pv.GetPubKey()
if err != nil {
return errors.Wrap(err, "can't get pubkey")
}
genVals[i] = types.GenesisValidator{ genVals[i] = types.GenesisValidator{
Address: pv.GetPubKey().Address(),
PubKey: pv.GetPubKey(),
Address: pubKey.Address(),
PubKey: pubKey,
Power: 1, Power: 1,
Name: nodeDirName, Name: nodeDirName,
} }


+ 29
- 7
consensus/common_test.go View File

@ -13,6 +13,8 @@ import (
"time" "time"
"github.com/go-kit/kit/log/term" "github.com/go-kit/kit/log/term"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"path" "path"
@ -82,17 +84,23 @@ func (vs *validatorStub) signVote(
voteType types.SignedMsgType, voteType types.SignedMsgType,
hash []byte, hash []byte,
header types.PartSetHeader) (*types.Vote, error) { header types.PartSetHeader) (*types.Vote, error) {
addr := vs.PrivValidator.GetPubKey().Address()
pubKey, err := vs.PrivValidator.GetPubKey()
if err != nil {
return nil, errors.Wrap(err, "can't get pubkey")
}
vote := &types.Vote{ vote := &types.Vote{
ValidatorIndex: vs.Index, ValidatorIndex: vs.Index,
ValidatorAddress: addr,
ValidatorAddress: pubKey.Address(),
Height: vs.Height, Height: vs.Height,
Round: vs.Round, Round: vs.Round,
Timestamp: tmtime.Now(), Timestamp: tmtime.Now(),
Type: voteType, Type: voteType,
BlockID: types.BlockID{Hash: hash, PartsHeader: header}, BlockID: types.BlockID{Hash: hash, PartsHeader: header},
} }
err := vs.PrivValidator.SignVote(config.ChainID(), vote)
err = vs.PrivValidator.SignVote(config.ChainID(), vote)
return vote, err return vote, err
} }
@ -136,7 +144,15 @@ func (vss ValidatorStubsByAddress) Len() int {
} }
func (vss ValidatorStubsByAddress) Less(i, j int) bool { func (vss ValidatorStubsByAddress) Less(i, j int) bool {
return bytes.Compare(vss[i].GetPubKey().Address(), vss[j].GetPubKey().Address()) == -1
vssi, err := vss[i].GetPubKey()
if err != nil {
panic(err)
}
vssj, err := vss[j].GetPubKey()
if err != nil {
panic(err)
}
return bytes.Compare(vssi.Address(), vssj.Address()) == -1
} }
func (vss ValidatorStubsByAddress) Swap(i, j int) { func (vss ValidatorStubsByAddress) Swap(i, j int) {
@ -199,7 +215,9 @@ func signAddVotes(
func validatePrevote(t *testing.T, cs *State, round int, privVal *validatorStub, blockHash []byte) { func validatePrevote(t *testing.T, cs *State, round int, privVal *validatorStub, blockHash []byte) {
prevotes := cs.Votes.Prevotes(round) prevotes := cs.Votes.Prevotes(round)
address := privVal.GetPubKey().Address()
pubKey, err := privVal.GetPubKey()
require.NoError(t, err)
address := pubKey.Address()
var vote *types.Vote var vote *types.Vote
if vote = prevotes.GetByAddress(address); vote == nil { if vote = prevotes.GetByAddress(address); vote == nil {
panic("Failed to find prevote from validator") panic("Failed to find prevote from validator")
@ -217,7 +235,9 @@ func validatePrevote(t *testing.T, cs *State, round int, privVal *validatorStub,
func validateLastPrecommit(t *testing.T, cs *State, privVal *validatorStub, blockHash []byte) { func validateLastPrecommit(t *testing.T, cs *State, privVal *validatorStub, blockHash []byte) {
votes := cs.LastCommit votes := cs.LastCommit
address := privVal.GetPubKey().Address()
pv, err := privVal.GetPubKey()
require.NoError(t, err)
address := pv.Address()
var vote *types.Vote var vote *types.Vote
if vote = votes.GetByAddress(address); vote == nil { if vote = votes.GetByAddress(address); vote == nil {
panic("Failed to find precommit from validator") panic("Failed to find precommit from validator")
@ -237,7 +257,9 @@ func validatePrecommit(
lockedBlockHash []byte, lockedBlockHash []byte,
) { ) {
precommits := cs.Votes.Precommits(thisRound) precommits := cs.Votes.Precommits(thisRound)
address := privVal.GetPubKey().Address()
pv, err := privVal.GetPubKey()
require.NoError(t, err)
address := pv.Address()
var vote *types.Vote var vote *types.Vote
if vote = precommits.GetByAddress(address); vote == nil { if vote = precommits.GetByAddress(address); vote == nil {
panic("Failed to find precommit from validator") panic("Failed to find precommit from validator")


+ 19
- 10
consensus/reactor_test.go View File

@ -154,8 +154,9 @@ func TestReactorWithEvidence(t *testing.T) {
// mock the evidence pool // mock the evidence pool
// everyone includes evidence of another double signing // everyone includes evidence of another double signing
vIdx := (i + 1) % nValidators vIdx := (i + 1) % nValidators
addr := privVals[vIdx].GetPubKey().Address()
evpool := newMockEvidencePool(addr)
pubKey, err := privVals[vIdx].GetPubKey()
require.NoError(t, err)
evpool := newMockEvidencePool(pubKey.Address())
// Make State // Make State
blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyAppConnCon, mempool, evpool) blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyAppConnCon, mempool, evpool)
@ -331,7 +332,9 @@ func TestReactorVotingPowerChange(t *testing.T) {
// map of active validators // map of active validators
activeVals := make(map[string]struct{}) activeVals := make(map[string]struct{})
for i := 0; i < nVals; i++ { for i := 0; i < nVals; i++ {
addr := css[i].privValidator.GetPubKey().Address()
pubKey, err := css[i].privValidator.GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
activeVals[string(addr)] = struct{}{} activeVals[string(addr)] = struct{}{}
} }
@ -343,7 +346,8 @@ func TestReactorVotingPowerChange(t *testing.T) {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
logger.Debug("---------------------------- Testing changing the voting power of one validator a few times") logger.Debug("---------------------------- Testing changing the voting power of one validator a few times")
val1PubKey := css[0].privValidator.GetPubKey()
val1PubKey, err := css[0].privValidator.GetPubKey()
require.NoError(t, err)
val1PubKeyABCI := types.TM2PB.PubKey(val1PubKey) val1PubKeyABCI := types.TM2PB.PubKey(val1PubKey)
updateValidatorTx := kvstore.MakeValSetChangeTx(val1PubKeyABCI, 25) updateValidatorTx := kvstore.MakeValSetChangeTx(val1PubKeyABCI, 25)
previousTotalVotingPower := css[0].GetRoundState().LastValidators.TotalVotingPower() previousTotalVotingPower := css[0].GetRoundState().LastValidators.TotalVotingPower()
@ -410,8 +414,9 @@ func TestReactorValidatorSetChanges(t *testing.T) {
// map of active validators // map of active validators
activeVals := make(map[string]struct{}) activeVals := make(map[string]struct{})
for i := 0; i < nVals; i++ { for i := 0; i < nVals; i++ {
addr := css[i].privValidator.GetPubKey().Address()
activeVals[string(addr)] = struct{}{}
pubKey, err := css[i].privValidator.GetPubKey()
require.NoError(t, err)
activeVals[string(pubKey.Address())] = struct{}{}
} }
// wait till everyone makes block 1 // wait till everyone makes block 1
@ -422,7 +427,8 @@ func TestReactorValidatorSetChanges(t *testing.T) {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
logger.Info("---------------------------- Testing adding one validator") logger.Info("---------------------------- Testing adding one validator")
newValidatorPubKey1 := css[nVals].privValidator.GetPubKey()
newValidatorPubKey1, err := css[nVals].privValidator.GetPubKey()
require.NoError(t, err)
valPubKey1ABCI := types.TM2PB.PubKey(newValidatorPubKey1) valPubKey1ABCI := types.TM2PB.PubKey(newValidatorPubKey1)
newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower)
@ -449,7 +455,8 @@ func TestReactorValidatorSetChanges(t *testing.T) {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
logger.Info("---------------------------- Testing changing the voting power of one validator") logger.Info("---------------------------- Testing changing the voting power of one validator")
updateValidatorPubKey1 := css[nVals].privValidator.GetPubKey()
updateValidatorPubKey1, err := css[nVals].privValidator.GetPubKey()
require.NoError(t, err)
updatePubKey1ABCI := types.TM2PB.PubKey(updateValidatorPubKey1) updatePubKey1ABCI := types.TM2PB.PubKey(updateValidatorPubKey1)
updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25)
previousTotalVotingPower := css[nVals].GetRoundState().LastValidators.TotalVotingPower() previousTotalVotingPower := css[nVals].GetRoundState().LastValidators.TotalVotingPower()
@ -469,11 +476,13 @@ func TestReactorValidatorSetChanges(t *testing.T) {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
logger.Info("---------------------------- Testing adding two validators at once") logger.Info("---------------------------- Testing adding two validators at once")
newValidatorPubKey2 := css[nVals+1].privValidator.GetPubKey()
newValidatorPubKey2, err := css[nVals+1].privValidator.GetPubKey()
require.NoError(t, err)
newVal2ABCI := types.TM2PB.PubKey(newValidatorPubKey2) newVal2ABCI := types.TM2PB.PubKey(newValidatorPubKey2)
newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower) newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower)
newValidatorPubKey3 := css[nVals+2].privValidator.GetPubKey()
newValidatorPubKey3, err := css[nVals+2].privValidator.GetPubKey()
require.NoError(t, err)
newVal3ABCI := types.TM2PB.PubKey(newValidatorPubKey3) newVal3ABCI := types.TM2PB.PubKey(newValidatorPubKey3)
newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower)


+ 32
- 10
consensus/replay_test.go View File

@ -344,10 +344,11 @@ func TestSimulateValidatorsChange(t *testing.T) {
//height 2 //height 2
height++ height++
incrementHeight(vss...) incrementHeight(vss...)
newValidatorPubKey1 := css[nVals].privValidator.GetPubKey()
newValidatorPubKey1, err := css[nVals].privValidator.GetPubKey()
require.NoError(t, err)
valPubKey1ABCI := types.TM2PB.PubKey(newValidatorPubKey1) valPubKey1ABCI := types.TM2PB.PubKey(newValidatorPubKey1)
newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower)
err := assertMempool(css[0].txNotifier).CheckTx(newValidatorTx1, nil, mempl.TxInfo{})
err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx1, nil, mempl.TxInfo{})
assert.Nil(t, err) assert.Nil(t, err)
propBlock, _ := css[0].createProposalBlock() //changeProposer(t, cs1, vs2) propBlock, _ := css[0].createProposalBlock() //changeProposer(t, cs1, vs2)
propBlockParts := propBlock.MakePartSet(partSize) propBlockParts := propBlock.MakePartSet(partSize)
@ -369,7 +370,8 @@ func TestSimulateValidatorsChange(t *testing.T) {
//height 3 //height 3
height++ height++
incrementHeight(vss...) incrementHeight(vss...)
updateValidatorPubKey1 := css[nVals].privValidator.GetPubKey()
updateValidatorPubKey1, err := css[nVals].privValidator.GetPubKey()
require.NoError(t, err)
updatePubKey1ABCI := types.TM2PB.PubKey(updateValidatorPubKey1) updatePubKey1ABCI := types.TM2PB.PubKey(updateValidatorPubKey1)
updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25)
err = assertMempool(css[0].txNotifier).CheckTx(updateValidatorTx1, nil, mempl.TxInfo{}) err = assertMempool(css[0].txNotifier).CheckTx(updateValidatorTx1, nil, mempl.TxInfo{})
@ -394,12 +396,14 @@ func TestSimulateValidatorsChange(t *testing.T) {
//height 4 //height 4
height++ height++
incrementHeight(vss...) incrementHeight(vss...)
newValidatorPubKey2 := css[nVals+1].privValidator.GetPubKey()
newValidatorPubKey2, err := css[nVals+1].privValidator.GetPubKey()
require.NoError(t, err)
newVal2ABCI := types.TM2PB.PubKey(newValidatorPubKey2) newVal2ABCI := types.TM2PB.PubKey(newValidatorPubKey2)
newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower) newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower)
err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx2, nil, mempl.TxInfo{}) err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx2, nil, mempl.TxInfo{})
assert.Nil(t, err) assert.Nil(t, err)
newValidatorPubKey3 := css[nVals+2].privValidator.GetPubKey()
newValidatorPubKey3, err := css[nVals+2].privValidator.GetPubKey()
require.NoError(t, err)
newVal3ABCI := types.TM2PB.PubKey(newValidatorPubKey3) newVal3ABCI := types.TM2PB.PubKey(newValidatorPubKey3)
newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower)
err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx3, nil, mempl.TxInfo{}) err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx3, nil, mempl.TxInfo{})
@ -412,7 +416,13 @@ func TestSimulateValidatorsChange(t *testing.T) {
sort.Sort(ValidatorStubsByAddress(newVss)) sort.Sort(ValidatorStubsByAddress(newVss))
selfIndex := 0 selfIndex := 0
for i, vs := range newVss { for i, vs := range newVss {
if vs.GetPubKey().Equals(css[0].privValidator.GetPubKey()) {
vsPubKey, err := vs.GetPubKey()
require.NoError(t, err)
css0PubKey, err := css[0].privValidator.GetPubKey()
require.NoError(t, err)
if vsPubKey.Equals(css0PubKey) {
selfIndex = i selfIndex = i
break break
} }
@ -469,7 +479,13 @@ func TestSimulateValidatorsChange(t *testing.T) {
copy(newVss, vss[:nVals+3]) copy(newVss, vss[:nVals+3])
sort.Sort(ValidatorStubsByAddress(newVss)) sort.Sort(ValidatorStubsByAddress(newVss))
for i, vs := range newVss { for i, vs := range newVss {
if vs.GetPubKey().Equals(css[0].privValidator.GetPubKey()) {
vsKeyKey, err := vs.GetPubKey()
require.NoError(t, err)
css0PubKey, err := css[0].privValidator.GetPubKey()
require.NoError(t, err)
if vsKeyKey.Equals(css0PubKey) {
selfIndex = i selfIndex = i
break break
} }
@ -642,7 +658,9 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin
chain, commits, err = makeBlockchainFromWAL(wal) chain, commits, err = makeBlockchainFromWAL(wal)
require.NoError(t, err) require.NoError(t, err)
stateDB, genisisState, store = stateAndStore(config, privVal.GetPubKey(), kvstore.ProtocolVersion)
pubKey, err := privVal.GetPubKey()
require.NoError(t, err)
stateDB, genisisState, store = stateAndStore(config, pubKey, kvstore.ProtocolVersion)
} }
store.chain = chain store.chain = chain
store.commits = commits store.commits = commits
@ -811,7 +829,9 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) {
defer os.RemoveAll(config.RootDir) defer os.RemoveAll(config.RootDir)
privVal := privval.LoadFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) privVal := privval.LoadFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile())
const appVersion = 0x0 const appVersion = 0x0
stateDB, state, store := stateAndStore(config, privVal.GetPubKey(), appVersion)
pubKey, err := privVal.GetPubKey()
require.NoError(t, err)
stateDB, state, store := stateAndStore(config, pubKey, appVersion)
genDoc, _ := sm.MakeGenesisDocFromFile(config.GenesisFile()) genDoc, _ := sm.MakeGenesisDocFromFile(config.GenesisFile())
state.LastValidators = state.Validators.Copy() state.LastValidators = state.Validators.Copy()
// mode = 0 for committing all the blocks // mode = 0 for committing all the blocks
@ -1095,7 +1115,9 @@ func TestHandshakeUpdatesValidators(t *testing.T) {
config := ResetConfig("handshake_test_") config := ResetConfig("handshake_test_")
defer os.RemoveAll(config.RootDir) defer os.RemoveAll(config.RootDir)
privVal := privval.LoadFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) privVal := privval.LoadFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile())
stateDB, state, store := stateAndStore(config, privVal.GetPubKey(), 0x0)
pubKey, err := privVal.GetPubKey()
require.NoError(t, err)
stateDB, state, store := stateAndStore(config, pubKey, 0x0)
oldValAddr := state.Validators.Validators[0].Address oldValAddr := state.Validators.Validators[0].Address


+ 80
- 28
consensus/state.go View File

@ -921,19 +921,27 @@ func (cs *State) enterPropose(height int64, round int) {
logger.Debug("This node is not a validator") logger.Debug("This node is not a validator")
return return
} }
logger.Debug("This node is a validator")
pubKey, err := cs.privValidator.GetPubKey()
if err != nil {
// If this node is a validator & proposer in the current round, it will
// miss the opportunity to create a block.
logger.Error("Error on retrival of pubkey", "err", err)
return
}
address := pubKey.Address()
// if not a validator, we're done // if not a validator, we're done
address := cs.privValidator.GetPubKey().Address()
if !cs.Validators.HasAddress(address) { if !cs.Validators.HasAddress(address) {
logger.Debug("This node is not a validator", "addr", address, "vals", cs.Validators) logger.Debug("This node is not a validator", "addr", address, "vals", cs.Validators)
return return
} }
logger.Debug("This node is a validator")
if cs.isProposer(address) { if cs.isProposer(address) {
logger.Info("enterPropose: Our turn to propose", logger.Info("enterPropose: Our turn to propose",
"proposer", "proposer",
cs.Validators.GetProposer().Address,
address,
"privValidator", "privValidator",
cs.privValidator) cs.privValidator)
cs.decideProposal(height, round) cs.decideProposal(height, round)
@ -961,7 +969,7 @@ func (cs *State) defaultDecideProposal(height int64, round int) {
} else { } else {
// Create a new proposal block from state/txs from the mempool. // Create a new proposal block from state/txs from the mempool.
block, blockParts = cs.createProposalBlock() block, blockParts = cs.createProposalBlock()
if block == nil { // on error
if block == nil {
return return
} }
} }
@ -1004,11 +1012,13 @@ func (cs *State) isProposalComplete() bool {
} }
// Create the next block to propose and return it.
// We really only need to return the parts, but the block
// is returned for convenience so we can log the proposal block.
// Returns nil block upon error.
// Create the next block to propose and return it. Returns nil block upon error.
//
// We really only need to return the parts, but the block is returned for
// convenience so we can log the proposal block.
//
// NOTE: keep it side-effect free for clarity. // NOTE: keep it side-effect free for clarity.
// CONTRACT: cs.privValidator is not nil.
func (cs *State) createProposalBlock() (block *types.Block, blockParts *types.PartSet) { func (cs *State) createProposalBlock() (block *types.Block, blockParts *types.PartSet) {
var commit *types.Commit var commit *types.Commit
switch { switch {
@ -1019,13 +1029,23 @@ func (cs *State) createProposalBlock() (block *types.Block, blockParts *types.Pa
case cs.LastCommit.HasTwoThirdsMajority(): case cs.LastCommit.HasTwoThirdsMajority():
// Make the commit from LastCommit // Make the commit from LastCommit
commit = cs.LastCommit.MakeCommit() commit = cs.LastCommit.MakeCommit()
default:
// This shouldn't happen.
cs.Logger.Error("enterPropose: Cannot propose anything: No commit for the previous block.")
default: // This shouldn't happen.
cs.Logger.Error("enterPropose: Cannot propose anything: No commit for the previous block")
return return
} }
proposerAddr := cs.privValidator.GetPubKey().Address()
if cs.privValidator == nil {
panic("entered createProposalBlock with privValidator being nil")
}
pubKey, err := cs.privValidator.GetPubKey()
if err != nil {
// If this node is a validator & proposer in the current round, it will
// miss the opportunity to create a block.
cs.Logger.Error("Error on retrival of pubkey", "err", err)
return
}
proposerAddr := pubKey.Address()
return cs.blockExec.CreateProposalBlock(cs.Height, cs.state, commit, proposerAddr) return cs.blockExec.CreateProposalBlock(cs.Height, cs.state, commit, proposerAddr)
} }
@ -1491,15 +1511,24 @@ func (cs *State) recordMetrics(height int64, block *types.Block) {
missingValidatorsPower += val.VotingPower missingValidatorsPower += val.VotingPower
} }
if cs.privValidator != nil && bytes.Equal(val.Address, cs.privValidator.GetPubKey().Address()) {
label := []string{
"validator_address", val.Address.String(),
if cs.privValidator != nil {
pubKey, err := cs.privValidator.GetPubKey()
if err != nil {
// Metrics won't be updated, but it's not critical.
cs.Logger.Error("Error on retrival of pubkey", "err", err)
continue
} }
cs.metrics.ValidatorPower.With(label...).Set(float64(val.VotingPower))
if commitSig.ForBlock() {
cs.metrics.ValidatorLastSignedHeight.With(label...).Set(float64(height))
} else {
cs.metrics.ValidatorMissedBlocks.With(label...).Add(float64(1))
if bytes.Equal(val.Address, pubKey.Address()) {
label := []string{
"validator_address", val.Address.String(),
}
cs.metrics.ValidatorPower.With(label...).Set(float64(val.VotingPower))
if commitSig.ForBlock() {
cs.metrics.ValidatorLastSignedHeight.With(label...).Set(float64(height))
} else {
cs.metrics.ValidatorMissedBlocks.With(label...).Add(float64(1))
}
} }
} }
} }
@ -1648,8 +1677,12 @@ func (cs *State) tryAddVote(vote *types.Vote, peerID p2p.ID) (bool, error) {
if err == ErrVoteHeightMismatch { if err == ErrVoteHeightMismatch {
return added, err return added, err
} else if voteErr, ok := err.(*types.ErrVoteConflictingVotes); ok { } else if voteErr, ok := err.(*types.ErrVoteConflictingVotes); ok {
addr := cs.privValidator.GetPubKey().Address()
if bytes.Equal(vote.ValidatorAddress, addr) {
pubKey, err := cs.privValidator.GetPubKey()
if err != nil {
return false, errors.Wrap(err, "can't get pubkey")
}
if bytes.Equal(vote.ValidatorAddress, pubKey.Address()) {
cs.Logger.Error( cs.Logger.Error(
"Found conflicting vote from ourselves. Did you unsafe_reset a validator?", "Found conflicting vote from ourselves. Did you unsafe_reset a validator?",
"height", "height",
@ -1838,6 +1871,7 @@ func (cs *State) addVote(
return added, err return added, err
} }
// CONTRACT: cs.privValidator is not nil.
func (cs *State) signVote( func (cs *State) signVote(
msgType types.SignedMsgType, msgType types.SignedMsgType,
hash []byte, hash []byte,
@ -1847,19 +1881,24 @@ func (cs *State) signVote(
// and the privValidator will refuse to sign anything. // and the privValidator will refuse to sign anything.
cs.wal.FlushAndSync() cs.wal.FlushAndSync()
addr := cs.privValidator.GetPubKey().Address()
valIndex, _ := cs.Validators.GetByAddress(addr)
pubKey, err := cs.privValidator.GetPubKey()
if err != nil {
return nil, errors.Wrap(err, "can't get pubkey")
}
addr := pubKey.Address()
valIdx, _ := cs.Validators.GetByAddress(addr)
vote := &types.Vote{ vote := &types.Vote{
ValidatorAddress: addr, ValidatorAddress: addr,
ValidatorIndex: valIndex,
ValidatorIndex: valIdx,
Height: cs.Height, Height: cs.Height,
Round: cs.Round, Round: cs.Round,
Timestamp: cs.voteTime(), Timestamp: cs.voteTime(),
Type: msgType, Type: msgType,
BlockID: types.BlockID{Hash: hash, PartsHeader: header}, BlockID: types.BlockID{Hash: hash, PartsHeader: header},
} }
err := cs.privValidator.SignVote(cs.state.ChainID, vote)
err = cs.privValidator.SignVote(cs.state.ChainID, vote)
return vote, err return vote, err
} }
@ -1884,10 +1923,23 @@ func (cs *State) voteTime() time.Time {
// sign the vote and publish on internalMsgQueue // sign the vote and publish on internalMsgQueue
func (cs *State) signAddVote(msgType types.SignedMsgType, hash []byte, header types.PartSetHeader) *types.Vote { func (cs *State) signAddVote(msgType types.SignedMsgType, hash []byte, header types.PartSetHeader) *types.Vote {
// if we don't have a key or we're not in the validator set, do nothing
if cs.privValidator == nil || !cs.Validators.HasAddress(cs.privValidator.GetPubKey().Address()) {
if cs.privValidator == nil { // the node does not have a key
return nil return nil
} }
pubKey, err := cs.privValidator.GetPubKey()
if err != nil {
// Vote won't be signed, but it's not critical.
cs.Logger.Error("Error on retrival of pubkey", "err", err)
return nil
}
// If the node not in the validator set, do nothing.
if !cs.Validators.HasAddress(pubKey.Address()) {
return nil
}
// TODO: pass pubKey to signVote
vote, err := cs.signVote(msgType, hash, header) vote, err := cs.signVote(msgType, hash, header)
if err == nil { if err == nil {
cs.sendInternalMessage(msgInfo{&VoteMessage{vote}, ""}) cs.sendInternalMessage(msgInfo{&VoteMessage{vote}, ""})


+ 48
- 16
consensus/state_test.go View File

@ -65,7 +65,9 @@ func TestStateProposerSelection0(t *testing.T) {
// Commit a block and ensure proposer for the next height is correct. // Commit a block and ensure proposer for the next height is correct.
prop := cs1.GetRoundState().Validators.GetProposer() prop := cs1.GetRoundState().Validators.GetProposer()
address := cs1.privValidator.GetPubKey().Address()
pv, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
address := pv.Address()
if !bytes.Equal(prop.Address, address) { if !bytes.Equal(prop.Address, address) {
t.Fatalf("expected proposer to be validator %d. Got %X", 0, prop.Address) t.Fatalf("expected proposer to be validator %d. Got %X", 0, prop.Address)
} }
@ -80,7 +82,9 @@ func TestStateProposerSelection0(t *testing.T) {
ensureNewRound(newRoundCh, height+1, 0) ensureNewRound(newRoundCh, height+1, 0)
prop = cs1.GetRoundState().Validators.GetProposer() prop = cs1.GetRoundState().Validators.GetProposer()
addr := vss[1].GetPubKey().Address()
pv1, err := vss[1].GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
if !bytes.Equal(prop.Address, addr) { if !bytes.Equal(prop.Address, addr) {
panic(fmt.Sprintf("expected proposer to be validator %d. Got %X", 1, prop.Address)) panic(fmt.Sprintf("expected proposer to be validator %d. Got %X", 1, prop.Address))
} }
@ -104,7 +108,9 @@ func TestStateProposerSelection2(t *testing.T) {
// everyone just votes nil. we get a new proposer each round // everyone just votes nil. we get a new proposer each round
for i := 0; i < len(vss); i++ { for i := 0; i < len(vss); i++ {
prop := cs1.GetRoundState().Validators.GetProposer() prop := cs1.GetRoundState().Validators.GetProposer()
addr := vss[(i+round)%len(vss)].GetPubKey().Address()
pvk, err := vss[(i+round)%len(vss)].GetPubKey()
require.NoError(t, err)
addr := pvk.Address()
correctProposer := addr correctProposer := addr
if !bytes.Equal(prop.Address, correctProposer) { if !bytes.Equal(prop.Address, correctProposer) {
panic(fmt.Sprintf( panic(fmt.Sprintf(
@ -516,7 +522,9 @@ func TestStateLockPOLRelock(t *testing.T) {
timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader) newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader)
@ -608,7 +616,9 @@ func TestStateLockPOLUnlock(t *testing.T) {
timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock) unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// everything done from perspective of cs1 // everything done from perspective of cs1
@ -700,7 +710,9 @@ func TestStateLockPOLSafety1(t *testing.T) {
timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round and wait for propose and prevote // start round and wait for propose and prevote
@ -817,7 +829,9 @@ func TestStateLockPOLSafety2(t *testing.T) {
timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock) unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// the block for R0: gets polkad but we miss it // the block for R0: gets polkad but we miss it
@ -909,7 +923,9 @@ func TestProposeValidBlock(t *testing.T) {
timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock) unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round and wait for propose and prevote // start round and wait for propose and prevote
@ -996,7 +1012,9 @@ func TestSetValidBlockOnDelayedPrevote(t *testing.T) {
timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round and wait for propose and prevote // start round and wait for propose and prevote
@ -1056,7 +1074,9 @@ func TestSetValidBlockOnDelayedProposal(t *testing.T) {
timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
@ -1127,7 +1147,9 @@ func TestWaitingTimeoutProposeOnNewRound(t *testing.T) {
timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round // start round
@ -1161,7 +1183,9 @@ func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) {
timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round // start round
@ -1195,7 +1219,9 @@ func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) {
timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round in which PO is not proposer // start round in which PO is not proposer
@ -1310,7 +1336,9 @@ func TestStartNextHeightCorrectly(t *testing.T) {
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader) newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round and wait for propose and prevote // start round and wait for propose and prevote
@ -1365,7 +1393,9 @@ func TestResetTimeoutPrecommitUponNewHeight(t *testing.T) {
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader) newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round and wait for propose and prevote // start round and wait for propose and prevote
@ -1502,7 +1532,9 @@ func TestStateHalt1(t *testing.T) {
timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlock) newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlock)
addr := cs1.privValidator.GetPubKey().Address()
pv1, err := cs1.privValidator.GetPubKey()
require.NoError(t, err)
addr := pv1.Address()
voteCh := subscribeToVoter(cs1, addr) voteCh := subscribeToVoter(cs1, addr)
// start round and wait for propose and prevote // start round and wait for propose and prevote


+ 7
- 3
consensus/types/height_vote_set_test.go View File

@ -54,9 +54,13 @@ func TestPeerCatchupRounds(t *testing.T) {
func makeVoteHR(t *testing.T, height int64, round int, privVals []types.PrivValidator, valIndex int) *types.Vote { func makeVoteHR(t *testing.T, height int64, round int, privVals []types.PrivValidator, valIndex int) *types.Vote {
privVal := privVals[valIndex] privVal := privVals[valIndex]
addr := privVal.GetPubKey().Address()
pubKey, err := privVal.GetPubKey()
if err != nil {
panic(err)
}
vote := &types.Vote{ vote := &types.Vote{
ValidatorAddress: addr,
ValidatorAddress: pubKey.Address(),
ValidatorIndex: valIndex, ValidatorIndex: valIndex,
Height: height, Height: height,
Round: round, Round: round,
@ -65,7 +69,7 @@ func makeVoteHR(t *testing.T, height int64, round int, privVals []types.PrivVali
BlockID: types.BlockID{Hash: []byte("fakehash"), PartsHeader: types.PartSetHeader{}}, BlockID: types.BlockID{Hash: []byte("fakehash"), PartsHeader: types.PartSetHeader{}},
} }
chainID := config.ChainID() chainID := config.ChainID()
err := privVal.SignVote(chainID, vote)
err = privVal.SignVote(chainID, vote)
if err != nil { if err != nil {
panic(fmt.Sprintf("Error signing vote: %v", err)) panic(fmt.Sprintf("Error signing vote: %v", err))
} }


+ 10
- 8
node/node.go View File

@ -309,12 +309,12 @@ func logNodeStartupInfo(state sm.State, pubKey crypto.PubKey, logger, consensusL
} }
} }
func onlyValidatorIsUs(state sm.State, privVal types.PrivValidator) bool {
func onlyValidatorIsUs(state sm.State, pubKey crypto.PubKey) bool {
if state.Validators.Size() > 1 { if state.Validators.Size() > 1 {
return false return false
} }
addr, _ := state.Validators.GetByIndex(0) addr, _ := state.Validators.GetByIndex(0)
return bytes.Equal(privVal.GetPubKey().Address(), addr)
return bytes.Equal(pubKey.Address(), addr)
} }
func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp proxy.AppConns, func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp proxy.AppConns,
@ -613,17 +613,16 @@ func NewNode(config *cfg.Config,
} }
} }
pubKey := privValidator.GetPubKey()
if pubKey == nil {
// TODO: GetPubKey should return errors - https://github.com/tendermint/tendermint/issues/3602
return nil, errors.New("could not retrieve public key from private validator")
pubKey, err := privValidator.GetPubKey()
if err != nil {
return nil, errors.Wrap(err, "can't get pubkey")
} }
logNodeStartupInfo(state, pubKey, logger, consensusLogger) logNodeStartupInfo(state, pubKey, logger, consensusLogger)
// Decide whether to fast-sync or not // Decide whether to fast-sync or not
// We don't fast-sync when the only validator is us. // We don't fast-sync when the only validator is us.
fastSync := config.FastSyncMode && !onlyValidatorIsUs(state, privValidator)
fastSync := config.FastSyncMode && !onlyValidatorIsUs(state, pubKey)
csMetrics, p2pMetrics, memplMetrics, smMetrics := metricsProvider(genDoc.ChainID) csMetrics, p2pMetrics, memplMetrics, smMetrics := metricsProvider(genDoc.ChainID)
@ -856,7 +855,10 @@ func (n *Node) ConfigureRPC() {
rpccore.SetEvidencePool(n.evidencePool) rpccore.SetEvidencePool(n.evidencePool)
rpccore.SetP2PPeers(n.sw) rpccore.SetP2PPeers(n.sw)
rpccore.SetP2PTransport(n) rpccore.SetP2PTransport(n)
pubKey := n.privValidator.GetPubKey()
pubKey, err := n.privValidator.GetPubKey()
if err != nil {
panic(err)
}
rpccore.SetPubKey(pubKey) rpccore.SetPubKey(pubKey)
rpccore.SetGenesisDoc(n.genesisDoc) rpccore.SetGenesisDoc(n.genesisDoc)
rpccore.SetProxyAppQuery(n.proxyApp.Query()) rpccore.SetProxyAppQuery(n.proxyApp.Query())


+ 2
- 2
privval/file.go View File

@ -237,8 +237,8 @@ func (pv *FilePV) GetAddress() types.Address {
// GetPubKey returns the public key of the validator. // GetPubKey returns the public key of the validator.
// Implements PrivValidator. // Implements PrivValidator.
func (pv *FilePV) GetPubKey() crypto.PubKey {
return pv.Key.PubKey
func (pv *FilePV) GetPubKey() (crypto.PubKey, error) {
return pv.Key.PubKey, nil
} }
// SignVote signs a canonical representation of the vote, along with the // SignVote signs a canonical representation of the vote, along with the


+ 3
- 1
privval/file_deprecated_test.go View File

@ -61,7 +61,9 @@ func assertEqualPV(t *testing.T, oldPV *privval.OldFilePV, newPV *privval.FilePV
assert.Equal(t, oldPV.Address, newPV.Key.Address) assert.Equal(t, oldPV.Address, newPV.Key.Address)
assert.Equal(t, oldPV.Address, newPV.GetAddress()) assert.Equal(t, oldPV.Address, newPV.GetAddress())
assert.Equal(t, oldPV.PubKey, newPV.Key.PubKey) assert.Equal(t, oldPV.PubKey, newPV.Key.PubKey)
assert.Equal(t, oldPV.PubKey, newPV.GetPubKey())
npv, err := newPV.GetPubKey()
require.NoError(t, err)
assert.Equal(t, oldPV.PubKey, npv)
assert.Equal(t, oldPV.PrivKey, newPV.Key.PrivKey) assert.Equal(t, oldPV.PrivKey, newPV.Key.PrivKey)
assert.Equal(t, oldPV.LastHeight, newPV.LastSignState.Height) assert.Equal(t, oldPV.LastHeight, newPV.LastSignState.Height)


+ 7
- 5
privval/signer_client.go View File

@ -1,6 +1,7 @@
package privval package privval
import ( import (
"fmt"
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -66,25 +67,26 @@ func (sc *SignerClient) Ping() error {
} }
// GetPubKey retrieves a public key from a remote signer // GetPubKey retrieves a public key from a remote signer
func (sc *SignerClient) GetPubKey() crypto.PubKey {
// returns an error if client is not able to provide the key
func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) {
response, err := sc.endpoint.SendRequest(&PubKeyRequest{}) response, err := sc.endpoint.SendRequest(&PubKeyRequest{})
if err != nil { if err != nil {
sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", err) sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", err)
return nil
return nil, errors.Wrap(err, "send")
} }
pubKeyResp, ok := response.(*PubKeyResponse) pubKeyResp, ok := response.(*PubKeyResponse)
if !ok { if !ok {
sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != PubKeyResponse") sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != PubKeyResponse")
return nil
return nil, errors.Errorf("unexpected response type %T", response)
} }
if pubKeyResp.Error != nil { if pubKeyResp.Error != nil {
sc.endpoint.Logger.Error("failed to get private validator's public key", "err", pubKeyResp.Error) sc.endpoint.Logger.Error("failed to get private validator's public key", "err", pubKeyResp.Error)
return nil
return nil, fmt.Errorf("remote error: %w", pubKeyResp.Error)
} }
return pubKeyResp.PubKey
return pubKeyResp.PubKey, nil
} }
// SignVote requests a remote signer to sign a vote // SignVote requests a remote signer to sign a vote


+ 10
- 5
privval/signer_client_test.go View File

@ -74,15 +74,20 @@ func TestSignerGetPubKey(t *testing.T) {
defer tc.signerServer.Stop() defer tc.signerServer.Stop()
defer tc.signerClient.Close() defer tc.signerClient.Close()
pubKey := tc.signerClient.GetPubKey()
expectedPubKey := tc.mockPV.GetPubKey()
pubKey, err := tc.signerClient.GetPubKey()
require.NoError(t, err)
expectedPubKey, err := tc.mockPV.GetPubKey()
require.NoError(t, err)
assert.Equal(t, expectedPubKey, pubKey) assert.Equal(t, expectedPubKey, pubKey)
addr := tc.signerClient.GetPubKey().Address()
expectedAddr := tc.mockPV.GetPubKey().Address()
pubKey, err = tc.signerClient.GetPubKey()
require.NoError(t, err)
expectedpk, err := tc.mockPV.GetPubKey()
require.NoError(t, err)
expectedAddr := expectedpk.Address()
assert.Equal(t, expectedAddr, addr)
assert.Equal(t, expectedAddr, pubKey.Address())
} }
} }


+ 7
- 3
privval/signer_requestHandler.go View File

@ -17,9 +17,13 @@ func DefaultValidationRequestHandler(
switch r := req.(type) { switch r := req.(type) {
case *PubKeyRequest: case *PubKeyRequest:
var p crypto.PubKey
p = privVal.GetPubKey()
res = &PubKeyResponse{p, nil}
var pubKey crypto.PubKey
pubKey, err = privVal.GetPubKey()
if err != nil {
res = &PubKeyResponse{nil, &RemoteSignerError{0, err.Error()}}
} else {
res = &PubKeyResponse{pubKey, nil}
}
case *SignVoteRequest: case *SignVoteRequest:
err = privVal.SignVote(chainID, r.Vote) err = privVal.SignVote(chainID, r.Vote)


+ 3
- 1
scripts/privValUpgrade_test.go View File

@ -100,7 +100,9 @@ func TestLoadAndUpgrade(t *testing.T) {
assert.Equal(t, oldPV.Address, upgradedPV.Key.Address) assert.Equal(t, oldPV.Address, upgradedPV.Key.Address)
assert.Equal(t, oldPV.Address, upgradedPV.GetAddress()) assert.Equal(t, oldPV.Address, upgradedPV.GetAddress())
assert.Equal(t, oldPV.PubKey, upgradedPV.Key.PubKey) assert.Equal(t, oldPV.PubKey, upgradedPV.Key.PubKey)
assert.Equal(t, oldPV.PubKey, upgradedPV.GetPubKey())
upv, err := upgradedPV.GetPubKey()
require.NoError(t, err)
assert.Equal(t, oldPV.PubKey, upv)
assert.Equal(t, oldPV.PrivKey, upgradedPV.Key.PrivKey) assert.Equal(t, oldPV.PrivKey, upgradedPV.Key.PrivKey)
assert.Equal(t, oldPV.LastHeight, upgradedPV.LastSignState.Height) assert.Equal(t, oldPV.LastHeight, upgradedPV.LastSignState.Height)


+ 2
- 1
state/state_test.go View File

@ -326,7 +326,8 @@ func TestProposerFrequency(t *testing.T) {
votePower := int64(tmrand.Int()%maxPower) + 1 votePower := int64(tmrand.Int()%maxPower) + 1
totalVotePower += votePower totalVotePower += votePower
privVal := types.NewMockPV() privVal := types.NewMockPV()
pubKey := privVal.GetPubKey()
pubKey, err := privVal.GetPubKey()
require.NoError(t, err)
val := types.NewValidator(pubKey, votePower) val := types.NewValidator(pubKey, votePower)
val.ProposerPriority = tmrand.Int64() val.ProposerPriority = tmrand.Int64()
vals[j] = val vals[j] = val


+ 5
- 1
state/validation_test.go View File

@ -171,8 +171,12 @@ func TestValidateBlockCommit(t *testing.T) {
time.Now(), time.Now(),
) )
require.NoError(t, err, "height %d", height) require.NoError(t, err, "height %d", height)
bpvPubKey, err := badPrivVal.GetPubKey()
require.NoError(t, err)
badVote := &types.Vote{ badVote := &types.Vote{
ValidatorAddress: badPrivVal.GetPubKey().Address(),
ValidatorAddress: bpvPubKey.Address(),
ValidatorIndex: 0, ValidatorIndex: 0,
Height: height, Height: height,
Round: 0, Round: 0,


+ 22
- 5
tools/tm-signer-harness/internal/test_harness.go View File

@ -190,9 +190,17 @@ func (th *TestHarness) Run() {
// local Tendermint version. // local Tendermint version.
func (th *TestHarness) TestPublicKey() error { func (th *TestHarness) TestPublicKey() error {
th.logger.Info("TEST: Public key of remote signer") th.logger.Info("TEST: Public key of remote signer")
th.logger.Info("Local", "pubKey", th.fpv.GetPubKey())
th.logger.Info("Remote", "pubKey", th.signerClient.GetPubKey())
if th.fpv.GetPubKey() != th.signerClient.GetPubKey() {
fpvk, err := th.fpv.GetPubKey()
if err != nil {
return err
}
th.logger.Info("Local", "pubKey", fpvk)
sck, err := th.signerClient.GetPubKey()
if err != nil {
return err
}
th.logger.Info("Remote", "pubKey", sck)
if fpvk != sck {
th.logger.Error("FAILED: Local and remote public keys do not match") th.logger.Error("FAILED: Local and remote public keys do not match")
return newTestHarnessError(ErrTestPublicKeyFailed, nil, "") return newTestHarnessError(ErrTestPublicKeyFailed, nil, "")
} }
@ -230,8 +238,12 @@ func (th *TestHarness) TestSignProposal() error {
th.logger.Error("FAILED: Signed proposal is invalid", "err", err) th.logger.Error("FAILED: Signed proposal is invalid", "err", err)
return newTestHarnessError(ErrTestSignProposalFailed, err, "") return newTestHarnessError(ErrTestSignProposalFailed, err, "")
} }
sck, err := th.signerClient.GetPubKey()
if err != nil {
return err
}
// now validate the signature on the proposal // now validate the signature on the proposal
if th.signerClient.GetPubKey().VerifyBytes(propBytes, prop.Signature) {
if sck.VerifyBytes(propBytes, prop.Signature) {
th.logger.Info("Successfully validated proposal signature") th.logger.Info("Successfully validated proposal signature")
} else { } else {
th.logger.Error("FAILED: Proposal signature validation failed") th.logger.Error("FAILED: Proposal signature validation failed")
@ -274,8 +286,13 @@ func (th *TestHarness) TestSignVote() error {
th.logger.Error("FAILED: Signed vote is invalid", "err", err) th.logger.Error("FAILED: Signed vote is invalid", "err", err)
return newTestHarnessError(ErrTestSignVoteFailed, err, fmt.Sprintf("voteType=%d", voteType)) return newTestHarnessError(ErrTestSignVoteFailed, err, fmt.Sprintf("voteType=%d", voteType))
} }
sck, err := th.signerClient.GetPubKey()
if err != nil {
return err
}
// now validate the signature on the proposal // now validate the signature on the proposal
if th.signerClient.GetPubKey().VerifyBytes(voteBytes, vote.Signature) {
if sck.VerifyBytes(voteBytes, vote.Signature) {
th.logger.Info("Successfully validated vote signature", "type", voteType) th.logger.Info("Successfully validated vote signature", "type", voteType)
} else { } else {
th.logger.Error("FAILED: Vote signature validation failed", "type", voteType) th.logger.Error("FAILED: Vote signature validation failed", "type", voteType)


+ 3
- 2
types/block_test.go View File

@ -475,9 +475,10 @@ func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) {
vi := 0 vi := 0
for n := range tc.blockIDs { for n := range tc.blockIDs {
for i := 0; i < tc.numVotes[n]; i++ { for i := 0; i < tc.numVotes[n]; i++ {
addr := vals[vi].GetPubKey().Address()
pubKey, err := vals[vi].GetPubKey()
require.NoError(t, err)
vote := &Vote{ vote := &Vote{
ValidatorAddress: addr,
ValidatorAddress: pubKey.Address(),
ValidatorIndex: vi, ValidatorIndex: vi,
Height: height - 1, Height: height - 1,
Round: round, Round: round,


+ 33
- 30
types/evidence_test.go View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/crypto/tmhash"
) )
@ -17,17 +18,20 @@ type voteData struct {
valid bool valid bool
} }
func makeVote(val PrivValidator, chainID string, valIndex int, height int64, round, step int, blockID BlockID) *Vote {
addr := val.GetPubKey().Address()
func makeVote(
t *testing.T, val PrivValidator, chainID string, valIndex int, height int64, round, step int, blockID BlockID,
) *Vote {
pubKey, err := val.GetPubKey()
require.NoError(t, err)
v := &Vote{ v := &Vote{
ValidatorAddress: addr,
ValidatorAddress: pubKey.Address(),
ValidatorIndex: valIndex, ValidatorIndex: valIndex,
Height: height, Height: height,
Round: round, Round: round,
Type: SignedMsgType(step), Type: SignedMsgType(step),
BlockID: blockID, BlockID: blockID,
} }
err := val.SignVote(chainID, v)
err = val.SignVote(chainID, v)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -45,28 +49,27 @@ func TestEvidence(t *testing.T) {
const chainID = "mychain" const chainID = "mychain"
vote1 := makeVote(val, chainID, 0, 10, 2, 1, blockID)
badVote := makeVote(val, chainID, 0, 10, 2, 1, blockID)
vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID)
badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID)
err := val2.SignVote(chainID, badVote) err := val2.SignVote(chainID, badVote)
if err != nil {
panic(err)
}
assert.NoError(t, err)
cases := []voteData{ cases := []voteData{
{vote1, makeVote(val, chainID, 0, 10, 2, 1, blockID2), true}, // different block ids
{vote1, makeVote(val, chainID, 0, 10, 2, 1, blockID3), true},
{vote1, makeVote(val, chainID, 0, 10, 2, 1, blockID4), true},
{vote1, makeVote(val, chainID, 0, 10, 2, 1, blockID), false}, // wrong block id
{vote1, makeVote(val, "mychain2", 0, 10, 2, 1, blockID2), false}, // wrong chain id
{vote1, makeVote(val, chainID, 1, 10, 2, 1, blockID2), false}, // wrong val index
{vote1, makeVote(val, chainID, 0, 11, 2, 1, blockID2), false}, // wrong height
{vote1, makeVote(val, chainID, 0, 10, 3, 1, blockID2), false}, // wrong round
{vote1, makeVote(val, chainID, 0, 10, 2, 2, blockID2), false}, // wrong step
{vote1, makeVote(val2, chainID, 0, 10, 2, 1, blockID), false}, // wrong validator
{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2), true}, // different block ids
{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3), true},
{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID4), true},
{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID), false}, // wrong block id
{vote1, makeVote(t, val, "mychain2", 0, 10, 2, 1, blockID2), false}, // wrong chain id
{vote1, makeVote(t, val, chainID, 1, 10, 2, 1, blockID2), false}, // wrong val index
{vote1, makeVote(t, val, chainID, 0, 11, 2, 1, blockID2), false}, // wrong height
{vote1, makeVote(t, val, chainID, 0, 10, 3, 1, blockID2), false}, // wrong round
{vote1, makeVote(t, val, chainID, 0, 10, 2, 2, blockID2), false}, // wrong step
{vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID), false}, // wrong validator
{vote1, badVote, false}, // signed by wrong key {vote1, badVote, false}, // signed by wrong key
} }
pubKey := val.GetPubKey()
pubKey, err := val.GetPubKey()
require.NoError(t, err)
for _, c := range cases { for _, c := range cases {
ev := &DuplicateVoteEvidence{ ev := &DuplicateVoteEvidence{
VoteA: c.vote1, VoteA: c.vote1,
@ -81,14 +84,14 @@ func TestEvidence(t *testing.T) {
} }
func TestDuplicatedVoteEvidence(t *testing.T) { func TestDuplicatedVoteEvidence(t *testing.T) {
ev := randomDuplicatedVoteEvidence()
ev := randomDuplicatedVoteEvidence(t)
assert.True(t, ev.Equal(ev)) assert.True(t, ev.Equal(ev))
assert.False(t, ev.Equal(&DuplicateVoteEvidence{})) assert.False(t, ev.Equal(&DuplicateVoteEvidence{}))
} }
func TestEvidenceList(t *testing.T) { func TestEvidenceList(t *testing.T) {
ev := randomDuplicatedVoteEvidence()
ev := randomDuplicatedVoteEvidence(t)
evl := EvidenceList([]Evidence{ev}) evl := EvidenceList([]Evidence{ev})
assert.NotNil(t, evl.Hash()) assert.NotNil(t, evl.Hash())
@ -103,8 +106,8 @@ func TestMaxEvidenceBytes(t *testing.T) {
const chainID = "mychain" const chainID = "mychain"
ev := &DuplicateVoteEvidence{ ev := &DuplicateVoteEvidence{
PubKey: secp256k1.GenPrivKey().PubKey(), // use secp because it's pubkey is longer PubKey: secp256k1.GenPrivKey().PubKey(), // use secp because it's pubkey is longer
VoteA: makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID),
VoteB: makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
VoteA: makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID),
VoteB: makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
} }
bz, err := cdc.MarshalBinaryLengthPrefixed(ev) bz, err := cdc.MarshalBinaryLengthPrefixed(ev)
@ -113,14 +116,14 @@ func TestMaxEvidenceBytes(t *testing.T) {
assert.EqualValues(t, MaxEvidenceBytes, len(bz)) assert.EqualValues(t, MaxEvidenceBytes, len(bz))
} }
func randomDuplicatedVoteEvidence() *DuplicateVoteEvidence {
func randomDuplicatedVoteEvidence(t *testing.T) *DuplicateVoteEvidence {
val := NewMockPV() val := NewMockPV()
blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash")) blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
const chainID = "mychain" const chainID = "mychain"
return &DuplicateVoteEvidence{ return &DuplicateVoteEvidence{
VoteA: makeVote(val, chainID, 0, 10, 2, 1, blockID),
VoteB: makeVote(val, chainID, 0, 10, 2, 1, blockID2),
VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID),
VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2),
} }
} }
@ -143,7 +146,7 @@ func TestDuplicateVoteEvidenceValidation(t *testing.T) {
ev.VoteB = nil ev.VoteB = nil
}, true}, }, true},
{"Invalid vote type", func(ev *DuplicateVoteEvidence) { {"Invalid vote type", func(ev *DuplicateVoteEvidence) {
ev.VoteA = makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0, blockID2)
ev.VoteA = makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0, blockID2)
}, true}, }, true},
{"Invalid vote order", func(ev *DuplicateVoteEvidence) { {"Invalid vote order", func(ev *DuplicateVoteEvidence) {
swap := ev.VoteA.Copy() swap := ev.VoteA.Copy()
@ -155,8 +158,8 @@ func TestDuplicateVoteEvidenceValidation(t *testing.T) {
tc := tc tc := tc
t.Run(tc.testName, func(t *testing.T) { t.Run(tc.testName, func(t *testing.T) {
pk := secp256k1.GenPrivKey().PubKey() pk := secp256k1.GenPrivKey().PubKey()
vote1 := makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID)
vote2 := makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID2)
vote1 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID)
vote2 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID2)
ev := NewDuplicateVoteEvidence(pk, vote1, vote2) ev := NewDuplicateVoteEvidence(pk, vote1, vote2)
tc.malleateEvidence(ev) tc.malleateEvidence(ev)
assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result") assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result")


+ 15
- 7
types/priv_validator.go View File

@ -12,8 +12,7 @@ import (
// PrivValidator defines the functionality of a local Tendermint validator // PrivValidator defines the functionality of a local Tendermint validator
// that signs votes and proposals, and never double signs. // that signs votes and proposals, and never double signs.
type PrivValidator interface { type PrivValidator interface {
// TODO: Extend the interface to return errors too. Issue: https://github.com/tendermint/tendermint/issues/3602
GetPubKey() crypto.PubKey
GetPubKey() (crypto.PubKey, error)
SignVote(chainID string, vote *Vote) error SignVote(chainID string, vote *Vote) error
SignProposal(chainID string, proposal *Proposal) error SignProposal(chainID string, proposal *Proposal) error
@ -29,7 +28,16 @@ func (pvs PrivValidatorsByAddress) Len() int {
} }
func (pvs PrivValidatorsByAddress) Less(i, j int) bool { func (pvs PrivValidatorsByAddress) Less(i, j int) bool {
return bytes.Compare(pvs[i].GetPubKey().Address(), pvs[j].GetPubKey().Address()) == -1
pvi, err := pvs[i].GetPubKey()
if err != nil {
panic(err)
}
pvj, err := pvs[j].GetPubKey()
if err != nil {
panic(err)
}
return bytes.Compare(pvi.Address(), pvj.Address()) == -1
} }
func (pvs PrivValidatorsByAddress) Swap(i, j int) { func (pvs PrivValidatorsByAddress) Swap(i, j int) {
@ -61,8 +69,8 @@ func NewMockPVWithParams(privKey crypto.PrivKey, breakProposalSigning, breakVote
} }
// Implements PrivValidator. // Implements PrivValidator.
func (pv MockPV) GetPubKey() crypto.PubKey {
return pv.PrivKey.PubKey()
func (pv MockPV) GetPubKey() (crypto.PubKey, error) {
return pv.PrivKey.PubKey(), nil
} }
// Implements PrivValidator. // Implements PrivValidator.
@ -97,8 +105,8 @@ func (pv MockPV) SignProposal(chainID string, proposal *Proposal) error {
// String returns a string representation of the MockPV. // String returns a string representation of the MockPV.
func (pv MockPV) String() string { func (pv MockPV) String() string {
addr := pv.GetPubKey().Address()
return fmt.Sprintf("MockPV{%v}", addr)
mpv, _ := pv.GetPubKey() // mockPV will never return an error, ignored here
return fmt.Sprintf("MockPV{%v}", mpv.Address())
} }
// XXX: Implement. // XXX: Implement.


+ 6
- 4
types/proposal_test.go View File

@ -45,7 +45,8 @@ func TestProposalString(t *testing.T) {
func TestProposalVerifySignature(t *testing.T) { func TestProposalVerifySignature(t *testing.T) {
privVal := NewMockPV() privVal := NewMockPV()
pubKey := privVal.GetPubKey()
pubKey, err := privVal.GetPubKey()
require.NoError(t, err)
prop := NewProposal( prop := NewProposal(
4, 2, 2, 4, 2, 2,
@ -53,7 +54,7 @@ func TestProposalVerifySignature(t *testing.T) {
signBytes := prop.SignBytes("test_chain_id") signBytes := prop.SignBytes("test_chain_id")
// sign it // sign it
err := privVal.SignProposal("test_chain_id", prop)
err = privVal.SignProposal("test_chain_id", prop)
require.NoError(t, err) require.NoError(t, err)
// verify the same proposal // verify the same proposal
@ -93,8 +94,9 @@ func BenchmarkProposalSign(b *testing.B) {
func BenchmarkProposalVerifySignature(b *testing.B) { func BenchmarkProposalVerifySignature(b *testing.B) {
privVal := NewMockPV() privVal := NewMockPV()
err := privVal.SignProposal("test_chain_id", testProposal) err := privVal.SignProposal("test_chain_id", testProposal)
require.Nil(b, err)
pubKey := privVal.GetPubKey()
require.NoError(b, err)
pubKey, err := privVal.GetPubKey()
require.NoError(b, err)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
pubKey.VerifyBytes(testProposal.SignBytes("test_chain_id"), testProposal.Signature) pubKey.VerifyBytes(testProposal.SignBytes("test_chain_id"), testProposal.Signature)


+ 5
- 3
types/protobuf_test.go View File

@ -6,6 +6,7 @@ import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
amino "github.com/tendermint/go-amino" amino "github.com/tendermint/go-amino"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
@ -131,11 +132,12 @@ func TestABCIEvidence(t *testing.T) {
blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash")) blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
const chainID = "mychain" const chainID = "mychain"
pubKey := val.GetPubKey()
pubKey, err := val.GetPubKey()
require.NoError(t, err)
ev := &DuplicateVoteEvidence{ ev := &DuplicateVoteEvidence{
PubKey: pubKey, PubKey: pubKey,
VoteA: makeVote(val, chainID, 0, 10, 2, 1, blockID),
VoteB: makeVote(val, chainID, 0, 10, 2, 1, blockID2),
VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID),
VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2),
} }
abciEv := TM2PB.Evidence( abciEv := TM2PB.Evidence(
ev, ev,


+ 13
- 4
types/test_util.go View File

@ -2,6 +2,8 @@ package types
import ( import (
"time" "time"
"github.com/pkg/errors"
) )
func MakeCommit(blockID BlockID, height int64, round int, func MakeCommit(blockID BlockID, height int64, round int,
@ -9,9 +11,12 @@ func MakeCommit(blockID BlockID, height int64, round int,
// all sign // all sign
for i := 0; i < len(validators); i++ { for i := 0; i < len(validators); i++ {
addr := validators[i].GetPubKey().Address()
pubKey, err := validators[i].GetPubKey()
if err != nil {
return nil, errors.Wrap(err, "can't get pubkey")
}
vote := &Vote{ vote := &Vote{
ValidatorAddress: addr,
ValidatorAddress: pubKey.Address(),
ValidatorIndex: i, ValidatorIndex: i,
Height: height, Height: height,
Round: round, Round: round,
@ -20,7 +25,7 @@ func MakeCommit(blockID BlockID, height int64, round int,
Timestamp: now, Timestamp: now,
} }
_, err := signAddVote(validators[i], vote, voteSet)
_, err = signAddVote(validators[i], vote, voteSet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -45,7 +50,11 @@ func MakeVote(
chainID string, chainID string,
now time.Time, now time.Time,
) (*Vote, error) { ) (*Vote, error) {
addr := privVal.GetPubKey().Address()
pubKey, err := privVal.GetPubKey()
if err != nil {
return nil, errors.Wrap(err, "can't get pubkey")
}
addr := pubKey.Address()
idx, _ := valSet.GetByAddress(addr) idx, _ := valSet.GetByAddress(addr)
vote := &Vote{ vote := &Vote{
ValidatorAddress: addr, ValidatorAddress: addr,


+ 4
- 1
types/validator.go View File

@ -105,7 +105,10 @@ func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator) {
if randPower { if randPower {
votePower += int64(tmrand.Uint32()) votePower += int64(tmrand.Uint32())
} }
pubKey := privVal.GetPubKey()
pubKey, err := privVal.GetPubKey()
if err != nil {
panic(fmt.Errorf("could not retrieve pubkey %w", err))
}
val := NewValidator(pubKey, votePower) val := NewValidator(pubKey, votePower)
return val, privVal return val, privVal
} }

+ 86
- 37
types/vote_set_test.go View File

@ -5,6 +5,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto"
tmrand "github.com/tendermint/tendermint/libs/rand" tmrand "github.com/tendermint/tendermint/libs/rand"
@ -73,7 +74,10 @@ func TestAddVote(t *testing.T) {
// t.Logf(">> %v", voteSet) // t.Logf(">> %v", voteSet)
val0Addr := val0.GetPubKey().Address()
val0p, err := val0.GetPubKey()
require.NoError(t, err)
val0Addr := val0p.Address()
if voteSet.GetByAddress(val0Addr) != nil { if voteSet.GetByAddress(val0Addr) != nil {
t.Errorf("expected GetByAddress(val0.Address) to be nil") t.Errorf("expected GetByAddress(val0.Address) to be nil")
} }
@ -94,7 +98,7 @@ func TestAddVote(t *testing.T) {
Timestamp: tmtime.Now(), Timestamp: tmtime.Now(),
BlockID: BlockID{nil, PartSetHeader{}}, BlockID: BlockID{nil, PartSetHeader{}},
} }
_, err := signAddVote(val0, vote, voteSet)
_, err = signAddVote(val0, vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -126,9 +130,11 @@ func Test2_3Majority(t *testing.T) {
} }
// 6 out of 10 voted for nil. // 6 out of 10 voted for nil.
for i := 0; i < 6; i++ { for i := 0; i < 6; i++ {
addr := privValidators[i].GetPubKey().Address()
pubKey, err := privValidators[i].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, i) vote := withValidator(voteProto, addr, i)
_, err := signAddVote(privValidators[i], vote, voteSet)
_, err = signAddVote(privValidators[i], vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -140,9 +146,11 @@ func Test2_3Majority(t *testing.T) {
// 7th validator voted for some blockhash // 7th validator voted for some blockhash
{ {
addr := privValidators[6].GetPubKey().Address()
pubKey, err := privValidators[6].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 6) vote := withValidator(voteProto, addr, 6)
_, err := signAddVote(privValidators[6], withBlockHash(vote, tmrand.Bytes(32)), voteSet)
_, err = signAddVote(privValidators[6], withBlockHash(vote, tmrand.Bytes(32)), voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -154,9 +162,11 @@ func Test2_3Majority(t *testing.T) {
// 8th validator voted for nil. // 8th validator voted for nil.
{ {
addr := privValidators[7].GetPubKey().Address()
pubKey, err := privValidators[7].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 7) vote := withValidator(voteProto, addr, 7)
_, err := signAddVote(privValidators[7], vote, voteSet)
_, err = signAddVote(privValidators[7], vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -187,9 +197,11 @@ func Test2_3MajorityRedux(t *testing.T) {
// 66 out of 100 voted for nil. // 66 out of 100 voted for nil.
for i := 0; i < 66; i++ { for i := 0; i < 66; i++ {
addr := privValidators[i].GetPubKey().Address()
pubKey, err := privValidators[i].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, i) vote := withValidator(voteProto, addr, i)
_, err := signAddVote(privValidators[i], vote, voteSet)
_, err = signAddVote(privValidators[i], vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -201,9 +213,11 @@ func Test2_3MajorityRedux(t *testing.T) {
// 67th validator voted for nil // 67th validator voted for nil
{ {
adrr := privValidators[66].GetPubKey().Address()
pubKey, err := privValidators[66].GetPubKey()
require.NoError(t, err)
adrr := pubKey.Address()
vote := withValidator(voteProto, adrr, 66) vote := withValidator(voteProto, adrr, 66)
_, err := signAddVote(privValidators[66], withBlockHash(vote, nil), voteSet)
_, err = signAddVote(privValidators[66], withBlockHash(vote, nil), voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -215,10 +229,12 @@ func Test2_3MajorityRedux(t *testing.T) {
// 68th validator voted for a different BlockParts PartSetHeader // 68th validator voted for a different BlockParts PartSetHeader
{ {
addr := privValidators[67].GetPubKey().Address()
pubKey, err := privValidators[67].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 67) vote := withValidator(voteProto, addr, 67)
blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)} blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)}
_, err := signAddVote(privValidators[67], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
_, err = signAddVote(privValidators[67], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -230,10 +246,12 @@ func Test2_3MajorityRedux(t *testing.T) {
// 69th validator voted for different BlockParts Total // 69th validator voted for different BlockParts Total
{ {
addr := privValidators[68].GetPubKey().Address()
pubKey, err := privValidators[68].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 68) vote := withValidator(voteProto, addr, 68)
blockPartsHeader := PartSetHeader{blockPartsTotal + 1, blockPartsHeader.Hash} blockPartsHeader := PartSetHeader{blockPartsTotal + 1, blockPartsHeader.Hash}
_, err := signAddVote(privValidators[68], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
_, err = signAddVote(privValidators[68], withBlockPartsHeader(vote, blockPartsHeader), voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -245,9 +263,11 @@ func Test2_3MajorityRedux(t *testing.T) {
// 70th validator voted for different BlockHash // 70th validator voted for different BlockHash
{ {
addr := privValidators[69].GetPubKey().Address()
pubKey, err := privValidators[69].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 69) vote := withValidator(voteProto, addr, 69)
_, err := signAddVote(privValidators[69], withBlockHash(vote, tmrand.Bytes(32)), voteSet)
_, err = signAddVote(privValidators[69], withBlockHash(vote, tmrand.Bytes(32)), voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -259,9 +279,11 @@ func Test2_3MajorityRedux(t *testing.T) {
// 71st validator voted for the right BlockHash & BlockPartsHeader // 71st validator voted for the right BlockHash & BlockPartsHeader
{ {
addr := privValidators[70].GetPubKey().Address()
pubKey, err := privValidators[70].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 70) vote := withValidator(voteProto, addr, 70)
_, err := signAddVote(privValidators[70], vote, voteSet)
_, err = signAddVote(privValidators[70], vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -288,7 +310,9 @@ func TestBadVotes(t *testing.T) {
// val0 votes for nil. // val0 votes for nil.
{ {
addr := privValidators[0].GetPubKey().Address()
pubKey, err := privValidators[0].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 0) vote := withValidator(voteProto, addr, 0)
added, err := signAddVote(privValidators[0], vote, voteSet) added, err := signAddVote(privValidators[0], vote, voteSet)
if !added || err != nil { if !added || err != nil {
@ -298,7 +322,9 @@ func TestBadVotes(t *testing.T) {
// val0 votes again for some block. // val0 votes again for some block.
{ {
addr := privValidators[0].GetPubKey().Address()
pubKey, err := privValidators[0].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 0) vote := withValidator(voteProto, addr, 0)
added, err := signAddVote(privValidators[0], withBlockHash(vote, tmrand.Bytes(32)), voteSet) added, err := signAddVote(privValidators[0], withBlockHash(vote, tmrand.Bytes(32)), voteSet)
if added || err == nil { if added || err == nil {
@ -308,7 +334,9 @@ func TestBadVotes(t *testing.T) {
// val1 votes on another height // val1 votes on another height
{ {
addr := privValidators[1].GetPubKey().Address()
pubKey, err := privValidators[1].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 1) vote := withValidator(voteProto, addr, 1)
added, err := signAddVote(privValidators[1], withHeight(vote, height+1), voteSet) added, err := signAddVote(privValidators[1], withHeight(vote, height+1), voteSet)
if added || err == nil { if added || err == nil {
@ -318,7 +346,9 @@ func TestBadVotes(t *testing.T) {
// val2 votes on another round // val2 votes on another round
{ {
addr := privValidators[2].GetPubKey().Address()
pubKey, err := privValidators[2].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 2) vote := withValidator(voteProto, addr, 2)
added, err := signAddVote(privValidators[2], withRound(vote, round+1), voteSet) added, err := signAddVote(privValidators[2], withRound(vote, round+1), voteSet)
if added || err == nil { if added || err == nil {
@ -328,7 +358,9 @@ func TestBadVotes(t *testing.T) {
// val3 votes of another type. // val3 votes of another type.
{ {
addr := privValidators[3].GetPubKey().Address()
pubKey, err := privValidators[3].GetPubKey()
require.NoError(t, err)
addr := pubKey.Address()
vote := withValidator(voteProto, addr, 3) vote := withValidator(voteProto, addr, 3)
added, err := signAddVote(privValidators[3], withType(vote, byte(PrecommitType)), voteSet) added, err := signAddVote(privValidators[3], withType(vote, byte(PrecommitType)), voteSet)
if added || err == nil { if added || err == nil {
@ -353,7 +385,10 @@ func TestConflicts(t *testing.T) {
BlockID: BlockID{nil, PartSetHeader{}}, BlockID: BlockID{nil, PartSetHeader{}},
} }
val0Addr := privValidators[0].GetPubKey().Address()
val0, err := privValidators[0].GetPubKey()
require.NoError(t, err)
val0Addr := val0.Address()
// val0 votes for nil. // val0 votes for nil.
{ {
vote := withValidator(voteProto, val0Addr, 0) vote := withValidator(voteProto, val0Addr, 0)
@ -407,7 +442,9 @@ func TestConflicts(t *testing.T) {
// val1 votes for blockHash1. // val1 votes for blockHash1.
{ {
addr := privValidators[1].GetPubKey().Address()
pv, err := privValidators[1].GetPubKey()
assert.NoError(t, err)
addr := pv.Address()
vote := withValidator(voteProto, addr, 1) vote := withValidator(voteProto, addr, 1)
added, err := signAddVote(privValidators[1], withBlockHash(vote, blockHash1), voteSet) added, err := signAddVote(privValidators[1], withBlockHash(vote, blockHash1), voteSet)
if !added || err != nil { if !added || err != nil {
@ -425,7 +462,9 @@ func TestConflicts(t *testing.T) {
// val2 votes for blockHash2. // val2 votes for blockHash2.
{ {
addr := privValidators[2].GetPubKey().Address()
pv, err := privValidators[2].GetPubKey()
assert.NoError(t, err)
addr := pv.Address()
vote := withValidator(voteProto, addr, 2) vote := withValidator(voteProto, addr, 2)
added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash2), voteSet) added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash2), voteSet)
if !added || err != nil { if !added || err != nil {
@ -446,7 +485,9 @@ func TestConflicts(t *testing.T) {
// val2 votes for blockHash1. // val2 votes for blockHash1.
{ {
addr := privValidators[2].GetPubKey().Address()
pv, err := privValidators[2].GetPubKey()
assert.NoError(t, err)
addr := pv.Address()
vote := withValidator(voteProto, addr, 2) vote := withValidator(voteProto, addr, 2)
added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash1), voteSet) added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash1), voteSet)
if !added { if !added {
@ -488,9 +529,11 @@ func TestMakeCommit(t *testing.T) {
// 6 out of 10 voted for some block. // 6 out of 10 voted for some block.
for i := 0; i < 6; i++ { for i := 0; i < 6; i++ {
addr := privValidators[i].GetPubKey().Address()
pv, err := privValidators[i].GetPubKey()
assert.NoError(t, err)
addr := pv.Address()
vote := withValidator(voteProto, addr, i) vote := withValidator(voteProto, addr, i)
_, err := signAddVote(privValidators[i], vote, voteSet)
_, err = signAddVote(privValidators[i], vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -501,12 +544,14 @@ func TestMakeCommit(t *testing.T) {
// 7th voted for some other block. // 7th voted for some other block.
{ {
addr := privValidators[6].GetPubKey().Address()
pv, err := privValidators[6].GetPubKey()
assert.NoError(t, err)
addr := pv.Address()
vote := withValidator(voteProto, addr, 6) vote := withValidator(voteProto, addr, 6)
vote = withBlockHash(vote, tmrand.Bytes(32)) vote = withBlockHash(vote, tmrand.Bytes(32))
vote = withBlockPartsHeader(vote, PartSetHeader{123, tmrand.Bytes(32)}) vote = withBlockPartsHeader(vote, PartSetHeader{123, tmrand.Bytes(32)})
_, err := signAddVote(privValidators[6], vote, voteSet)
_, err = signAddVote(privValidators[6], vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -514,9 +559,11 @@ func TestMakeCommit(t *testing.T) {
// The 8th voted like everyone else. // The 8th voted like everyone else.
{ {
addr := privValidators[7].GetPubKey().Address()
pv, err := privValidators[7].GetPubKey()
assert.NoError(t, err)
addr := pv.Address()
vote := withValidator(voteProto, addr, 7) vote := withValidator(voteProto, addr, 7)
_, err := signAddVote(privValidators[7], vote, voteSet)
_, err = signAddVote(privValidators[7], vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -524,11 +571,13 @@ func TestMakeCommit(t *testing.T) {
// The 9th voted for nil. // The 9th voted for nil.
{ {
addr := privValidators[8].GetPubKey().Address()
pv, err := privValidators[8].GetPubKey()
assert.NoError(t, err)
addr := pv.Address()
vote := withValidator(voteProto, addr, 8) vote := withValidator(voteProto, addr, 8)
vote.BlockID = BlockID{} vote.BlockID = BlockID{}
_, err := signAddVote(privValidators[8], vote, voteSet)
_, err = signAddVote(privValidators[8], vote, voteSet)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }


+ 6
- 4
types/vote_test.go View File

@ -143,13 +143,14 @@ func TestVoteProposalNotEq(t *testing.T) {
func TestVoteVerifySignature(t *testing.T) { func TestVoteVerifySignature(t *testing.T) {
privVal := NewMockPV() privVal := NewMockPV()
pubkey := privVal.GetPubKey()
pubkey, err := privVal.GetPubKey()
require.NoError(t, err)
vote := examplePrecommit() vote := examplePrecommit()
signBytes := vote.SignBytes("test_chain_id") signBytes := vote.SignBytes("test_chain_id")
// sign it // sign it
err := privVal.SignVote("test_chain_id", vote)
err = privVal.SignVote("test_chain_id", vote)
require.NoError(t, err) require.NoError(t, err)
// verify the same vote // verify the same vote
@ -193,12 +194,13 @@ func TestIsVoteTypeValid(t *testing.T) {
func TestVoteVerify(t *testing.T) { func TestVoteVerify(t *testing.T) {
privVal := NewMockPV() privVal := NewMockPV()
pubkey := privVal.GetPubKey()
pubkey, err := privVal.GetPubKey()
require.NoError(t, err)
vote := examplePrevote() vote := examplePrevote()
vote.ValidatorAddress = pubkey.Address() vote.ValidatorAddress = pubkey.Address()
err := vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey())
err = vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey())
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Equal(t, ErrVoteInvalidValidatorAddress, err) assert.Equal(t, ErrVoteInvalidValidatorAddress, err)
} }


Loading…
Cancel
Save