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