github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/privval/signer_client.go (about) 1 package privval 2 3 import ( 4 "time" 5 6 "github.com/gnolang/gno/tm2/pkg/bft/types" 7 "github.com/gnolang/gno/tm2/pkg/crypto" 8 "github.com/gnolang/gno/tm2/pkg/errors" 9 ) 10 11 // SignerClient implements PrivValidator. 12 // Handles remote validator connections that provide signing services 13 type SignerClient struct { 14 endpoint *SignerListenerEndpoint 15 } 16 17 var _ types.PrivValidator = (*SignerClient)(nil) 18 19 // NewSignerClient returns an instance of SignerClient. 20 // it will start the endpoint (if not already started) 21 func NewSignerClient(endpoint *SignerListenerEndpoint) (*SignerClient, error) { 22 if !endpoint.IsRunning() { 23 if err := endpoint.Start(); err != nil { 24 return nil, errors.Wrap(err, "failed to start listener endpoint") 25 } 26 } 27 28 return &SignerClient{endpoint: endpoint}, nil 29 } 30 31 // Close closes the underlying connection 32 func (sc *SignerClient) Close() error { 33 return sc.endpoint.Close() 34 } 35 36 // IsConnected indicates with the signer is connected to a remote signing service 37 func (sc *SignerClient) IsConnected() bool { 38 return sc.endpoint.IsConnected() 39 } 40 41 // WaitForConnection waits maxWait for a connection or returns a timeout error 42 func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error { 43 return sc.endpoint.WaitForConnection(maxWait) 44 } 45 46 //-------------------------------------------------------- 47 // Implement PrivValidator 48 49 // Ping sends a ping request to the remote signer 50 func (sc *SignerClient) Ping() error { 51 response, err := sc.endpoint.SendRequest(&PingRequest{}) 52 if err != nil { 53 sc.endpoint.Logger.Error("SignerClient::Ping", "err", err) 54 return nil 55 } 56 57 _, ok := response.(*PingResponse) 58 if !ok { 59 sc.endpoint.Logger.Error("SignerClient::Ping", "err", "response != PingResponse") 60 return err 61 } 62 63 return nil 64 } 65 66 // GetPubKey retrieves a public key from a remote signer 67 func (sc *SignerClient) GetPubKey() crypto.PubKey { 68 response, err := sc.endpoint.SendRequest(&PubKeyRequest{}) 69 if err != nil { 70 sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", err) 71 return nil 72 } 73 74 pubKeyResp, ok := response.(*PubKeyResponse) 75 if !ok { 76 sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != PubKeyResponse") 77 return nil 78 } 79 80 if pubKeyResp.Error != nil { 81 sc.endpoint.Logger.Error("failed to get private validator's public key", "err", pubKeyResp.Error) 82 return nil 83 } 84 85 return pubKeyResp.PubKey 86 } 87 88 // SignVote requests a remote signer to sign a vote 89 func (sc *SignerClient) SignVote(chainID string, vote *types.Vote) error { 90 response, err := sc.endpoint.SendRequest(&SignVoteRequest{Vote: vote}) 91 if err != nil { 92 sc.endpoint.Logger.Error("SignerClient::SignVote", "err", err) 93 return err 94 } 95 96 resp, ok := response.(*SignedVoteResponse) 97 if !ok { 98 sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != SignedVoteResponse") 99 return ErrUnexpectedResponse 100 } 101 102 if resp.Error != nil { 103 return resp.Error 104 } 105 *vote = *resp.Vote 106 107 return nil 108 } 109 110 // SignProposal requests a remote signer to sign a proposal 111 func (sc *SignerClient) SignProposal(chainID string, proposal *types.Proposal) error { 112 response, err := sc.endpoint.SendRequest(&SignProposalRequest{Proposal: proposal}) 113 if err != nil { 114 sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", err) 115 return err 116 } 117 118 resp, ok := response.(*SignedProposalResponse) 119 if !ok { 120 sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", "response != SignedProposalResponse") 121 return ErrUnexpectedResponse 122 } 123 if resp.Error != nil { 124 return resp.Error 125 } 126 *proposal = *resp.Proposal 127 128 return nil 129 }