github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/privval/retry_signer_client.go (about) 1 package privval 2 3 import ( 4 "fmt" 5 "time" 6 7 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 8 9 "github.com/line/ostracon/crypto" 10 "github.com/line/ostracon/types" 11 ) 12 13 // RetrySignerClient wraps SignerClient adding retry for each operation (except 14 // Ping) w/ a timeout. 15 type RetrySignerClient struct { 16 next *SignerClient 17 retries int 18 timeout time.Duration 19 } 20 21 // NewRetrySignerClient returns RetrySignerClient. If +retries+ is 0, the 22 // client will be retrying each operation indefinitely. 23 func NewRetrySignerClient(sc *SignerClient, retries int, timeout time.Duration) *RetrySignerClient { 24 return &RetrySignerClient{sc, retries, timeout} 25 } 26 27 var _ types.PrivValidator = (*RetrySignerClient)(nil) 28 29 func (sc *RetrySignerClient) Close() error { 30 return sc.next.Close() 31 } 32 33 func (sc *RetrySignerClient) IsConnected() bool { 34 return sc.next.IsConnected() 35 } 36 37 func (sc *RetrySignerClient) WaitForConnection(maxWait time.Duration) error { 38 return sc.next.WaitForConnection(maxWait) 39 } 40 41 //-------------------------------------------------------- 42 // Implement PrivValidator 43 44 func (sc *RetrySignerClient) GetPubKey() (crypto.PubKey, error) { 45 var ( 46 pk crypto.PubKey 47 err error 48 ) 49 for i := 0; i < sc.retries || sc.retries == 0; i++ { 50 pk, err = sc.next.GetPubKey() 51 if err == nil { 52 return pk, nil 53 } 54 // If remote signer errors, we don't retry. 55 if _, ok := err.(*RemoteSignerError); ok { 56 return nil, err 57 } 58 time.Sleep(sc.timeout) 59 } 60 return nil, fmt.Errorf("exhausted all attempts to get pubkey: %w", err) 61 } 62 63 func (sc *RetrySignerClient) SignVote(chainID string, vote *tmproto.Vote) error { 64 var err error 65 for i := 0; i < sc.retries || sc.retries == 0; i++ { 66 err = sc.next.SignVote(chainID, vote) 67 if err == nil { 68 return nil 69 } 70 // If remote signer errors, we don't retry. 71 if _, ok := err.(*RemoteSignerError); ok { 72 return err 73 } 74 time.Sleep(sc.timeout) 75 } 76 return fmt.Errorf("exhausted all attempts to sign vote: %w", err) 77 } 78 79 func (sc *RetrySignerClient) SignProposal(chainID string, proposal *tmproto.Proposal) error { 80 var err error 81 for i := 0; i < sc.retries || sc.retries == 0; i++ { 82 err = sc.next.SignProposal(chainID, proposal) 83 if err == nil { 84 return nil 85 } 86 // If remote signer errors, we don't retry. 87 if _, ok := err.(*RemoteSignerError); ok { 88 return err 89 } 90 time.Sleep(sc.timeout) 91 } 92 return fmt.Errorf("exhausted all attempts to sign proposal: %w", err) 93 } 94 95 func (sc *RetrySignerClient) GenerateVRFProof(message []byte) (crypto.Proof, error) { 96 var err error 97 var proof crypto.Proof 98 for i := 0; i < sc.retries || sc.retries == 0; i++ { 99 proof, err = sc.next.GenerateVRFProof(message) 100 if err == nil { 101 return proof, nil 102 } 103 time.Sleep(sc.timeout) 104 } 105 return proof, fmt.Errorf("exhausted all attempts to generate vrf proof: %w", err) 106 }