github.com/prysmaticlabs/prysm@v1.4.4/validator/rpc/server.go (about)

     1  package rpc
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"time"
     9  
    10  	middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    11  	recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
    12  	grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
    13  	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
    14  	healthpb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
    15  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    16  	pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
    17  	"github.com/prysmaticlabs/prysm/shared/event"
    18  	"github.com/prysmaticlabs/prysm/shared/logutil"
    19  	"github.com/prysmaticlabs/prysm/shared/rand"
    20  	"github.com/prysmaticlabs/prysm/shared/traceutil"
    21  	"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
    22  	"github.com/prysmaticlabs/prysm/validator/client"
    23  	"github.com/prysmaticlabs/prysm/validator/db"
    24  	"github.com/prysmaticlabs/prysm/validator/keymanager"
    25  	"github.com/sirupsen/logrus"
    26  	"go.opencensus.io/plugin/ocgrpc"
    27  	"google.golang.org/grpc"
    28  	"google.golang.org/grpc/credentials"
    29  	"google.golang.org/grpc/reflection"
    30  )
    31  
    32  // Config options for the gRPC server.
    33  type Config struct {
    34  	ValidatorGatewayHost     string
    35  	ValidatorGatewayPort     int
    36  	ValidatorMonitoringHost  string
    37  	ValidatorMonitoringPort  int
    38  	BeaconClientEndpoint     string
    39  	ClientMaxCallRecvMsgSize int
    40  	ClientGrpcRetries        uint
    41  	ClientGrpcRetryDelay     time.Duration
    42  	ClientGrpcHeaders        []string
    43  	ClientWithCert           string
    44  	Host                     string
    45  	Port                     string
    46  	CertFlag                 string
    47  	KeyFlag                  string
    48  	ValDB                    db.Database
    49  	WalletDir                string
    50  	ValidatorService         *client.ValidatorService
    51  	SyncChecker              client.SyncChecker
    52  	GenesisFetcher           client.GenesisFetcher
    53  	WalletInitializedFeed    *event.Feed
    54  	NodeGatewayEndpoint      string
    55  	Wallet                   *wallet.Wallet
    56  	Keymanager               keymanager.IKeymanager
    57  }
    58  
    59  // Server defining a gRPC server for the remote signer API.
    60  type Server struct {
    61  	logsStreamer              logutil.Streamer
    62  	streamLogsBufferSize      int
    63  	beaconChainClient         ethpb.BeaconChainClient
    64  	beaconNodeClient          ethpb.NodeClient
    65  	beaconNodeValidatorClient ethpb.BeaconNodeValidatorClient
    66  	beaconNodeHealthClient    healthpb.HealthClient
    67  	valDB                     db.Database
    68  	ctx                       context.Context
    69  	cancel                    context.CancelFunc
    70  	beaconClientEndpoint      string
    71  	clientMaxCallRecvMsgSize  int
    72  	clientGrpcRetries         uint
    73  	clientGrpcRetryDelay      time.Duration
    74  	clientGrpcHeaders         []string
    75  	clientWithCert            string
    76  	host                      string
    77  	port                      string
    78  	listener                  net.Listener
    79  	keymanager                keymanager.IKeymanager
    80  	withCert                  string
    81  	withKey                   string
    82  	credentialError           error
    83  	grpcServer                *grpc.Server
    84  	jwtKey                    []byte
    85  	validatorService          *client.ValidatorService
    86  	syncChecker               client.SyncChecker
    87  	genesisFetcher            client.GenesisFetcher
    88  	walletDir                 string
    89  	wallet                    *wallet.Wallet
    90  	walletInitializedFeed     *event.Feed
    91  	walletInitialized         bool
    92  	nodeGatewayEndpoint       string
    93  	validatorMonitoringHost   string
    94  	validatorMonitoringPort   int
    95  	validatorGatewayHost      string
    96  	validatorGatewayPort      int
    97  }
    98  
    99  // NewServer instantiates a new gRPC server.
   100  func NewServer(ctx context.Context, cfg *Config) *Server {
   101  	ctx, cancel := context.WithCancel(ctx)
   102  	return &Server{
   103  		ctx:                      ctx,
   104  		cancel:                   cancel,
   105  		logsStreamer:             logutil.NewStreamServer(),
   106  		streamLogsBufferSize:     1000, // Enough to handle most bursts of logs in the validator client.
   107  		host:                     cfg.Host,
   108  		port:                     cfg.Port,
   109  		withCert:                 cfg.CertFlag,
   110  		withKey:                  cfg.KeyFlag,
   111  		beaconClientEndpoint:     cfg.BeaconClientEndpoint,
   112  		clientMaxCallRecvMsgSize: cfg.ClientMaxCallRecvMsgSize,
   113  		clientGrpcRetries:        cfg.ClientGrpcRetries,
   114  		clientGrpcRetryDelay:     cfg.ClientGrpcRetryDelay,
   115  		clientGrpcHeaders:        cfg.ClientGrpcHeaders,
   116  		clientWithCert:           cfg.ClientWithCert,
   117  		valDB:                    cfg.ValDB,
   118  		validatorService:         cfg.ValidatorService,
   119  		syncChecker:              cfg.SyncChecker,
   120  		genesisFetcher:           cfg.GenesisFetcher,
   121  		walletDir:                cfg.WalletDir,
   122  		walletInitializedFeed:    cfg.WalletInitializedFeed,
   123  		walletInitialized:        cfg.Wallet != nil,
   124  		wallet:                   cfg.Wallet,
   125  		keymanager:               cfg.Keymanager,
   126  		nodeGatewayEndpoint:      cfg.NodeGatewayEndpoint,
   127  		validatorMonitoringHost:  cfg.ValidatorMonitoringHost,
   128  		validatorMonitoringPort:  cfg.ValidatorMonitoringPort,
   129  		validatorGatewayHost:     cfg.ValidatorGatewayHost,
   130  		validatorGatewayPort:     cfg.ValidatorGatewayPort,
   131  	}
   132  }
   133  
   134  // Start the gRPC server.
   135  func (s *Server) Start() {
   136  	// Setup the gRPC server options and TLS configuration.
   137  	address := fmt.Sprintf("%s:%s", s.host, s.port)
   138  	lis, err := net.Listen("tcp", address)
   139  	if err != nil {
   140  		log.Errorf("Could not listen to port in Start() %s: %v", address, err)
   141  	}
   142  	s.listener = lis
   143  
   144  	// Register interceptors for metrics gathering as well as our
   145  	// own, custom JWT unary interceptor.
   146  	opts := []grpc.ServerOption{
   147  		grpc.StatsHandler(&ocgrpc.ServerHandler{}),
   148  		grpc.UnaryInterceptor(middleware.ChainUnaryServer(
   149  			recovery.UnaryServerInterceptor(
   150  				recovery.WithRecoveryHandlerContext(traceutil.RecoveryHandlerFunc),
   151  			),
   152  			grpc_prometheus.UnaryServerInterceptor,
   153  			grpc_opentracing.UnaryServerInterceptor(),
   154  			s.JWTInterceptor(),
   155  		)),
   156  	}
   157  	grpc_prometheus.EnableHandlingTimeHistogram()
   158  
   159  	if s.withCert != "" && s.withKey != "" {
   160  		creds, err := credentials.NewServerTLSFromFile(s.withCert, s.withKey)
   161  		if err != nil {
   162  			log.WithError(err).Fatal("Could not load TLS keys")
   163  		}
   164  		opts = append(opts, grpc.Creds(creds))
   165  		log.WithFields(logrus.Fields{
   166  			"crt-path": s.withCert,
   167  			"key-path": s.withKey,
   168  		}).Info("Loaded TLS certificates")
   169  	}
   170  	s.grpcServer = grpc.NewServer(opts...)
   171  
   172  	// Register a gRPC client to the beacon node.
   173  	if err := s.registerBeaconClient(); err != nil {
   174  		log.WithError(err).Fatal("Could not register beacon chain gRPC client")
   175  	}
   176  
   177  	// We create a new, random JWT key upon validator startup.
   178  	jwtKey, err := createRandomJWTKey()
   179  	if err != nil {
   180  		log.WithError(err).Fatal("Could not initialize validator jwt key")
   181  	}
   182  	s.jwtKey = jwtKey
   183  
   184  	// Register services available for the gRPC server.
   185  	reflection.Register(s.grpcServer)
   186  	pb.RegisterAuthServer(s.grpcServer, s)
   187  	pb.RegisterWalletServer(s.grpcServer, s)
   188  	pb.RegisterHealthServer(s.grpcServer, s)
   189  	pb.RegisterBeaconServer(s.grpcServer, s)
   190  	pb.RegisterAccountsServer(s.grpcServer, s)
   191  	pb.RegisterSlashingProtectionServer(s.grpcServer, s)
   192  
   193  	go func() {
   194  		if s.listener != nil {
   195  			if err := s.grpcServer.Serve(s.listener); err != nil {
   196  				log.Errorf("Could not serve: %v", err)
   197  			}
   198  		}
   199  	}()
   200  	go s.checkUserSignup(s.ctx)
   201  	log.WithField("address", address).Info("gRPC server listening on address")
   202  }
   203  
   204  // Stop the gRPC server.
   205  func (s *Server) Stop() error {
   206  	s.cancel()
   207  	if s.listener != nil {
   208  		s.grpcServer.GracefulStop()
   209  		log.Debug("Initiated graceful stop of server")
   210  	}
   211  	return nil
   212  }
   213  
   214  // Status returns nil or credentialError.
   215  func (s *Server) Status() error {
   216  	return s.credentialError
   217  }
   218  
   219  func createRandomJWTKey() ([]byte, error) {
   220  	r := rand.NewGenerator()
   221  	jwtKey := make([]byte, 32)
   222  	n, err := r.Read(jwtKey)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	if n != len(jwtKey) {
   227  		return nil, errors.New("could not create appropriately sized random JWT key")
   228  	}
   229  	return jwtKey, nil
   230  }