You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
2.8 KiB

  1. package grpc
  2. import (
  3. "context"
  4. grpc "google.golang.org/grpc"
  5. "google.golang.org/grpc/status"
  6. "github.com/tendermint/tendermint/crypto"
  7. cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
  8. "github.com/tendermint/tendermint/libs/log"
  9. privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval"
  10. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  11. "github.com/tendermint/tendermint/types"
  12. )
  13. // SignerClient implements PrivValidator.
  14. // Handles remote validator connections that provide signing services
  15. type SignerClient struct {
  16. logger log.Logger
  17. client privvalproto.PrivValidatorAPIClient
  18. conn *grpc.ClientConn
  19. chainID string
  20. }
  21. var _ types.PrivValidator = (*SignerClient)(nil)
  22. // NewSignerClient returns an instance of SignerClient.
  23. // it will start the endpoint (if not already started)
  24. func NewSignerClient(conn *grpc.ClientConn,
  25. chainID string, log log.Logger) (*SignerClient, error) {
  26. sc := &SignerClient{
  27. logger: log,
  28. chainID: chainID,
  29. client: privvalproto.NewPrivValidatorAPIClient(conn), // Create the Private Validator Client
  30. }
  31. return sc, nil
  32. }
  33. // Close closes the underlying connection
  34. func (sc *SignerClient) Close() error {
  35. sc.logger.Info("Stopping service")
  36. if sc.conn != nil {
  37. return sc.conn.Close()
  38. }
  39. return nil
  40. }
  41. //--------------------------------------------------------
  42. // Implement PrivValidator
  43. // GetPubKey retrieves a public key from a remote signer
  44. // returns an error if client is not able to provide the key
  45. func (sc *SignerClient) GetPubKey(ctx context.Context) (crypto.PubKey, error) {
  46. resp, err := sc.client.GetPubKey(ctx, &privvalproto.PubKeyRequest{ChainId: sc.chainID})
  47. if err != nil {
  48. errStatus, _ := status.FromError(err)
  49. sc.logger.Error("SignerClient::GetPubKey", "err", errStatus.Message())
  50. return nil, errStatus.Err()
  51. }
  52. pk, err := cryptoenc.PubKeyFromProto(resp.PubKey)
  53. if err != nil {
  54. return nil, err
  55. }
  56. return pk, nil
  57. }
  58. // SignVote requests a remote signer to sign a vote
  59. func (sc *SignerClient) SignVote(ctx context.Context, chainID string, vote *tmproto.Vote) error {
  60. resp, err := sc.client.SignVote(ctx, &privvalproto.SignVoteRequest{ChainId: sc.chainID, Vote: vote})
  61. if err != nil {
  62. errStatus, _ := status.FromError(err)
  63. sc.logger.Error("Client SignVote", "err", errStatus.Message())
  64. return errStatus.Err()
  65. }
  66. *vote = resp.Vote
  67. return nil
  68. }
  69. // SignProposal requests a remote signer to sign a proposal
  70. func (sc *SignerClient) SignProposal(ctx context.Context, chainID string, proposal *tmproto.Proposal) error {
  71. resp, err := sc.client.SignProposal(
  72. ctx, &privvalproto.SignProposalRequest{ChainId: chainID, Proposal: proposal})
  73. if err != nil {
  74. errStatus, _ := status.FromError(err)
  75. sc.logger.Error("SignerClient::SignProposal", "err", errStatus.Message())
  76. return errStatus.Err()
  77. }
  78. *proposal = resp.Proposal
  79. return nil
  80. }