diff --git a/privval/signer_client.go b/privval/signer_client.go index bc032bb7a..a8684bbef 100644 --- a/privval/signer_client.go +++ b/privval/signer_client.go @@ -53,25 +53,25 @@ func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error { // Implement PrivValidator // GetPubKey retrieves a public key from a remote signer -func (sc *SignerClient) GetPubKey() crypto.PubKey { +func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) { response, err := sc.endpoint.SendRequest(&PubKeyRequest{}) if err != nil { sc.endpoint.Logger.Error("error sending request", "err", err) - return nil + return nil, err } pubKeyResp, ok := response.(*PubKeyResponse) if !ok { sc.endpoint.Logger.Error("response is not PubKeyResponse") - return nil + return nil, err } if pubKeyResp.Error != nil { sc.endpoint.Logger.Error("failed to get private validator's public key", "err", pubKeyResp.Error) - return nil + return nil, err } - return pubKeyResp.PubKey + return pubKeyResp.PubKey, nil } // SignVote requests a remote signer to sign a vote diff --git a/privval/signer_client_test.go b/privval/signer_client_test.go index d6ebff159..f68a156a2 100644 --- a/privval/signer_client_test.go +++ b/privval/signer_client_test.go @@ -58,13 +58,15 @@ func TestSignerGetPubKey(t *testing.T) { defer tc.signerService.OnStop() defer tc.signer.Close() - pubKey := tc.signer.GetPubKey() - expectedPubKey := tc.mockPV.GetPubKey() + pubKey, err := tc.signer.GetPubKey() + assert.NoError(t, err) + expectedPubKey, err := tc.mockPV.GetPubKey() + assert.NoError(t, err) assert.Equal(t, expectedPubKey, pubKey) - addr := tc.signer.GetPubKey().Address() - expectedAddr := tc.mockPV.GetPubKey().Address() + addr := pubKey.Address() + expectedAddr := expectedPubKey.Address() assert.Equal(t, expectedAddr, addr) }() diff --git a/privval/signer_service.go b/privval/signer_service.go index 016a7dde0..01d6ffda1 100644 --- a/privval/signer_service.go +++ b/privval/signer_service.go @@ -14,7 +14,10 @@ func HandleValidatorRequest(req RemoteSignerMsg, chainID string, privVal types.P switch r := req.(type) { case *PubKeyRequest: var p crypto.PubKey - p = privVal.GetPubKey() + p, err = privVal.GetPubKey() + if err != nil { + return nil, err + } res = &PubKeyResponse{p, nil} case *SignVoteRequest: diff --git a/types/priv_validator.go b/types/priv_validator.go index d984314bd..61047c02a 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -12,9 +12,7 @@ import ( // PrivValidator defines the functionality of a local Tendermint validator // that signs votes and proposals, and never double signs. type PrivValidator interface { - // TODO: Why it is not possible to return an error? nil feels not enough.. - GetPubKey() crypto.PubKey - + GetPubKey() (crypto.PubKey, error) SignVote(chainID string, vote *Vote) error SignProposal(chainID string, proposal *Proposal) error } @@ -29,7 +27,17 @@ func (pvs PrivValidatorsByAddress) Len() int { } func (pvs PrivValidatorsByAddress) Less(i, j int) bool { - return bytes.Compare(pvs[i].GetPubKey().Address(), pvs[j].GetPubKey().Address()) == -1 + pk1, err := pvs[i].GetPubKey() + if err != nil { + return false // Send pk with errors to the end + } + + pk2, err := pvs[j].GetPubKey() + if err != nil { + return true // Send pk with errors to the end + } + + return bytes.Compare(pk1.Address(), pk2.Address()) == -1 } func (pvs PrivValidatorsByAddress) Swap(i, j int) { @@ -61,8 +69,8 @@ func NewMockPVWithParams(privKey crypto.PrivKey, breakProposalSigning, breakVote } // 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. @@ -97,7 +105,12 @@ func (pv *MockPV) SignProposal(chainID string, proposal *Proposal) error { // String returns a string representation of the MockPV. func (pv *MockPV) String() string { - addr := pv.GetPubKey().Address() + pk, err := pv.GetPubKey() + if err != nil { + return fmt.Sprintf("MockPV{%v}", err) + } + + addr := pk.Address() return fmt.Sprintf("MockPV{%v}", addr) } diff --git a/types/test_util.go b/types/test_util.go index 18e472148..9e83f1bdb 100644 --- a/types/test_util.go +++ b/types/test_util.go @@ -10,7 +10,12 @@ func MakeCommit(blockID BlockID, height int64, round int, // all sign for i := 0; i < len(validators); i++ { - addr := validators[i].GetPubKey().Address() + pk, err := validators[i].GetPubKey() + if err != nil { + return nil, err + } + + addr := pk.Address() vote := &Vote{ ValidatorAddress: addr, ValidatorIndex: i, @@ -21,7 +26,7 @@ func MakeCommit(blockID BlockID, height int64, round int, Timestamp: tmtime.Now(), } - _, err := signAddVote(validators[i], vote, voteSet) + _, err = signAddVote(validators[i], vote, voteSet) if err != nil { return nil, err } diff --git a/types/validator.go b/types/validator.go index 325d20f5c..5d11d46b3 100644 --- a/types/validator.go +++ b/types/validator.go @@ -98,13 +98,18 @@ func (v *Validator) Bytes() []byte { // RandValidator returns a randomized validator, useful for testing. // UNSTABLE -func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator) { +func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator, error) { privVal := NewMockPV() votePower := minPower if randPower { votePower += int64(cmn.RandUint32()) } - pubKey := privVal.GetPubKey() + + pubKey, err := privVal.GetPubKey() + if err != nil { + return nil, nil, err + } + val := NewValidator(pubKey, votePower) - return val, privVal + return val, privVal, nil } diff --git a/types/validator_set.go b/types/validator_set.go index 36ce67f06..b21485bb3 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -793,17 +793,23 @@ func (valz ValidatorsByAddress) Swap(i, j int) { // RandValidatorSet returns a randomized validator set, useful for testing. // NOTE: PrivValidator are in order. // UNSTABLE -func RandValidatorSet(numValidators int, votingPower int64) (*ValidatorSet, []PrivValidator) { +func RandValidatorSet(numValidators int, votingPower int64) (*ValidatorSet, []PrivValidator, error) { valz := make([]*Validator, numValidators) privValidators := make([]PrivValidator, numValidators) + for i := 0; i < numValidators; i++ { - val, privValidator := RandValidator(false, votingPower) + val, privValidator, err := RandValidator(false, votingPower) + if err != nil { + return nil, nil, err + } valz[i] = val privValidators[i] = privValidator } + vals := NewValidatorSet(valz) sort.Sort(PrivValidatorsByAddress(privValidators)) - return vals, privValidators + + return vals, privValidators, nil } ///////////////////////////////////////////////////////////////////////////////