github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/service.go (about) 1 // Package rpc defines a gRPC server implementing the Ethereum consensus API as needed 2 // by validator clients and consumers of chain data. 3 package rpc 4 5 import ( 6 "context" 7 "errors" 8 "fmt" 9 "net" 10 "sync" 11 12 middleware "github.com/grpc-ecosystem/go-grpc-middleware" 13 recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" 14 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" 15 grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" 16 "github.com/prysmaticlabs/prysm/beacon-chain/blockchain" 17 "github.com/prysmaticlabs/prysm/beacon-chain/cache" 18 "github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache" 19 blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block" 20 opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation" 21 statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state" 22 "github.com/prysmaticlabs/prysm/beacon-chain/db" 23 "github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations" 24 "github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings" 25 "github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits" 26 "github.com/prysmaticlabs/prysm/beacon-chain/p2p" 27 "github.com/prysmaticlabs/prysm/beacon-chain/powchain" 28 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/v1/beacon" 29 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/v1/debug" 30 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/v1/events" 31 node "github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/v1/node" 32 beaconv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/beacon" 33 debugv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/debug" 34 nodev1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/node" 35 validatorv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator" 36 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher" 37 "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen" 38 chainSync "github.com/prysmaticlabs/prysm/beacon-chain/sync" 39 pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 40 pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" 41 ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1" 42 ethpbv1alpha1 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 43 "github.com/prysmaticlabs/prysm/shared/featureconfig" 44 "github.com/prysmaticlabs/prysm/shared/logutil" 45 "github.com/prysmaticlabs/prysm/shared/params" 46 "github.com/prysmaticlabs/prysm/shared/traceutil" 47 "github.com/sirupsen/logrus" 48 "go.opencensus.io/plugin/ocgrpc" 49 "google.golang.org/grpc" 50 "google.golang.org/grpc/credentials" 51 "google.golang.org/grpc/peer" 52 "google.golang.org/grpc/reflection" 53 ) 54 55 const attestationBufferSize = 100 56 57 // Service defining an RPC server for a beacon node. 58 type Service struct { 59 cfg *Config 60 ctx context.Context 61 cancel context.CancelFunc 62 listener net.Listener 63 grpcServer *grpc.Server 64 canonicalStateChan chan *pbp2p.BeaconState 65 incomingAttestation chan *ethpbv1alpha1.Attestation 66 credentialError error 67 connectedRPCClients map[net.Addr]bool 68 clientConnectionLock sync.Mutex 69 } 70 71 // Config options for the beacon node RPC server. 72 type Config struct { 73 Host string 74 Port string 75 CertFlag string 76 KeyFlag string 77 BeaconMonitoringHost string 78 BeaconMonitoringPort int 79 BeaconDB db.HeadAccessDatabase 80 ChainInfoFetcher blockchain.ChainInfoFetcher 81 HeadFetcher blockchain.HeadFetcher 82 CanonicalFetcher blockchain.CanonicalFetcher 83 ForkFetcher blockchain.ForkFetcher 84 FinalizationFetcher blockchain.FinalizationFetcher 85 AttestationReceiver blockchain.AttestationReceiver 86 BlockReceiver blockchain.BlockReceiver 87 POWChainService powchain.Chain 88 ChainStartFetcher powchain.ChainStartFetcher 89 GenesisTimeFetcher blockchain.TimeFetcher 90 GenesisFetcher blockchain.GenesisFetcher 91 EnableDebugRPCEndpoints bool 92 MockEth1Votes bool 93 AttestationsPool attestations.Pool 94 ExitPool voluntaryexits.PoolManager 95 SlashingsPool slashings.PoolManager 96 SyncService chainSync.Checker 97 Broadcaster p2p.Broadcaster 98 PeersFetcher p2p.PeersProvider 99 PeerManager p2p.PeerManager 100 MetadataProvider p2p.MetadataProvider 101 DepositFetcher depositcache.DepositFetcher 102 PendingDepositFetcher depositcache.PendingDepositsFetcher 103 StateNotifier statefeed.Notifier 104 BlockNotifier blockfeed.Notifier 105 OperationNotifier opfeed.Notifier 106 StateGen *stategen.State 107 MaxMsgSize int 108 } 109 110 // NewService instantiates a new RPC service instance that will 111 // be registered into a running beacon node. 112 func NewService(ctx context.Context, cfg *Config) *Service { 113 ctx, cancel := context.WithCancel(ctx) 114 return &Service{ 115 cfg: cfg, 116 ctx: ctx, 117 cancel: cancel, 118 canonicalStateChan: make(chan *pbp2p.BeaconState, params.BeaconConfig().DefaultBufferSize), 119 incomingAttestation: make(chan *ethpbv1alpha1.Attestation, params.BeaconConfig().DefaultBufferSize), 120 connectedRPCClients: make(map[net.Addr]bool), 121 } 122 } 123 124 // Start the gRPC server. 125 func (s *Service) Start() { 126 address := fmt.Sprintf("%s:%s", s.cfg.Host, s.cfg.Port) 127 lis, err := net.Listen("tcp", address) 128 if err != nil { 129 log.Errorf("Could not listen to port in Start() %s: %v", address, err) 130 } 131 s.listener = lis 132 log.WithField("address", address).Info("gRPC server listening on port") 133 134 opts := []grpc.ServerOption{ 135 grpc.StatsHandler(&ocgrpc.ServerHandler{}), 136 grpc.StreamInterceptor(middleware.ChainStreamServer( 137 recovery.StreamServerInterceptor( 138 recovery.WithRecoveryHandlerContext(traceutil.RecoveryHandlerFunc), 139 ), 140 grpc_prometheus.StreamServerInterceptor, 141 grpc_opentracing.StreamServerInterceptor(), 142 s.validatorStreamConnectionInterceptor, 143 )), 144 grpc.UnaryInterceptor(middleware.ChainUnaryServer( 145 recovery.UnaryServerInterceptor( 146 recovery.WithRecoveryHandlerContext(traceutil.RecoveryHandlerFunc), 147 ), 148 grpc_prometheus.UnaryServerInterceptor, 149 grpc_opentracing.UnaryServerInterceptor(), 150 s.validatorUnaryConnectionInterceptor, 151 )), 152 grpc.MaxRecvMsgSize(s.cfg.MaxMsgSize), 153 } 154 grpc_prometheus.EnableHandlingTimeHistogram() 155 if s.cfg.CertFlag != "" && s.cfg.KeyFlag != "" { 156 creds, err := credentials.NewServerTLSFromFile(s.cfg.CertFlag, s.cfg.KeyFlag) 157 if err != nil { 158 log.WithError(err).Fatal("Could not load TLS keys") 159 } 160 opts = append(opts, grpc.Creds(creds)) 161 } else { 162 log.Warn("You are using an insecure gRPC server. If you are running your beacon node and " + 163 "validator on the same machines, you can ignore this message. If you want to know " + 164 "how to enable secure connections, see: https://docs.prylabs.network/docs/prysm-usage/secure-grpc") 165 } 166 s.grpcServer = grpc.NewServer(opts...) 167 168 validatorServer := &validatorv1alpha1.Server{ 169 Ctx: s.ctx, 170 BeaconDB: s.cfg.BeaconDB, 171 AttestationCache: cache.NewAttestationCache(), 172 AttPool: s.cfg.AttestationsPool, 173 ExitPool: s.cfg.ExitPool, 174 HeadFetcher: s.cfg.HeadFetcher, 175 ForkFetcher: s.cfg.ForkFetcher, 176 FinalizationFetcher: s.cfg.FinalizationFetcher, 177 TimeFetcher: s.cfg.GenesisTimeFetcher, 178 CanonicalStateChan: s.canonicalStateChan, 179 BlockFetcher: s.cfg.POWChainService, 180 DepositFetcher: s.cfg.DepositFetcher, 181 ChainStartFetcher: s.cfg.ChainStartFetcher, 182 Eth1InfoFetcher: s.cfg.POWChainService, 183 SyncChecker: s.cfg.SyncService, 184 StateNotifier: s.cfg.StateNotifier, 185 BlockNotifier: s.cfg.BlockNotifier, 186 OperationNotifier: s.cfg.OperationNotifier, 187 P2P: s.cfg.Broadcaster, 188 BlockReceiver: s.cfg.BlockReceiver, 189 MockEth1Votes: s.cfg.MockEth1Votes, 190 Eth1BlockFetcher: s.cfg.POWChainService, 191 PendingDepositsFetcher: s.cfg.PendingDepositFetcher, 192 SlashingsPool: s.cfg.SlashingsPool, 193 StateGen: s.cfg.StateGen, 194 } 195 nodeServer := &nodev1alpha1.Server{ 196 LogsStreamer: logutil.NewStreamServer(), 197 StreamLogsBufferSize: 1000, // Enough to handle bursts of beacon node logs for gRPC streaming. 198 BeaconDB: s.cfg.BeaconDB, 199 Server: s.grpcServer, 200 SyncChecker: s.cfg.SyncService, 201 GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, 202 PeersFetcher: s.cfg.PeersFetcher, 203 PeerManager: s.cfg.PeerManager, 204 GenesisFetcher: s.cfg.GenesisFetcher, 205 BeaconMonitoringHost: s.cfg.BeaconMonitoringHost, 206 BeaconMonitoringPort: s.cfg.BeaconMonitoringPort, 207 } 208 nodeServerV1 := &node.Server{ 209 BeaconDB: s.cfg.BeaconDB, 210 Server: s.grpcServer, 211 SyncChecker: s.cfg.SyncService, 212 GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, 213 PeersFetcher: s.cfg.PeersFetcher, 214 PeerManager: s.cfg.PeerManager, 215 MetadataProvider: s.cfg.MetadataProvider, 216 HeadFetcher: s.cfg.HeadFetcher, 217 } 218 219 beaconChainServer := &beaconv1alpha1.Server{ 220 Ctx: s.ctx, 221 BeaconDB: s.cfg.BeaconDB, 222 AttestationsPool: s.cfg.AttestationsPool, 223 SlashingsPool: s.cfg.SlashingsPool, 224 HeadFetcher: s.cfg.HeadFetcher, 225 FinalizationFetcher: s.cfg.FinalizationFetcher, 226 CanonicalFetcher: s.cfg.CanonicalFetcher, 227 ChainStartFetcher: s.cfg.ChainStartFetcher, 228 DepositFetcher: s.cfg.DepositFetcher, 229 BlockFetcher: s.cfg.POWChainService, 230 CanonicalStateChan: s.canonicalStateChan, 231 GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, 232 StateNotifier: s.cfg.StateNotifier, 233 BlockNotifier: s.cfg.BlockNotifier, 234 AttestationNotifier: s.cfg.OperationNotifier, 235 Broadcaster: s.cfg.Broadcaster, 236 StateGen: s.cfg.StateGen, 237 SyncChecker: s.cfg.SyncService, 238 ReceivedAttestationsBuffer: make(chan *ethpbv1alpha1.Attestation, attestationBufferSize), 239 CollectedAttestationsBuffer: make(chan []*ethpbv1alpha1.Attestation, attestationBufferSize), 240 } 241 beaconChainServerV1 := &beacon.Server{ 242 BeaconDB: s.cfg.BeaconDB, 243 AttestationsPool: s.cfg.AttestationsPool, 244 SlashingsPool: s.cfg.SlashingsPool, 245 ChainInfoFetcher: s.cfg.ChainInfoFetcher, 246 GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, 247 BlockNotifier: s.cfg.BlockNotifier, 248 Broadcaster: s.cfg.Broadcaster, 249 BlockReceiver: s.cfg.BlockReceiver, 250 StateGenService: s.cfg.StateGen, 251 StateFetcher: &statefetcher.StateProvider{ 252 BeaconDB: s.cfg.BeaconDB, 253 ChainInfoFetcher: s.cfg.ChainInfoFetcher, 254 GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, 255 StateGenService: s.cfg.StateGen, 256 }, 257 VoluntaryExitsPool: s.cfg.ExitPool, 258 } 259 ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer) 260 ethpbv1.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1) 261 pbrpc.RegisterHealthServer(s.grpcServer, nodeServer) 262 ethpbv1alpha1.RegisterBeaconChainServer(s.grpcServer, beaconChainServer) 263 ethpbv1.RegisterBeaconChainServer(s.grpcServer, beaconChainServerV1) 264 ethpbv1.RegisterEventsServer(s.grpcServer, &events.Server{ 265 Ctx: s.ctx, 266 StateNotifier: s.cfg.StateNotifier, 267 BlockNotifier: s.cfg.BlockNotifier, 268 OperationNotifier: s.cfg.OperationNotifier, 269 }) 270 if s.cfg.EnableDebugRPCEndpoints { 271 log.Info("Enabled debug gRPC endpoints") 272 debugServer := &debugv1alpha1.Server{ 273 GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, 274 BeaconDB: s.cfg.BeaconDB, 275 StateGen: s.cfg.StateGen, 276 HeadFetcher: s.cfg.HeadFetcher, 277 PeerManager: s.cfg.PeerManager, 278 PeersFetcher: s.cfg.PeersFetcher, 279 } 280 debugServerV1 := &debug.Server{ 281 BeaconDB: s.cfg.BeaconDB, 282 HeadFetcher: s.cfg.HeadFetcher, 283 StateFetcher: &statefetcher.StateProvider{ 284 BeaconDB: s.cfg.BeaconDB, 285 ChainInfoFetcher: s.cfg.ChainInfoFetcher, 286 GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, 287 StateGenService: s.cfg.StateGen, 288 }, 289 } 290 pbrpc.RegisterDebugServer(s.grpcServer, debugServer) 291 ethpbv1.RegisterBeaconDebugServer(s.grpcServer, debugServerV1) 292 } 293 ethpbv1alpha1.RegisterBeaconNodeValidatorServer(s.grpcServer, validatorServer) 294 295 // Register reflection service on gRPC server. 296 reflection.Register(s.grpcServer) 297 298 go func() { 299 if s.listener != nil { 300 if err := s.grpcServer.Serve(s.listener); err != nil { 301 log.Errorf("Could not serve gRPC: %v", err) 302 } 303 } 304 }() 305 } 306 307 // Stop the service. 308 func (s *Service) Stop() error { 309 s.cancel() 310 if s.listener != nil { 311 s.grpcServer.GracefulStop() 312 log.Debug("Initiated graceful stop of gRPC server") 313 } 314 return nil 315 } 316 317 // Status returns nil or credentialError 318 func (s *Service) Status() error { 319 if s.cfg.SyncService.Syncing() { 320 return errors.New("syncing") 321 } 322 if s.credentialError != nil { 323 return s.credentialError 324 } 325 return nil 326 } 327 328 // Stream interceptor for new validator client connections to the beacon node. 329 func (s *Service) validatorStreamConnectionInterceptor( 330 srv interface{}, 331 ss grpc.ServerStream, 332 _ *grpc.StreamServerInfo, 333 handler grpc.StreamHandler, 334 ) error { 335 s.logNewClientConnection(ss.Context()) 336 return handler(srv, ss) 337 } 338 339 // Unary interceptor for new validator client connections to the beacon node. 340 func (s *Service) validatorUnaryConnectionInterceptor( 341 ctx context.Context, 342 req interface{}, 343 _ *grpc.UnaryServerInfo, 344 handler grpc.UnaryHandler, 345 ) (interface{}, error) { 346 s.logNewClientConnection(ctx) 347 return handler(ctx, req) 348 } 349 350 func (s *Service) logNewClientConnection(ctx context.Context) { 351 if featureconfig.Get().DisableGRPCConnectionLogs { 352 return 353 } 354 if clientInfo, ok := peer.FromContext(ctx); ok { 355 // Check if we have not yet observed this grpc client connection 356 // in the running beacon node. 357 s.clientConnectionLock.Lock() 358 defer s.clientConnectionLock.Unlock() 359 if !s.connectedRPCClients[clientInfo.Addr] { 360 log.WithFields(logrus.Fields{ 361 "addr": clientInfo.Addr.String(), 362 }).Infof("New gRPC client connected to beacon node") 363 s.connectedRPCClients[clientInfo.Addr] = true 364 } 365 } 366 }