prysm-pulse/validator/node/node.go
Raul Jordan 92932ae58e
[Feature] - Slashing Interchange Support (#8024)
* Change LowestSignedProposal to Also Return a Boolean for Slashing Protection (#8020)

* amend to use bools

* ineff assign

* comment

* Update `LowestSignedTargetEpoch` to include exists (#8004)

* Replace highest with lowerest

* Update validator/db/kv/attestation_history_v2.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Update validator/db/kv/attestation_history_v2.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Invert equality for saveLowestSourceTargetToDB

* Add eip checks to ensure epochs cant be lower than db ones

* Should be less than equal to

* Check if epoch exists in DB getters

* Revert run time checks

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* Export Attesting History for Slashing Interchange Standard (#8027)

* added in att history checks

* logic for export

* export return nil

* test for export atts

* round trip passes first try!

* rem println

* fix up tests

* pass test

* Validate Proposers Are Not Slashable With Regard to Data Within Slasher Interchange JSON (#8031)

* filter slashable blocks and atts in same json stub

* add filter blocks func

* add test for filtering out the bad public keys

* Export Slashing Protection History Via CLI (#8040)

* include cli entrypoint for history exports

* builds properly

* test to confirm we export the data as expected

* abstract helpers properly

* full test suite

* gaz

* better errors

* marshal ident

* Add the additional eip-3076 attestation checks (#7966)

* Replace highest with lowerest

* Update validator/db/kv/attestation_history_v2.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Update validator/db/kv/attestation_history_v2.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Invert equality for saveLowestSourceTargetToDB

* Add eip checks to ensure epochs cant be lower than db ones

* Should be less than equal to

* Check if epoch exists in DB getters

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Add EIP-3076 Invariants for Proposer Slashing Protection (#8067)

* add invariant for proposer protection

* write different test cases

* pass tests

* Add EIP-3076 Interchange JSON CLI command to validator (#7880)

* Import JSON CLI

* CLI impotr

* f

* Begin adding new commands in slashing protection

* Move testing helpers to separate packae

* Add command for importing slashing protection JSONs

* fix import cycle

* fix test

* Undo cleaning changes

* Improvements

* Add better prompts

* Fix prompt

* Fix

* Fix

* Fix

* Fix conflict

* Fix

* Fixes

* Fixes

* Fix exported func

* test func

* Fixes

* fix test

* simplify import and standardize with export

* add round trip test

* true integration test works

* fix up comments

* logrus

* better error

* fix build

* build fix

* Update validator/slashing-protection/cli_export.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Update validator/slashing-protection/cli_import.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* fmt

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Filter Slashable Attester Public Keys in Slashing Interchange Import (#8051)

* filter slashable attesters from the same JSON

* builds

* fix up initially broken test

* circular dep

* import fix

* giz

* added in attesting history package

* add test for filter slashable attester keys

* pass tests

* Save Slashable Keys to Disk in the Validator Client (#8082)

* begin db funcs

* add in test and bucket

* gaz

* rem changes to import

* ineff assign

* add godoc

* Properly Handle Duplicate Public Key Entries in Slashing Interchange Imports (#8089)

* Prevent Blacklisted Public Keys from Slashing Protection Imports from Having Duties at Runtime (#8084)

* tests on update duties

* ensure the slashable public keys are filtered out from update duties via test

* begin test

* attempt test

* rename for better context

* pass tests

* deep source

* ensure tests pass

* Check for Signing Root Mismatch When Submitting Proposals and Importing Proposals in Slashing Interchange (#8085)

* flexible signing root

* add test

* add tests

* fix test

* Preston's comments

* res tests

* ensure we consider the case for minimum proposals

* pass test

* tests passing

* rem unused code

* Set Empty Epochs in Between Attestations as FAR_FUTURE_EPOCH in Attesting History (#8113)

* set target data

* all tests passing

* ineff assign

* signing root

* Add Slashing Interchange, EIP-3076, Spec Tests to Prysm (#7858)

* Add interchange test framework

* add checks for attestations

* Import genesis root if necessary

* flexible signing root

* add test

* Sync

* fix up test build

* only 3 failing tests now

* two failing

* attempting to debug problems in conformity tests

* include latest changes

* protect test in validator/client passing

* pass tests

* imports

* spec tests passing with bazel

* gh archive link to spectests using tar.gz suffix

* rev

* rev more comment changes

* fix sha

* godoc

* add back save

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Implement Migration for Unattested Epochs in Attesting History Database (#8121)

* migrate attesting history backbone done

* begin migration logic

* implement migration logic

* migration test

* add test

* migration logic

* bazel

* migration to its own file

* Handle empty blocks and attestations in interchange json and sort interchange json by public key (#8132)

* Handle empty blocks and attestations in interchange json

* add test

* sort json

* easier empty arrays

* pass test

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* builds

* more tests finally build

* Align Slashing Interchange With Optimized Slashing Protection (#8268)

* attestation history should account for multiple targets per source

* attempt at some fixes

* attempt some test fixes

* experimenting with sorting

* only one more failing test

* tests now pass

* slash protect tests passing

* only few tests now failing

* only spec tests failing now

* spec tests passing

* all tests passing

* helper function for verifying double votes

* use helper

* gaz

* deep source

* tests fixed

* expect specific number of times for domain data calls

* final comments

* Batch Save Imported EIP-3076 Attestations (#8304)

* optimize save

* test added

* add test for sad path

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>

* revert bad find replace

* add comment to db func

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: Shay Zluf <thezluf@gmail.com>
2021-01-22 17:12:22 -06:00

541 lines
18 KiB
Go

// Package node is the main process which handles the lifecycle of
// the runtime services in a validator client process, gracefully shutting
// everything down upon close.
package node
import (
"context"
"fmt"
"os"
"os/signal"
"path/filepath"
"strings"
"sync"
"syscall"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/shared"
"github.com/prysmaticlabs/prysm/shared/backuputil"
"github.com/prysmaticlabs/prysm/shared/cmd"
"github.com/prysmaticlabs/prysm/shared/debug"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/fileutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/prereq"
"github.com/prysmaticlabs/prysm/shared/prometheus"
"github.com/prysmaticlabs/prysm/shared/tracing"
"github.com/prysmaticlabs/prysm/shared/version"
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
"github.com/prysmaticlabs/prysm/validator/client"
"github.com/prysmaticlabs/prysm/validator/db/kv"
"github.com/prysmaticlabs/prysm/validator/flags"
g "github.com/prysmaticlabs/prysm/validator/graffiti"
"github.com/prysmaticlabs/prysm/validator/keymanager"
"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
"github.com/prysmaticlabs/prysm/validator/rpc"
"github.com/prysmaticlabs/prysm/validator/rpc/gateway"
slashingprotection "github.com/prysmaticlabs/prysm/validator/slashing-protection"
"github.com/prysmaticlabs/prysm/validator/slashing-protection/iface"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
// ValidatorClient defines an instance of an eth2 validator that manages
// the entire lifecycle of services attached to it participating in eth2.
type ValidatorClient struct {
cliCtx *cli.Context
db *kv.Store
services *shared.ServiceRegistry // Lifecycle and service store.
lock sync.RWMutex
wallet *wallet.Wallet
walletInitialized *event.Feed
stop chan struct{} // Channel to wait for termination notifications.
}
// NewValidatorClient creates a new, Prysm validator client.
func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) {
if err := tracing.Setup(
"validator", // service name
cliCtx.String(cmd.TracingProcessNameFlag.Name),
cliCtx.String(cmd.TracingEndpointFlag.Name),
cliCtx.Float64(cmd.TraceSampleFractionFlag.Name),
cliCtx.Bool(cmd.EnableTracingFlag.Name),
); err != nil {
return nil, err
}
verbosity := cliCtx.String(cmd.VerbosityFlag.Name)
level, err := logrus.ParseLevel(verbosity)
if err != nil {
return nil, err
}
logrus.SetLevel(level)
// Warn if user's platform is not supported
prereq.WarnIfNotSupported(cliCtx.Context)
registry := shared.NewServiceRegistry()
ValidatorClient := &ValidatorClient{
cliCtx: cliCtx,
services: registry,
walletInitialized: new(event.Feed),
stop: make(chan struct{}),
}
featureconfig.ConfigureValidator(cliCtx)
cmd.ConfigureValidator(cliCtx)
if cliCtx.IsSet(cmd.ChainConfigFileFlag.Name) {
chainConfigFileName := cliCtx.String(cmd.ChainConfigFileFlag.Name)
params.LoadChainConfigFile(chainConfigFileName)
}
// If the --web flag is enabled to administer the validator
// client via a web portal, we start the validator client in a different way.
if cliCtx.IsSet(flags.EnableWebFlag.Name) {
log.Info("Enabling web portal to manage the validator client")
if err := ValidatorClient.initializeForWeb(cliCtx); err != nil {
return nil, err
}
return ValidatorClient, nil
}
if cliCtx.IsSet(cmd.ChainConfigFileFlag.Name) {
chainConfigFileName := cliCtx.String(cmd.ChainConfigFileFlag.Name)
params.LoadChainConfigFile(chainConfigFileName)
}
if err := ValidatorClient.initializeFromCLI(cliCtx); err != nil {
return nil, err
}
return ValidatorClient, nil
}
// Start every service in the validator client.
func (c *ValidatorClient) Start() {
c.lock.Lock()
log.WithFields(logrus.Fields{
"version": version.GetVersion(),
}).Info("Starting validator node")
c.services.StartAll()
stop := c.stop
c.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(c.cliCtx) // Ensure trace and CPU profile data are flushed.
go c.Close()
for i := 10; i > 0; i-- {
<-sigc
if i > 1 {
log.WithField("times", i-1).Info("Already shutting down, interrupt more to panic.")
}
}
panic("Panic closing the validator client")
}()
// Wait for stop channel to be closed.
<-stop
}
// Close handles graceful shutdown of the system.
func (c *ValidatorClient) Close() {
c.lock.Lock()
defer c.lock.Unlock()
c.services.StopAll()
log.Info("Stopping Prysm validator")
close(c.stop)
}
func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
var keyManager keymanager.IKeymanager
var err error
if cliCtx.IsSet(flags.InteropNumValidators.Name) {
numValidatorKeys := cliCtx.Uint64(flags.InteropNumValidators.Name)
offset := cliCtx.Uint64(flags.InteropStartIndex.Name)
keyManager, err = imported.NewInteropKeymanager(cliCtx.Context, offset, numValidatorKeys)
if err != nil {
return errors.Wrap(err, "could not generate interop keys")
}
} else {
// Read the wallet from the specified path.
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
return nil, wallet.ErrNoWalletFound
})
if err != nil {
return errors.Wrap(err, "could not open wallet")
}
c.wallet = w
log.WithFields(logrus.Fields{
"wallet": w.AccountsDir(),
"keymanager-kind": w.KeymanagerKind().String(),
}).Info("Opened validator wallet")
keyManager, err = w.InitializeKeymanager(cliCtx.Context)
if err != nil {
return errors.Wrap(err, "could not read keymanager for wallet")
}
}
dataDir := cliCtx.String(flags.WalletDirFlag.Name)
if c.wallet != nil {
dataDir = c.wallet.AccountsDir()
}
if cliCtx.String(cmd.DataDirFlag.Name) != cmd.DefaultDataDir() {
dataDir = cliCtx.String(cmd.DataDirFlag.Name)
}
clearFlag := cliCtx.Bool(cmd.ClearDB.Name)
forceClearFlag := cliCtx.Bool(cmd.ForceClearDB.Name)
if clearFlag || forceClearFlag {
if dataDir == "" && c.wallet != nil {
dataDir = c.wallet.AccountsDir()
if dataDir == "" {
log.Fatal(
"Could not determine your system'c HOME path, please specify a --datadir you wish " +
"to use for your validator data",
)
}
}
if err := clearDB(cliCtx.Context, dataDir, forceClearFlag); err != nil {
return err
}
} else {
dataFile := filepath.Join(dataDir, kv.ProtectionDbFileName)
if !fileutil.FileExists(dataFile) {
log.Warnf("Slashing protection file %s is missing.\n"+
"If you changed your --wallet-dir or --datadir, please copy your previous \"validator.db\" file into your current --datadir.\n"+
"Disregard this warning if this is the first time you are running this set of keys.", dataFile)
}
}
log.WithField("databasePath", dataDir).Info("Checking DB")
valDB, err := kv.NewKVStore(cliCtx.Context, dataDir, nil)
if err != nil {
return errors.Wrap(err, "could not initialize db")
}
c.db = valDB
if err := valDB.RunUpMigrations(cliCtx.Context); err != nil {
return errors.Wrap(err, "could not run database migration")
}
if !cliCtx.Bool(cmd.DisableMonitoringFlag.Name) {
if err := c.registerPrometheusService(cliCtx); err != nil {
return err
}
}
if featureconfig.Get().SlasherProtection {
if err := c.registerSlasherClientService(); err != nil {
return err
}
}
if err := c.registerClientService(keyManager); err != nil {
return err
}
if cliCtx.Bool(flags.EnableRPCFlag.Name) {
if err := c.registerRPCService(cliCtx, keyManager); err != nil {
return err
}
if err := c.registerRPCGatewayService(cliCtx); err != nil {
return err
}
}
return nil
}
func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
var keyManager keymanager.IKeymanager
var err error
walletDir := cliCtx.String(flags.WalletDirFlag.Name)
defaultWalletPasswordFilePath := filepath.Join(walletDir, wallet.DefaultWalletPasswordFile)
if fileutil.FileExists(defaultWalletPasswordFilePath) {
if err := cliCtx.Set(flags.WalletPasswordFileFlag.Name, defaultWalletPasswordFilePath); err != nil {
return errors.Wrap(err, "could not set default wallet password file path")
}
}
// Read the wallet from the specified path.
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
return nil, nil
})
if err != nil {
return errors.Wrap(err, "could not open wallet")
}
if w != nil {
c.wallet = w
log.WithFields(logrus.Fields{
"wallet": w.AccountsDir(),
"keymanager-kind": w.KeymanagerKind().String(),
}).Info("Opened validator wallet")
keyManager, err = w.InitializeKeymanager(cliCtx.Context)
if err != nil {
return errors.Wrap(err, "could not read keymanager for wallet")
}
}
dataDir := cliCtx.String(flags.WalletDirFlag.Name)
if c.wallet != nil {
dataDir = c.wallet.AccountsDir()
}
if cliCtx.String(cmd.DataDirFlag.Name) != cmd.DefaultDataDir() {
dataDir = cliCtx.String(cmd.DataDirFlag.Name)
}
clearFlag := cliCtx.Bool(cmd.ClearDB.Name)
forceClearFlag := cliCtx.Bool(cmd.ForceClearDB.Name)
if clearFlag || forceClearFlag {
if dataDir == "" {
dataDir = cmd.DefaultDataDir()
if dataDir == "" {
log.Fatal(
"Could not determine your system'c HOME path, please specify a --datadir you wish " +
"to use for your validator data",
)
}
}
if err := clearDB(cliCtx.Context, dataDir, forceClearFlag); err != nil {
return err
}
}
log.WithField("databasePath", dataDir).Info("Checking DB")
valDB, err := kv.NewKVStore(cliCtx.Context, dataDir, make([][48]byte, 0))
if err != nil {
return errors.Wrap(err, "could not initialize db")
}
c.db = valDB
if err := valDB.RunUpMigrations(cliCtx.Context); err != nil {
return errors.Wrap(err, "could not run database migration")
}
if !cliCtx.Bool(cmd.DisableMonitoringFlag.Name) {
if err := c.registerPrometheusService(cliCtx); err != nil {
return err
}
}
if featureconfig.Get().SlasherProtection {
if err := c.registerSlasherClientService(); err != nil {
return err
}
}
if err := c.registerClientService(keyManager); err != nil {
return err
}
if err := c.registerRPCService(cliCtx, keyManager); err != nil {
return err
}
if err := c.registerRPCGatewayService(cliCtx); err != nil {
return err
}
gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name)
gatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name)
webAddress := fmt.Sprintf("http://%s:%d", gatewayHost, gatewayPort)
log.WithField("address", webAddress).Info(
"Starting Prysm web UI on address, open in browser to access",
)
return nil
}
func (c *ValidatorClient) registerPrometheusService(cliCtx *cli.Context) error {
var additionalHandlers []prometheus.Handler
if cliCtx.IsSet(cmd.EnableBackupWebhookFlag.Name) {
additionalHandlers = append(
additionalHandlers,
prometheus.Handler{
Path: "/db/backup",
Handler: backuputil.BackupHandler(c.db, cliCtx.String(cmd.BackupWebhookOutputDir.Name)),
},
)
}
service := prometheus.NewService(
fmt.Sprintf("%s:%d", c.cliCtx.String(cmd.MonitoringHostFlag.Name), c.cliCtx.Int(flags.MonitoringPortFlag.Name)),
c.services,
additionalHandlers...,
)
logrus.AddHook(prometheus.NewLogrusCollector())
return c.services.RegisterService(service)
}
func (c *ValidatorClient) registerClientService(
keyManager keymanager.IKeymanager,
) error {
endpoint := c.cliCtx.String(flags.BeaconRPCProviderFlag.Name)
dataDir := c.cliCtx.String(cmd.DataDirFlag.Name)
logValidatorBalances := !c.cliCtx.Bool(flags.DisablePenaltyRewardLogFlag.Name)
emitAccountMetrics := !c.cliCtx.Bool(flags.DisableAccountMetricsFlag.Name)
cert := c.cliCtx.String(flags.CertFlag.Name)
graffiti := c.cliCtx.String(flags.GraffitiFlag.Name)
maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
var sp *slashingprotection.Service
var protector iface.Protector
if err := c.services.FetchService(&sp); err == nil {
protector = sp
}
gStruct := &g.Graffiti{}
var err error
if c.cliCtx.IsSet(flags.GraffitiFileFlag.Name) {
n := c.cliCtx.String(flags.GraffitiFileFlag.Name)
gStruct, err = g.ParseGraffitiFile(n)
if err != nil {
log.WithError(err).Warn("Could not parse graffiti file")
}
}
v, err := client.NewValidatorService(c.cliCtx.Context, &client.Config{
Endpoint: endpoint,
DataDir: dataDir,
KeyManager: keyManager,
LogValidatorBalances: logValidatorBalances,
EmitAccountMetrics: emitAccountMetrics,
CertFlag: cert,
GraffitiFlag: graffiti,
GrpcMaxCallRecvMsgSizeFlag: maxCallRecvMsgSize,
GrpcRetriesFlag: grpcRetries,
GrpcRetryDelay: grpcRetryDelay,
GrpcHeadersFlag: c.cliCtx.String(flags.GrpcHeadersFlag.Name),
Protector: protector,
ValDB: c.db,
UseWeb: c.cliCtx.Bool(flags.EnableWebFlag.Name),
WalletInitializedFeed: c.walletInitialized,
GraffitiStruct: gStruct,
LogDutyCountDown: c.cliCtx.Bool(flags.EnableDutyCountDown.Name),
})
if err != nil {
return errors.Wrap(err, "could not initialize client service")
}
return c.services.RegisterService(v)
}
func (c *ValidatorClient) registerSlasherClientService() error {
endpoint := c.cliCtx.String(flags.SlasherRPCProviderFlag.Name)
if endpoint == "" {
return errors.New("external slasher feature flag is set but no slasher endpoint is configured")
}
cert := c.cliCtx.String(flags.SlasherCertFlag.Name)
maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
sp, err := slashingprotection.NewService(c.cliCtx.Context, &slashingprotection.Config{
Endpoint: endpoint,
CertFlag: cert,
GrpcMaxCallRecvMsgSizeFlag: maxCallRecvMsgSize,
GrpcRetriesFlag: grpcRetries,
GrpcRetryDelay: grpcRetryDelay,
GrpcHeadersFlag: c.cliCtx.String(flags.GrpcHeadersFlag.Name),
})
if err != nil {
return errors.Wrap(err, "could not initialize client service")
}
return c.services.RegisterService(sp)
}
func (c *ValidatorClient) registerRPCService(cliCtx *cli.Context, km keymanager.IKeymanager) error {
var vs *client.ValidatorService
if err := c.services.FetchService(&vs); err != nil {
return err
}
validatorGatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name)
validatorGatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name)
validatorMonitoringHost := cliCtx.String(cmd.MonitoringHostFlag.Name)
validatorMonitoringPort := cliCtx.Int(flags.MonitoringPortFlag.Name)
rpcHost := cliCtx.String(flags.RPCHost.Name)
rpcPort := cliCtx.Int(flags.RPCPort.Name)
nodeGatewayEndpoint := cliCtx.String(flags.BeaconRPCGatewayProviderFlag.Name)
beaconClientEndpoint := cliCtx.String(flags.BeaconRPCProviderFlag.Name)
maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
walletDir := cliCtx.String(flags.WalletDirFlag.Name)
grpcHeaders := c.cliCtx.String(flags.GrpcHeadersFlag.Name)
clientCert := c.cliCtx.String(flags.CertFlag.Name)
server := rpc.NewServer(cliCtx.Context, &rpc.Config{
ValDB: c.db,
Host: rpcHost,
Port: fmt.Sprintf("%d", rpcPort),
WalletInitializedFeed: c.walletInitialized,
ValidatorService: vs,
SyncChecker: vs,
GenesisFetcher: vs,
NodeGatewayEndpoint: nodeGatewayEndpoint,
WalletDir: walletDir,
Wallet: c.wallet,
Keymanager: km,
ValidatorGatewayHost: validatorGatewayHost,
ValidatorGatewayPort: validatorGatewayPort,
ValidatorMonitoringHost: validatorMonitoringHost,
ValidatorMonitoringPort: validatorMonitoringPort,
BeaconClientEndpoint: beaconClientEndpoint,
ClientMaxCallRecvMsgSize: maxCallRecvMsgSize,
ClientGrpcRetries: grpcRetries,
ClientGrpcRetryDelay: grpcRetryDelay,
ClientGrpcHeaders: strings.Split(grpcHeaders, ","),
ClientWithCert: clientCert,
})
return c.services.RegisterService(server)
}
func (c *ValidatorClient) registerRPCGatewayService(cliCtx *cli.Context) error {
gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name)
if gatewayHost != flags.DefaultGatewayHost {
log.WithField("web-host", gatewayHost).Warn(
"You are using a non-default web host. Web traffic is served by HTTP, so be wary of " +
"changing this parameter if you are exposing this host to the Internet!",
)
}
gatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name)
rpcHost := cliCtx.String(flags.RPCHost.Name)
rpcPort := cliCtx.Int(flags.RPCPort.Name)
rpcAddr := fmt.Sprintf("%s:%d", rpcHost, rpcPort)
gatewayAddress := fmt.Sprintf("%s:%d", gatewayHost, gatewayPort)
allowedOrigins := strings.Split(cliCtx.String(flags.GPRCGatewayCorsDomain.Name), ",")
gatewaySrv := gateway.New(
cliCtx.Context,
rpcAddr,
gatewayAddress,
allowedOrigins,
)
return c.services.RegisterService(gatewaySrv)
}
func clearDB(ctx context.Context, dataDir string, force bool) error {
var err error
clearDBConfirmed := force
if !force {
actionText := "This will delete your validator's historical actions database stored in your data directory. " +
"This may lead to potential slashing - do you want to proceed? (Y/N)"
deniedText := "The historical actions database will not be deleted. No changes have been made."
clearDBConfirmed, err = cmd.ConfirmAction(actionText, deniedText)
if err != nil {
return errors.Wrapf(err, "Could not clear DB in dir %s", dataDir)
}
}
if clearDBConfirmed {
valDB, err := kv.NewKVStore(ctx, dataDir, nil)
if err != nil {
return errors.Wrapf(err, "Could not create DB in dir %s", dataDir)
}
if err := valDB.Close(); err != nil {
return errors.Wrapf(err, "could not close DB in dir %s", dataDir)
}
log.Warning("Removing database")
if err := valDB.ClearDB(); err != nil {
return errors.Wrapf(err, "Could not clear DB in dir %s", dataDir)
}
}
return nil
}