github.com/number571/tendermint@v0.34.11-gost/privval/grpc/util.go (about)

     1  package grpc
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"crypto/x509"
     7  	"io/ioutil"
     8  	"os"
     9  	"time"
    10  
    11  	grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
    12  	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
    13  
    14  	cfg "github.com/number571/tendermint/config"
    15  	"github.com/number571/tendermint/libs/log"
    16  	tmnet "github.com/number571/tendermint/libs/net"
    17  	grpc "google.golang.org/grpc"
    18  	"google.golang.org/grpc/credentials"
    19  	"google.golang.org/grpc/keepalive"
    20  )
    21  
    22  // DefaultDialOptions constructs a list of grpc dial options
    23  func DefaultDialOptions(
    24  	extraOpts ...grpc.DialOption,
    25  ) []grpc.DialOption {
    26  	const (
    27  		retries            = 50 // 50 * 100ms = 5s total
    28  		timeout            = 1 * time.Second
    29  		maxCallRecvMsgSize = 1 << 20 // Default 5Mb
    30  	)
    31  
    32  	var kacp = keepalive.ClientParameters{
    33  		Time:    10 * time.Second, // send pings every 10 seconds if there is no activity
    34  		Timeout: 2 * time.Second,  // wait 2 seconds for ping ack before considering the connection dead
    35  	}
    36  
    37  	opts := []grpc_retry.CallOption{
    38  		grpc_retry.WithBackoff(grpc_retry.BackoffExponential(timeout)),
    39  	}
    40  
    41  	dialOpts := []grpc.DialOption{
    42  		grpc.WithKeepaliveParams(kacp),
    43  		grpc.WithDefaultCallOptions(
    44  			grpc.MaxCallRecvMsgSize(maxCallRecvMsgSize),
    45  			grpc_retry.WithMax(retries),
    46  		),
    47  		grpc.WithUnaryInterceptor(
    48  			grpc_retry.UnaryClientInterceptor(opts...),
    49  		),
    50  	}
    51  
    52  	dialOpts = append(dialOpts, extraOpts...)
    53  
    54  	return dialOpts
    55  }
    56  
    57  func GenerateTLS(certPath, keyPath, ca string, log log.Logger) grpc.DialOption {
    58  	certificate, err := tls.LoadX509KeyPair(
    59  		certPath,
    60  		keyPath,
    61  	)
    62  	if err != nil {
    63  		log.Error("error", err)
    64  		os.Exit(1)
    65  	}
    66  
    67  	certPool := x509.NewCertPool()
    68  	bs, err := ioutil.ReadFile(ca)
    69  	if err != nil {
    70  		log.Error("failed to read ca cert:", "error", err)
    71  		os.Exit(1)
    72  	}
    73  
    74  	ok := certPool.AppendCertsFromPEM(bs)
    75  	if !ok {
    76  		log.Error("failed to append certs")
    77  		os.Exit(1)
    78  	}
    79  
    80  	transportCreds := credentials.NewTLS(&tls.Config{
    81  		Certificates: []tls.Certificate{certificate},
    82  		RootCAs:      certPool,
    83  		MinVersion:   tls.VersionTLS13,
    84  	})
    85  
    86  	return grpc.WithTransportCredentials(transportCreds)
    87  }
    88  
    89  // DialRemoteSigner is  a generalized function to dial the gRPC server.
    90  func DialRemoteSigner(
    91  	config *cfg.PrivValidatorConfig,
    92  	chainID string,
    93  	logger log.Logger,
    94  	usePrometheus bool,
    95  ) (*SignerClient, error) {
    96  	var transportSecurity grpc.DialOption
    97  	if config.AreSecurityOptionsPresent() {
    98  		transportSecurity = GenerateTLS(config.ClientCertificateFile(),
    99  			config.ClientKeyFile(), config.RootCAFile(), logger)
   100  	} else {
   101  		transportSecurity = grpc.WithInsecure()
   102  		logger.Info("Using an insecure gRPC connection!")
   103  	}
   104  
   105  	dialOptions := DefaultDialOptions()
   106  	if usePrometheus {
   107  		grpcMetrics := grpc_prometheus.DefaultClientMetrics
   108  		dialOptions = append(dialOptions, grpc.WithUnaryInterceptor(grpcMetrics.UnaryClientInterceptor()))
   109  	}
   110  
   111  	dialOptions = append(dialOptions, transportSecurity)
   112  
   113  	ctx := context.Background()
   114  	_, address := tmnet.ProtocolAndAddress(config.ListenAddr)
   115  	conn, err := grpc.DialContext(ctx, address, dialOptions...)
   116  	if err != nil {
   117  		logger.Error("unable to connect to server", "target", address, "err", err)
   118  	}
   119  
   120  	return NewSignerClient(conn, chainID, logger)
   121  }