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 }