- package grpc
-
- import (
- "context"
- "crypto/tls"
- "crypto/x509"
- "io/ioutil"
- "os"
- "time"
-
- grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
- grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
-
- "github.com/tendermint/tendermint/config"
- "github.com/tendermint/tendermint/libs/log"
- tmnet "github.com/tendermint/tendermint/libs/net"
- grpc "google.golang.org/grpc"
- "google.golang.org/grpc/credentials"
- "google.golang.org/grpc/credentials/insecure"
- "google.golang.org/grpc/keepalive"
- )
-
- // DefaultDialOptions constructs a list of grpc dial options
- func DefaultDialOptions(
- extraOpts ...grpc.DialOption,
- ) []grpc.DialOption {
- const (
- retries = 50 // 50 * 100ms = 5s total
- timeout = 1 * time.Second
- maxCallRecvMsgSize = 1 << 20 // Default 5Mb
- )
-
- var kacp = keepalive.ClientParameters{
- Time: 10 * time.Second, // send pings every 10 seconds if there is no activity
- Timeout: 2 * time.Second, // wait 2 seconds for ping ack before considering the connection dead
- }
-
- opts := []grpc_retry.CallOption{
- grpc_retry.WithBackoff(grpc_retry.BackoffExponential(timeout)),
- }
-
- dialOpts := []grpc.DialOption{
- grpc.WithKeepaliveParams(kacp),
- grpc.WithDefaultCallOptions(
- grpc.MaxCallRecvMsgSize(maxCallRecvMsgSize),
- grpc_retry.WithMax(retries),
- ),
- grpc.WithUnaryInterceptor(
- grpc_retry.UnaryClientInterceptor(opts...),
- ),
- }
-
- dialOpts = append(dialOpts, extraOpts...)
-
- return dialOpts
- }
-
- func GenerateTLS(certPath, keyPath, ca string, log log.Logger) grpc.DialOption {
- certificate, err := tls.LoadX509KeyPair(
- certPath,
- keyPath,
- )
- if err != nil {
- log.Error("error", err)
- os.Exit(1)
- }
-
- certPool := x509.NewCertPool()
- bs, err := ioutil.ReadFile(ca)
- if err != nil {
- log.Error("failed to read ca cert:", "error", err)
- os.Exit(1)
- }
-
- ok := certPool.AppendCertsFromPEM(bs)
- if !ok {
- log.Error("failed to append certs")
- os.Exit(1)
- }
-
- transportCreds := credentials.NewTLS(&tls.Config{
- Certificates: []tls.Certificate{certificate},
- RootCAs: certPool,
- MinVersion: tls.VersionTLS13,
- })
-
- return grpc.WithTransportCredentials(transportCreds)
- }
-
- // DialRemoteSigner is a generalized function to dial the gRPC server.
- func DialRemoteSigner(
- cfg *config.PrivValidatorConfig,
- chainID string,
- logger log.Logger,
- usePrometheus bool,
- ) (*SignerClient, error) {
- var transportSecurity grpc.DialOption
- if cfg.AreSecurityOptionsPresent() {
- transportSecurity = GenerateTLS(cfg.ClientCertificateFile(),
- cfg.ClientKeyFile(), cfg.RootCAFile(), logger)
- } else {
- transportSecurity = grpc.WithTransportCredentials(insecure.NewCredentials())
- logger.Info("Using an insecure gRPC connection!")
- }
-
- dialOptions := DefaultDialOptions()
- if usePrometheus {
- grpcMetrics := grpc_prometheus.DefaultClientMetrics
- dialOptions = append(dialOptions, grpc.WithUnaryInterceptor(grpcMetrics.UnaryClientInterceptor()))
- }
-
- dialOptions = append(dialOptions, transportSecurity)
-
- ctx := context.Background()
- _, address := tmnet.ProtocolAndAddress(cfg.ListenAddr)
- conn, err := grpc.DialContext(ctx, address, dialOptions...)
- if err != nil {
- logger.Error("unable to connect to server", "target", address, "err", err)
- }
-
- return NewSignerClient(conn, chainID, logger)
- }
|