github.com/prysmaticlabs/prysm@v1.4.4/slasher/rpc/service.go (about)

     1  // Package rpc defines an implementation of a gRPC slasher service,
     2  // providing endpoints for determining whether or not a block/attestation
     3  // is slashable based on slasher's evidence.
     4  package rpc
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"net"
    10  
    11  	middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    12  	recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
    13  	grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
    14  	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
    15  	slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
    16  	"github.com/prysmaticlabs/prysm/shared/traceutil"
    17  	"github.com/prysmaticlabs/prysm/slasher/beaconclient"
    18  	"github.com/prysmaticlabs/prysm/slasher/db"
    19  	"github.com/prysmaticlabs/prysm/slasher/detection"
    20  	"go.opencensus.io/plugin/ocgrpc"
    21  	"google.golang.org/grpc"
    22  	"google.golang.org/grpc/credentials"
    23  	"google.golang.org/grpc/reflection"
    24  )
    25  
    26  // Service defines a server implementation of the gRPC Slasher service,
    27  // providing RPC endpoints for retrieving slashing proofs for malicious validators.
    28  type Service struct {
    29  	cfg             *Config
    30  	ctx             context.Context
    31  	cancel          context.CancelFunc
    32  	listener        net.Listener
    33  	grpcServer      *grpc.Server
    34  	credentialError error
    35  }
    36  
    37  // Config options for the slasher node RPC server.
    38  type Config struct {
    39  	Host         string
    40  	Port         string
    41  	CertFlag     string
    42  	KeyFlag      string
    43  	Detector     *detection.Service
    44  	SlasherDB    db.Database
    45  	BeaconClient *beaconclient.Service
    46  }
    47  
    48  // NewService instantiates a new RPC service instance that will
    49  // be registered into a running beacon node.
    50  func NewService(ctx context.Context, cfg *Config) *Service {
    51  	ctx, cancel := context.WithCancel(ctx)
    52  	return &Service{
    53  		cfg:    cfg,
    54  		ctx:    ctx,
    55  		cancel: cancel,
    56  	}
    57  }
    58  
    59  // Start the gRPC service.
    60  func (s *Service) Start() {
    61  	address := fmt.Sprintf("%s:%s", s.cfg.Host, s.cfg.Port)
    62  	lis, err := net.Listen("tcp", address)
    63  	if err != nil {
    64  		log.Errorf("Could not listen to port in Start() %s: %v", address, err)
    65  	}
    66  	s.listener = lis
    67  	log.WithField("address", address).Info("gRPC server listening on port")
    68  
    69  	opts := []grpc.ServerOption{
    70  		grpc.StatsHandler(&ocgrpc.ServerHandler{}),
    71  		grpc.StreamInterceptor(middleware.ChainStreamServer(
    72  			recovery.StreamServerInterceptor(
    73  				recovery.WithRecoveryHandlerContext(traceutil.RecoveryHandlerFunc),
    74  			),
    75  			grpc_prometheus.StreamServerInterceptor,
    76  			grpc_opentracing.StreamServerInterceptor(),
    77  		)),
    78  		grpc.UnaryInterceptor(middleware.ChainUnaryServer(
    79  			recovery.UnaryServerInterceptor(
    80  				recovery.WithRecoveryHandlerContext(traceutil.RecoveryHandlerFunc),
    81  			),
    82  			grpc_prometheus.UnaryServerInterceptor,
    83  			grpc_opentracing.UnaryServerInterceptor(),
    84  		)),
    85  	}
    86  	grpc_prometheus.EnableHandlingTimeHistogram()
    87  	// TODO(#791): Utilize a certificate for secure connections
    88  	// between beacon nodes and validator clients.
    89  	if s.cfg.CertFlag != "" && s.cfg.KeyFlag != "" {
    90  		creds, err := credentials.NewServerTLSFromFile(s.cfg.CertFlag, s.cfg.KeyFlag)
    91  		if err != nil {
    92  			log.Errorf("Could not load TLS keys: %s", err)
    93  			s.credentialError = err
    94  		}
    95  		opts = append(opts, grpc.Creds(creds))
    96  	} else {
    97  		log.Warn("You are using an insecure gRPC server. If you are running your slasher and " +
    98  			"validator on the same machines, you can ignore this message. If you want to know " +
    99  			"how to enable secure connections, see: https://docs.prylabs.network/docs/prysm-usage/secure-grpc")
   100  	}
   101  	s.grpcServer = grpc.NewServer(opts...)
   102  
   103  	slasherServer := &Server{
   104  		ctx:          s.ctx,
   105  		detector:     s.cfg.Detector,
   106  		slasherDB:    s.cfg.SlasherDB,
   107  		beaconClient: s.cfg.BeaconClient,
   108  	}
   109  	slashpb.RegisterSlasherServer(s.grpcServer, slasherServer)
   110  
   111  	// Register reflection service on gRPC server.
   112  	reflection.Register(s.grpcServer)
   113  
   114  	go func() {
   115  		if s.listener == nil {
   116  			return
   117  		}
   118  		if err := s.grpcServer.Serve(s.listener); err != nil {
   119  			log.Errorf("Could not serve gRPC: %v", err)
   120  		}
   121  	}()
   122  }
   123  
   124  // Stop the service.
   125  func (s *Service) Stop() error {
   126  	s.cancel()
   127  	if s.listener != nil {
   128  		s.grpcServer.GracefulStop()
   129  		log.Debug("Initiated graceful stop of gRPC server")
   130  	}
   131  	return nil
   132  }
   133  
   134  // Status returns nil if slasher is ready to receive attestations and
   135  // blocks from clients for slashing detection.
   136  func (s *Service) Status() error {
   137  	if s.credentialError != nil {
   138  		return s.credentialError
   139  	}
   140  	if bs := s.cfg.BeaconClient.Status(); bs != nil {
   141  		return bs
   142  	}
   143  	return s.cfg.Detector.Status()
   144  }