github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/privval/signer_client.go (about) 1 package privval 2 3 import ( 4 "fmt" 5 "time" 6 7 privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval" 8 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 9 10 "github.com/line/ostracon/crypto" 11 cryptoenc "github.com/line/ostracon/crypto/encoding" 12 ocprivvalproto "github.com/line/ostracon/proto/ostracon/privval" 13 "github.com/line/ostracon/types" 14 ) 15 16 // SignerClient implements PrivValidator. 17 // Handles remote validator connections that provide signing services 18 type SignerClient struct { 19 endpoint *SignerListenerEndpoint 20 chainID string 21 } 22 23 var _ types.PrivValidator = (*SignerClient)(nil) 24 25 // NewSignerClient returns an instance of SignerClient. 26 // it will start the endpoint (if not already started) 27 func NewSignerClient(endpoint *SignerListenerEndpoint, chainID string) (*SignerClient, error) { 28 if !endpoint.IsRunning() { 29 if err := endpoint.Start(); err != nil { 30 return nil, fmt.Errorf("failed to start listener endpoint: %w", err) 31 } 32 } 33 34 return &SignerClient{endpoint: endpoint, chainID: chainID}, nil 35 } 36 37 // Close closes the underlying connection 38 func (sc *SignerClient) Close() error { 39 return sc.endpoint.Close() 40 } 41 42 // IsConnected indicates with the signer is connected to a remote signing service 43 func (sc *SignerClient) IsConnected() bool { 44 return sc.endpoint.IsConnected() 45 } 46 47 // WaitForConnection waits maxWait for a connection or returns a timeout error 48 func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error { 49 return sc.endpoint.WaitForConnection(maxWait) 50 } 51 52 //-------------------------------------------------------- 53 // Implement PrivValidator 54 55 // GetPubKey retrieves a public key from a remote signer 56 // returns an error if client is not able to provide the key 57 func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) { 58 response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PubKeyRequest{ChainId: sc.chainID})) 59 if err != nil { 60 return nil, fmt.Errorf("send: %w", err) 61 } 62 63 resp := response.GetPubKeyResponse() 64 if resp == nil { 65 return nil, ErrUnexpectedResponse 66 } 67 if resp.Error != nil { 68 return nil, &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} 69 } 70 71 pk, err := cryptoenc.PubKeyFromProto(&resp.PubKey) 72 if err != nil { 73 return nil, err 74 } 75 76 return pk, nil 77 } 78 79 // SignVote requests a remote signer to sign a vote 80 func (sc *SignerClient) SignVote(chainID string, vote *tmproto.Vote) error { 81 response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.SignVoteRequest{Vote: vote, ChainId: chainID})) 82 if err != nil { 83 return err 84 } 85 86 resp := response.GetSignedVoteResponse() 87 if resp == nil { 88 return ErrUnexpectedResponse 89 } 90 if resp.Error != nil { 91 return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} 92 } 93 94 *vote = resp.Vote 95 96 return nil 97 } 98 99 // SignProposal requests a remote signer to sign a proposal 100 func (sc *SignerClient) SignProposal(chainID string, proposal *tmproto.Proposal) error { 101 response, err := sc.endpoint.SendRequest(mustWrapMsg( 102 &privvalproto.SignProposalRequest{Proposal: proposal, ChainId: chainID}, 103 )) 104 if err != nil { 105 return err 106 } 107 108 resp := response.GetSignedProposalResponse() 109 if resp == nil { 110 return ErrUnexpectedResponse 111 } 112 if resp.Error != nil { 113 return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} 114 } 115 116 *proposal = resp.Proposal 117 118 return nil 119 } 120 121 // GenerateVRFProof requests a remote signer to generate a VRF proof 122 func (sc *SignerClient) GenerateVRFProof(message []byte) (crypto.Proof, error) { 123 msg := &ocprivvalproto.VRFProofRequest{Message: message} 124 response, err := sc.endpoint.SendRequest(mustWrapMsg(msg)) 125 if err != nil { 126 sc.endpoint.Logger.Error("SignerClient::GenerateVRFProof", "err", err) 127 return nil, err 128 } 129 130 switch r := response.Sum.(type) { 131 case *ocprivvalproto.Message_VrfProofResponse: 132 if r.VrfProofResponse.Error != nil { 133 return nil, fmt.Errorf(r.VrfProofResponse.Error.Description) 134 } 135 return r.VrfProofResponse.Proof, nil 136 default: 137 sc.endpoint.Logger.Error("SignerClient::GenerateVRFProof", "err", "response != VRFProofResponse") 138 return nil, ErrUnexpectedResponse 139 } 140 }