github.com/prysmaticlabs/prysm@v1.4.4/validator/slashing-protection/slasher_client.go (about)

     1  package slashingprotection
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  	"time"
     9  
    10  	middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    11  	grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
    12  	grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
    13  	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
    14  	ethsl "github.com/prysmaticlabs/prysm/proto/slashing"
    15  	"github.com/prysmaticlabs/prysm/shared/grpcutils"
    16  	"go.opencensus.io/plugin/ocgrpc"
    17  	"google.golang.org/grpc"
    18  	"google.golang.org/grpc/connectivity"
    19  	"google.golang.org/grpc/credentials"
    20  )
    21  
    22  // Service represents a service to manage the validator
    23  // ￿slashing protection.
    24  type Service struct {
    25  	cfg           *Config
    26  	ctx           context.Context
    27  	cancel        context.CancelFunc
    28  	conn          *grpc.ClientConn
    29  	grpcHeaders   []string
    30  	slasherClient ethsl.SlasherClient
    31  }
    32  
    33  // Config for the validator service.
    34  type Config struct {
    35  	Endpoint                   string
    36  	CertFlag                   string
    37  	GrpcMaxCallRecvMsgSizeFlag int
    38  	GrpcRetriesFlag            uint
    39  	GrpcRetryDelay             time.Duration
    40  	GrpcHeadersFlag            string
    41  }
    42  
    43  // NewService creates a new validator service for the service
    44  // registry.
    45  func NewService(ctx context.Context, cfg *Config) (*Service, error) {
    46  	ctx, cancel := context.WithCancel(ctx)
    47  	return &Service{
    48  		cfg:         cfg,
    49  		ctx:         ctx,
    50  		cancel:      cancel,
    51  		grpcHeaders: strings.Split(cfg.GrpcHeadersFlag, ","),
    52  	}, nil
    53  }
    54  
    55  // Start the slasher protection service and grpc client.
    56  func (s *Service) Start() {
    57  	if s.cfg.Endpoint != "" {
    58  		s.slasherClient = s.startSlasherClient()
    59  	}
    60  }
    61  
    62  func (s *Service) startSlasherClient() ethsl.SlasherClient {
    63  	var dialOpt grpc.DialOption
    64  
    65  	if s.cfg.CertFlag != "" {
    66  		creds, err := credentials.NewClientTLSFromFile(s.cfg.CertFlag, "")
    67  		if err != nil {
    68  			log.Errorf("Could not get valid slasher credentials: %v", err)
    69  			return nil
    70  		}
    71  		dialOpt = grpc.WithTransportCredentials(creds)
    72  	} else {
    73  		dialOpt = grpc.WithInsecure()
    74  		log.Warn("You are using an insecure slasher gRPC connection! Please provide a certificate and key to use a secure connection.")
    75  	}
    76  
    77  	s.ctx = grpcutils.AppendHeaders(s.ctx, s.grpcHeaders)
    78  
    79  	opts := []grpc.DialOption{
    80  		dialOpt,
    81  		grpc.WithDefaultCallOptions(
    82  			grpc_retry.WithMax(s.cfg.GrpcRetriesFlag),
    83  			grpc_retry.WithBackoff(grpc_retry.BackoffLinear(s.cfg.GrpcRetryDelay)),
    84  		),
    85  		grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
    86  		grpc.WithStreamInterceptor(middleware.ChainStreamClient(
    87  			grpc_opentracing.StreamClientInterceptor(),
    88  			grpc_prometheus.StreamClientInterceptor,
    89  			grpc_retry.StreamClientInterceptor(),
    90  		)),
    91  		grpc.WithUnaryInterceptor(middleware.ChainUnaryClient(
    92  			grpc_opentracing.UnaryClientInterceptor(),
    93  			grpc_prometheus.UnaryClientInterceptor,
    94  			grpc_retry.UnaryClientInterceptor(),
    95  			grpcutils.LogRequests,
    96  		)),
    97  	}
    98  	conn, err := grpc.DialContext(s.ctx, s.cfg.Endpoint, opts...)
    99  	if err != nil {
   100  		log.Errorf("Could not dial slasher endpoint: %s, %v", s.cfg.Endpoint, err)
   101  		return nil
   102  	}
   103  	log.Debug("Successfully started slasher gRPC connection")
   104  	s.conn = conn
   105  	return ethsl.NewSlasherClient(s.conn)
   106  
   107  }
   108  
   109  // Stop the validator service.
   110  func (s *Service) Stop() error {
   111  	s.cancel()
   112  	log.Info("Stopping slashing protection service")
   113  	if s.conn != nil {
   114  		return s.conn.Close()
   115  	}
   116  	return nil
   117  }
   118  
   119  // Status checks if the connection to slasher server is ready,
   120  // returns error otherwise.
   121  func (s *Service) Status() error {
   122  	if s.conn == nil {
   123  		return errors.New("no connection to slasher RPC")
   124  	}
   125  	if s.conn.GetState() != connectivity.Ready {
   126  		return fmt.Errorf("can`t connect to slasher server at: %v connection status: %v ", s.cfg.Endpoint, s.conn.GetState())
   127  	}
   128  	return nil
   129  }