prysm-pulse/validator/node/node.go
metanull-operator 1222ebb6db Graffiti flag (#4213)
* Implementation of graffiti flag without tests.
* Updated to pass graffiti as string instead of []byte all the way to the ProposeBlock RPC call. This ensures that the ToBytes32() call is handled in ProposeBlock as opposed to relying on the caller to ensure that the value passed is only 32 bytes. This adds work by doing that conversion on each proposed block for a static value of graffiti, but it also helps protect against an RPC call to ProposeBlock that has more than 32 bytes for graffiti.
* Added test case for validator.
* Added GraffitiFlag to validate usage test.
* Updated data structures and logic to convert graffiti flag from string to byte array earlier in the process. Now converting when setting up ValidatorService.
* Updated test case to correctly set up validator using byte array.
* Merge branch 'master' into graffitiFlag
2019-12-07 19:13:56 +00:00

167 lines
4.6 KiB
Go

// Package node defines a validator client which connects to a
// full beacon node as part of the Ethereum Serenity specification.
package node
import (
"context"
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/shared"
"github.com/prysmaticlabs/prysm/shared/cmd"
"github.com/prysmaticlabs/prysm/shared/debug"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/keystore"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/prometheus"
"github.com/prysmaticlabs/prysm/shared/tracing"
"github.com/prysmaticlabs/prysm/shared/version"
"github.com/prysmaticlabs/prysm/validator/client"
"github.com/prysmaticlabs/prysm/validator/flags"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var log = logrus.WithField("prefix", "node")
// ValidatorClient defines an instance of a sharding validator that manages
// the entire lifecycle of services attached to it participating in
// Ethereum Serenity.
type ValidatorClient struct {
ctx *cli.Context
services *shared.ServiceRegistry // Lifecycle and service store.
lock sync.RWMutex
stop chan struct{} // Channel to wait for termination notifications.
}
// NewValidatorClient creates a new, Ethereum Serenity validator client.
func NewValidatorClient(ctx *cli.Context) (*ValidatorClient, error) {
if err := tracing.Setup(
"validator", // service name
ctx.GlobalString(cmd.TracingProcessNameFlag.Name),
ctx.GlobalString(cmd.TracingEndpointFlag.Name),
ctx.GlobalFloat64(cmd.TraceSampleFractionFlag.Name),
ctx.GlobalBool(cmd.EnableTracingFlag.Name),
); err != nil {
return nil, err
}
verbosity := ctx.GlobalString(cmd.VerbosityFlag.Name)
level, err := logrus.ParseLevel(verbosity)
if err != nil {
return nil, err
}
logrus.SetLevel(level)
registry := shared.NewServiceRegistry()
ValidatorClient := &ValidatorClient{
ctx: ctx,
services: registry,
stop: make(chan struct{}),
}
featureconfig.ConfigureValidator(ctx)
// Use custom config values if the --no-custom-config flag is set.
if !ctx.GlobalBool(flags.NoCustomConfigFlag.Name) {
log.Info("Using custom parameter configuration")
if featureconfig.Get().MinimalConfig {
log.Warn("Using Minimal Config")
params.UseMinimalConfig()
} else {
log.Warn("Using Demo Config")
params.UseDemoBeaconConfig()
}
}
keys, err := keysParser(ctx)
if err != nil {
return nil, err
}
if err := ValidatorClient.registerPrometheusService(ctx); err != nil {
return nil, err
}
if err := ValidatorClient.registerClientService(ctx, keys); err != nil {
return nil, err
}
return ValidatorClient, nil
}
// Start every service in the validator client.
func (s *ValidatorClient) Start() {
s.lock.Lock()
log.WithFields(logrus.Fields{
"version": version.GetVersion(),
}).Info("Starting validator node")
s.services.StartAll()
stop := s.stop
s.lock.Unlock()
go func() {
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
defer signal.Stop(sigc)
<-sigc
log.Info("Got interrupt, shutting down...")
debug.Exit(s.ctx) // Ensure trace and CPU profile data are flushed.
go s.Close()
for i := 10; i > 0; i-- {
<-sigc
if i > 1 {
log.Info("Already shutting down, interrupt more to panic.", "times", i-1)
}
}
panic("Panic closing the sharding validator")
}()
// Wait for stop channel to be closed.
<-stop
}
// Close handles graceful shutdown of the system.
func (s *ValidatorClient) Close() {
s.lock.Lock()
defer s.lock.Unlock()
s.services.StopAll()
log.Info("Stopping sharding validator")
close(s.stop)
}
func (s *ValidatorClient) registerPrometheusService(ctx *cli.Context) error {
service := prometheus.NewPrometheusService(
fmt.Sprintf(":%d", ctx.GlobalInt64(cmd.MonitoringPortFlag.Name)),
s.services,
)
logrus.AddHook(prometheus.NewLogrusCollector())
return s.services.RegisterService(service)
}
func (s *ValidatorClient) registerClientService(ctx *cli.Context, keys map[string]*keystore.Key) error {
endpoint := ctx.GlobalString(flags.BeaconRPCProviderFlag.Name)
logValidatorBalances := !ctx.GlobalBool(flags.DisablePenaltyRewardLogFlag.Name)
cert := ctx.GlobalString(flags.CertFlag.Name)
graffiti := ctx.GlobalString(flags.GraffitiFlag.Name)
v, err := client.NewValidatorService(context.Background(), &client.Config{
Endpoint: endpoint,
Keys: keys,
LogValidatorBalances: logValidatorBalances,
CertFlag: cert,
GraffitiFlag: graffiti,
})
if err != nil {
return errors.Wrap(err, "could not initialize client service")
}
return s.services.RegisterService(v)
}