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