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 }