github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/privval/retry_signer_client.go (about)

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