mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-28 14:17:17 +00:00
cc741ed8af
* begin state service * begin on the state trie idea * created beacon state structure * add in the full clone getter * return by value instead * add all setters * new state setters are being completed * arrays roots exposed * close to finishing all these headerssss * functionality complete * added in proto benchmark test * test for compatibility * add test for compat * comments fixed * add clone * add clone * remove underlying copies * make it immutable * integrate it into chainservice * revert * wrap up comments for package * address all comments and godocs * address all comments * clone the pending attestation properly * properly clone remaining items * tests pass fixed bug * begin using it instead of head state * prevent nil pointer exceptions * begin using new struct in db * integrated new type into db package * add proper nil checks * using new state in archiver * refactored much of core * editing all the precompute functions * done with most core refactor * fixed up some bugs in the clone comparisons * append current epoch atts * add missing setters * add new setters * fix other core methods * fix up transition * main service and forkchoice * fix rpc * integrated to powchain * some more changes * fix build * improve processing of deposits * fix error * prevent panic * comment * fix process att * gaz * fix up att process * resolve existing review comments * resolve another batch of gh comments * resolve broken cpt state * revise testutil to use the new state * begin updating the state transition func to pass in more compartmentalized args * finish editing transition function to return errors * block operations pretty much done with refactor * state transition fully refactored * got epoch processing completed * fix build in fork choice * fixing more of the build * fix up broken sync package * it builds nowww it buildssss * revert registry changes * Recompute on Read (#4627) * compute on read * fix up eth1 data votes * looking into slashings bug introduced in core/ * able to advance more slots * add logging * can now sync with testnet yay * remove the leaves algorithm and other merkle imports * expose initialize unsafe funcs * Update beacon-chain/db/kv/state.go * lint Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * More Optimizations for New State (#4641) * map optimization * more optimizations * use a custom hasher * comment * block operations optimizations * Update beacon-chain/state/types.go Co-Authored-By: Raul Jordan <raul@prysmaticlabs.com> * fixed up various operations to use the validator index map access Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * archiver tests pass * fixing cache tests * cache tests passing * edited validator tests * powchain tests passing * halfway thru sync tests * more sync test fixes * add in tests for state/ * working through rpc tests * assignments tests passed * almost done with rpc/beacon tests * resolved painful validator test * fixed up even more tests * resolve tests * fix build * reduce a randao mixes copy * fixes under //beacon-chain/blockchain/... * build //beacon-chain/core/... * fixes * Runtime Optimizations (#4648) * parallelize shuffling * clean up * lint * fix build * use callback to read from registry * fix array roots and size map * new improvements * reduce hash allocs * improved shuffling * terence's review * use different method * raul's comment * new array roots * remove clone in pre-compute * Update beacon-chain/state/types.go Co-Authored-By: Raul Jordan <raul@prysmaticlabs.com> * raul's review * lint * fix build issues * fix visibility Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * fix visibility * build works for all * fix blockchain test * fix a few tests * fix more tests * update validator in slashing * archiver passing * fixed rpc/validator * progress on core tests * resolve broken rpc tests * blockchain tests passed * fix up some tests in core * fix message diff * remove unnecessary save * Save validator after slashing * Update validators one by one * another update * fix everything * fix more precompute tests * fix blocks tests * more elegant fix * more helper fixes * change back ? * fix test * fix skip slot * fix test * reset caches * fix testutil * raceoff fixed * passing * Retrieve cached state in the beginning * lint * Fixed tests part 1 * Fixed rest of the tests * Minor changes to avoid copying, small refactor to reduce deplicated code * Handle att req for slot 0 * New beacon state: Only populate merkle layers as needed, copy merkle layers on copy/clone. (#4689) * Only populate merkle layers as needed, copy merkle layers on copy/clone. * use custom copy * Make maps of correct size * slightly fast, doesn't wait for lock Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Target root can't be 0x00 * Don't use cache for current slot (may not be the right fix) * fixed up tests * Remove some copy for init sync. Not sure if it is safe enough for runtime though... testing... * Align with prev logic for process slots cachedState.Slot() < slot * Fix Initial Sync Flag (#4692) * fixes * fix up some test failures due to lack of nil checks * fix up some test failures due to lack of nil checks * fix up imports * revert some changes * imports Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * resolving further conflicts * Better skip slot cache (#4694) * Return copy of skip slot cache state, disable skip slot cache on sync * fix * Fix pruning * fix up issues with broken tests Co-authored-by: Nishant Das <nish1993@hotmail.com> Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> Co-authored-by: shayzluf <thezluf@gmail.com> Co-authored-by: terence tsao <terence@prysmaticlabs.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
332 lines
12 KiB
Go
332 lines
12 KiB
Go
// Package rpc defines the services that the beacon-chain uses to communicate via gRPC.
|
||
package rpc
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"math/rand"
|
||
"net"
|
||
"os"
|
||
|
||
middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||
recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
|
||
grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
|
||
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
|
||
opfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/operation"
|
||
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/aggregator"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/beacon"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/node"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/validator"
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/sync"
|
||
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
|
||
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
|
||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||
"github.com/prysmaticlabs/prysm/shared/params"
|
||
"github.com/prysmaticlabs/prysm/shared/slotutil"
|
||
"github.com/prysmaticlabs/prysm/shared/traceutil"
|
||
"github.com/sirupsen/logrus"
|
||
"go.opencensus.io/plugin/ocgrpc"
|
||
"google.golang.org/grpc"
|
||
"google.golang.org/grpc/credentials"
|
||
"google.golang.org/grpc/reflection"
|
||
)
|
||
|
||
var log logrus.FieldLogger
|
||
|
||
func init() {
|
||
log = logrus.WithField("prefix", "rpc")
|
||
rand.Seed(int64(os.Getpid()))
|
||
}
|
||
|
||
// Service defining an RPC server for a beacon node.
|
||
type Service struct {
|
||
ctx context.Context
|
||
cancel context.CancelFunc
|
||
beaconDB db.HeadAccessDatabase
|
||
headFetcher blockchain.HeadFetcher
|
||
forkFetcher blockchain.ForkFetcher
|
||
finalizationFetcher blockchain.FinalizationFetcher
|
||
participationFetcher blockchain.ParticipationFetcher
|
||
genesisTimeFetcher blockchain.GenesisTimeFetcher
|
||
attestationReceiver blockchain.AttestationReceiver
|
||
blockReceiver blockchain.BlockReceiver
|
||
powChainService powchain.Chain
|
||
chainStartFetcher powchain.ChainStartFetcher
|
||
mockEth1Votes bool
|
||
attestationsPool attestations.Pool
|
||
exitPool *voluntaryexits.Pool
|
||
syncService sync.Checker
|
||
host string
|
||
port string
|
||
listener net.Listener
|
||
withCert string
|
||
withKey string
|
||
grpcServer *grpc.Server
|
||
canonicalStateChan chan *pbp2p.BeaconState
|
||
incomingAttestation chan *ethpb.Attestation
|
||
credentialError error
|
||
p2p p2p.Broadcaster
|
||
peersFetcher p2p.PeersProvider
|
||
depositFetcher depositcache.DepositFetcher
|
||
pendingDepositFetcher depositcache.PendingDepositsFetcher
|
||
stateNotifier statefeed.Notifier
|
||
operationNotifier opfeed.Notifier
|
||
slasherConn *grpc.ClientConn
|
||
slasherProvider string
|
||
slasherCert string
|
||
slasherCredentialError error
|
||
slasherClient slashpb.SlasherClient
|
||
}
|
||
|
||
// Config options for the beacon node RPC server.
|
||
type Config struct {
|
||
Host string
|
||
Port string
|
||
CertFlag string
|
||
KeyFlag string
|
||
BeaconDB db.HeadAccessDatabase
|
||
HeadFetcher blockchain.HeadFetcher
|
||
ForkFetcher blockchain.ForkFetcher
|
||
FinalizationFetcher blockchain.FinalizationFetcher
|
||
ParticipationFetcher blockchain.ParticipationFetcher
|
||
AttestationReceiver blockchain.AttestationReceiver
|
||
BlockReceiver blockchain.BlockReceiver
|
||
POWChainService powchain.Chain
|
||
ChainStartFetcher powchain.ChainStartFetcher
|
||
GenesisTimeFetcher blockchain.GenesisTimeFetcher
|
||
MockEth1Votes bool
|
||
AttestationsPool attestations.Pool
|
||
ExitPool *voluntaryexits.Pool
|
||
SyncService sync.Checker
|
||
Broadcaster p2p.Broadcaster
|
||
PeersFetcher p2p.PeersProvider
|
||
DepositFetcher depositcache.DepositFetcher
|
||
PendingDepositFetcher depositcache.PendingDepositsFetcher
|
||
SlasherProvider string
|
||
SlasherCert string
|
||
StateNotifier statefeed.Notifier
|
||
OperationNotifier opfeed.Notifier
|
||
}
|
||
|
||
// NewService instantiates a new RPC service instance that will
|
||
// be registered into a running beacon node.
|
||
func NewService(ctx context.Context, cfg *Config) *Service {
|
||
ctx, cancel := context.WithCancel(ctx)
|
||
return &Service{
|
||
ctx: ctx,
|
||
cancel: cancel,
|
||
beaconDB: cfg.BeaconDB,
|
||
headFetcher: cfg.HeadFetcher,
|
||
forkFetcher: cfg.ForkFetcher,
|
||
finalizationFetcher: cfg.FinalizationFetcher,
|
||
participationFetcher: cfg.ParticipationFetcher,
|
||
genesisTimeFetcher: cfg.GenesisTimeFetcher,
|
||
attestationReceiver: cfg.AttestationReceiver,
|
||
blockReceiver: cfg.BlockReceiver,
|
||
p2p: cfg.Broadcaster,
|
||
peersFetcher: cfg.PeersFetcher,
|
||
powChainService: cfg.POWChainService,
|
||
chainStartFetcher: cfg.ChainStartFetcher,
|
||
mockEth1Votes: cfg.MockEth1Votes,
|
||
attestationsPool: cfg.AttestationsPool,
|
||
exitPool: cfg.ExitPool,
|
||
syncService: cfg.SyncService,
|
||
host: cfg.Host,
|
||
port: cfg.Port,
|
||
withCert: cfg.CertFlag,
|
||
withKey: cfg.KeyFlag,
|
||
depositFetcher: cfg.DepositFetcher,
|
||
pendingDepositFetcher: cfg.PendingDepositFetcher,
|
||
canonicalStateChan: make(chan *pbp2p.BeaconState, params.BeaconConfig().DefaultBufferSize),
|
||
incomingAttestation: make(chan *ethpb.Attestation, params.BeaconConfig().DefaultBufferSize),
|
||
stateNotifier: cfg.StateNotifier,
|
||
operationNotifier: cfg.OperationNotifier,
|
||
slasherProvider: cfg.SlasherProvider,
|
||
slasherCert: cfg.SlasherCert,
|
||
}
|
||
}
|
||
|
||
// Start the gRPC server.
|
||
func (s *Service) Start() {
|
||
address := fmt.Sprintf("%s:%s", s.host, s.port)
|
||
lis, err := net.Listen("tcp", address)
|
||
if err != nil {
|
||
log.Errorf("Could not listen to port in Start() %s: %v", address, err)
|
||
}
|
||
s.listener = lis
|
||
log.WithField("address", address).Info("RPC-API listening on port")
|
||
|
||
opts := []grpc.ServerOption{
|
||
grpc.StatsHandler(&ocgrpc.ServerHandler{}),
|
||
grpc.StreamInterceptor(middleware.ChainStreamServer(
|
||
recovery.StreamServerInterceptor(
|
||
recovery.WithRecoveryHandlerContext(traceutil.RecoveryHandlerFunc),
|
||
),
|
||
grpc_prometheus.StreamServerInterceptor,
|
||
grpc_opentracing.StreamServerInterceptor(),
|
||
)),
|
||
grpc.UnaryInterceptor(middleware.ChainUnaryServer(
|
||
recovery.UnaryServerInterceptor(
|
||
recovery.WithRecoveryHandlerContext(traceutil.RecoveryHandlerFunc),
|
||
),
|
||
grpc_prometheus.UnaryServerInterceptor,
|
||
grpc_opentracing.UnaryServerInterceptor(),
|
||
)),
|
||
}
|
||
grpc_prometheus.EnableHandlingTimeHistogram()
|
||
// TODO(#791): Utilize a certificate for secure connections
|
||
// between beacon nodes and validator clients.
|
||
if s.withCert != "" && s.withKey != "" {
|
||
creds, err := credentials.NewServerTLSFromFile(s.withCert, s.withKey)
|
||
if err != nil {
|
||
log.Errorf("Could not load TLS keys: %s", err)
|
||
s.credentialError = err
|
||
}
|
||
opts = append(opts, grpc.Creds(creds))
|
||
} else {
|
||
log.Warn("You are using an insecure gRPC connection! Provide a certificate and key to connect securely")
|
||
}
|
||
s.grpcServer = grpc.NewServer(opts...)
|
||
|
||
genesisTime := s.genesisTimeFetcher.GenesisTime()
|
||
ticker := slotutil.GetSlotTicker(genesisTime, params.BeaconConfig().SecondsPerSlot)
|
||
validatorServer := &validator.Server{
|
||
Ctx: s.ctx,
|
||
BeaconDB: s.beaconDB,
|
||
AttestationCache: cache.NewAttestationCache(),
|
||
AttPool: s.attestationsPool,
|
||
ExitPool: s.exitPool,
|
||
HeadFetcher: s.headFetcher,
|
||
ForkFetcher: s.forkFetcher,
|
||
FinalizationFetcher: s.finalizationFetcher,
|
||
CanonicalStateChan: s.canonicalStateChan,
|
||
BlockFetcher: s.powChainService,
|
||
DepositFetcher: s.depositFetcher,
|
||
ChainStartFetcher: s.chainStartFetcher,
|
||
Eth1InfoFetcher: s.powChainService,
|
||
SyncChecker: s.syncService,
|
||
StateNotifier: s.stateNotifier,
|
||
OperationNotifier: s.operationNotifier,
|
||
P2P: s.p2p,
|
||
BlockReceiver: s.blockReceiver,
|
||
MockEth1Votes: s.mockEth1Votes,
|
||
Eth1BlockFetcher: s.powChainService,
|
||
PendingDepositsFetcher: s.pendingDepositFetcher,
|
||
GenesisTime: genesisTime,
|
||
}
|
||
nodeServer := &node.Server{
|
||
BeaconDB: s.beaconDB,
|
||
Server: s.grpcServer,
|
||
SyncChecker: s.syncService,
|
||
GenesisTimeFetcher: s.genesisTimeFetcher,
|
||
PeersFetcher: s.peersFetcher,
|
||
}
|
||
beaconChainServer := &beacon.Server{
|
||
Ctx: s.ctx,
|
||
BeaconDB: s.beaconDB,
|
||
Pool: s.attestationsPool,
|
||
HeadFetcher: s.headFetcher,
|
||
FinalizationFetcher: s.finalizationFetcher,
|
||
ParticipationFetcher: s.participationFetcher,
|
||
ChainStartFetcher: s.chainStartFetcher,
|
||
CanonicalStateChan: s.canonicalStateChan,
|
||
StateNotifier: s.stateNotifier,
|
||
SlotTicker: ticker,
|
||
}
|
||
aggregatorServer := &aggregator.Server{
|
||
BeaconDB: s.beaconDB,
|
||
HeadFetcher: s.headFetcher,
|
||
SyncChecker: s.syncService,
|
||
AttPool: s.attestationsPool,
|
||
P2p: s.p2p,
|
||
}
|
||
pb.RegisterAggregatorServiceServer(s.grpcServer, aggregatorServer)
|
||
ethpb.RegisterNodeServer(s.grpcServer, nodeServer)
|
||
ethpb.RegisterBeaconChainServer(s.grpcServer, beaconChainServer)
|
||
ethpb.RegisterBeaconNodeValidatorServer(s.grpcServer, validatorServer)
|
||
|
||
// Register reflection service on gRPC server.
|
||
reflection.Register(s.grpcServer)
|
||
|
||
go func() {
|
||
if s.listener != nil {
|
||
if err := s.grpcServer.Serve(s.listener); err != nil {
|
||
log.Errorf("Could not serve gRPC: %v", err)
|
||
}
|
||
}
|
||
}()
|
||
if featureconfig.Get().EnableSlasherConnection {
|
||
s.startSlasherClient()
|
||
}
|
||
}
|
||
|
||
func (s *Service) startSlasherClient() {
|
||
var dialOpt grpc.DialOption
|
||
if s.slasherCert != "" {
|
||
creds, err := credentials.NewClientTLSFromFile(s.slasherCert, "")
|
||
if err != nil {
|
||
log.Errorf("Could not get valid credentials: %v", err)
|
||
s.slasherCredentialError = err
|
||
}
|
||
dialOpt = grpc.WithTransportCredentials(creds)
|
||
} else {
|
||
dialOpt = grpc.WithInsecure()
|
||
log.Warn("You are using an insecure gRPC connection! Please provide a certificate and key to use a secure connection.")
|
||
}
|
||
slasherOpts := []grpc.DialOption{
|
||
dialOpt,
|
||
grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
|
||
grpc.WithStreamInterceptor(middleware.ChainStreamClient(
|
||
grpc_opentracing.StreamClientInterceptor(),
|
||
grpc_prometheus.StreamClientInterceptor,
|
||
)),
|
||
grpc.WithUnaryInterceptor(middleware.ChainUnaryClient(
|
||
grpc_opentracing.UnaryClientInterceptor(),
|
||
grpc_prometheus.UnaryClientInterceptor,
|
||
)),
|
||
}
|
||
conn, err := grpc.DialContext(s.ctx, s.slasherProvider, slasherOpts...)
|
||
if err != nil {
|
||
log.Errorf("Could not dial endpoint: %s, %v", s.slasherProvider, err)
|
||
return
|
||
}
|
||
log.Info("Successfully started hash slinging slasher©️ gRPC connection")
|
||
s.slasherConn = conn
|
||
s.slasherClient = slashpb.NewSlasherClient(s.slasherConn)
|
||
}
|
||
|
||
// Stop the service.
|
||
func (s *Service) Stop() error {
|
||
s.cancel()
|
||
if s.listener != nil {
|
||
s.grpcServer.GracefulStop()
|
||
log.Debug("Initiated graceful stop of gRPC server")
|
||
}
|
||
if s.slasherConn != nil {
|
||
s.slasherConn.Close()
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Status returns nil or credentialError
|
||
func (s *Service) Status() error {
|
||
if s.credentialError != nil {
|
||
return s.credentialError
|
||
}
|
||
if s.slasherCredentialError != nil {
|
||
return s.slasherCredentialError
|
||
}
|
||
return nil
|
||
}
|