mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Remove Deposit Command from Validator Client (#7379)
* remove deposit code * Merge refs/heads/master into remove-deposit
This commit is contained in:
@@ -7,7 +7,6 @@ go_library(
|
||||
"accounts_backup.go",
|
||||
"accounts_create.go",
|
||||
"accounts_delete.go",
|
||||
"accounts_deposit.go",
|
||||
"accounts_exit.go",
|
||||
"accounts_helper.go",
|
||||
"accounts_import.go",
|
||||
@@ -30,7 +29,6 @@ go_library(
|
||||
"//shared/cmd:go_default_library",
|
||||
"//shared/featureconfig:go_default_library",
|
||||
"//shared/fileutil:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"//shared/petnames:go_default_library",
|
||||
"//shared/promptutil:go_default_library",
|
||||
"//validator/accounts/v2/prompt:go_default_library",
|
||||
@@ -61,7 +59,6 @@ go_test(
|
||||
"accounts_backup_test.go",
|
||||
"accounts_create_test.go",
|
||||
"accounts_delete_test.go",
|
||||
"accounts_deposit_test.go",
|
||||
"accounts_exit_test.go",
|
||||
"accounts_import_test.go",
|
||||
"accounts_list_test.go",
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/promptutil"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts/v2/prompt"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts/v2/wallet"
|
||||
"github.com/prysmaticlabs/prysm/validator/flags"
|
||||
v2keymanager "github.com/prysmaticlabs/prysm/validator/keymanager/v2"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager/v2/derived"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// SendDepositCli transaction for user specified accounts via an interactive
|
||||
// CLI process or via command-line flags.
|
||||
func SendDepositCli(cliCtx *cli.Context) error {
|
||||
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
|
||||
return nil, errors.New(
|
||||
"no wallet found, nothing to deposit",
|
||||
)
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not open wallet")
|
||||
}
|
||||
keymanager, err := w.InitializeKeymanager(
|
||||
cliCtx.Context,
|
||||
true, /* skip mnemonic confirm */
|
||||
)
|
||||
if err != nil && strings.Contains(err.Error(), "invalid checksum") {
|
||||
return errors.New("wrong wallet password entered")
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize keymanager")
|
||||
}
|
||||
switch w.KeymanagerKind() {
|
||||
case v2keymanager.Derived:
|
||||
km, ok := keymanager.(*derived.Keymanager)
|
||||
if !ok {
|
||||
return errors.New("could not assert keymanager interface to concrete type")
|
||||
}
|
||||
depositConfig, err := createDepositConfig(cliCtx, km)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize deposit config")
|
||||
}
|
||||
if err := km.SendDepositTx(depositConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errors.New("only Prysm HD wallets support sending deposits at the moment")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createDepositConfig(cliCtx *cli.Context, km *derived.Keymanager) (*derived.SendDepositConfig, error) {
|
||||
pubKeysBytes, err := km.FetchValidatingPublicKeys(cliCtx.Context)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not fetch validating public keys")
|
||||
}
|
||||
pubKeys := make([]bls.PublicKey, len(pubKeysBytes))
|
||||
for i, pk := range pubKeysBytes {
|
||||
pubKeys[i], err = bls.PublicKeyFromBytes(pk[:])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse BLS public key")
|
||||
}
|
||||
}
|
||||
// Allow the user to interactively select the accounts to deposit or optionally
|
||||
// provide them via cli flags as a string of comma-separated, hex strings. If the user has
|
||||
// selected to deposit all accounts, we skip this part.
|
||||
if !cliCtx.IsSet(flags.DepositAllAccountsFlag.Name) {
|
||||
pubKeys, err = filterPublicKeysFromUserInput(
|
||||
cliCtx,
|
||||
flags.DepositPublicKeysFlag,
|
||||
pubKeysBytes,
|
||||
prompt.SelectAccountsDepositPromptText,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not filter validating public keys for deposit")
|
||||
}
|
||||
}
|
||||
|
||||
web3Provider := cliCtx.String(flags.HTTPWeb3ProviderFlag.Name)
|
||||
// Enter the web3provider information.
|
||||
if web3Provider == "" {
|
||||
web3Provider, err = promptutil.DefaultAndValidatePrompt(
|
||||
"Enter the HTTP address of your eth1 endpoint for the Goerli testnet",
|
||||
cliCtx.String(flags.HTTPWeb3ProviderFlag.Name),
|
||||
func(input string) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not validate web3 provider endpoint")
|
||||
}
|
||||
}
|
||||
depositDelaySeconds := cliCtx.Int(flags.DepositDelaySecondsFlag.Name)
|
||||
config := &derived.SendDepositConfig{
|
||||
DepositContractAddress: cliCtx.String(flags.DepositContractAddressFlag.Name),
|
||||
DepositDelaySeconds: time.Duration(depositDelaySeconds) * time.Second,
|
||||
DepositPublicKeys: pubKeys,
|
||||
Web3Provider: web3Provider,
|
||||
}
|
||||
|
||||
if !cliCtx.Bool(flags.SkipDepositConfirmationFlag.Name) {
|
||||
confirmDepositPrompt := "You are about to send %d ETH into contract address %s for %d eth2 validator accounts. " +
|
||||
"Are you sure you want to do this? Enter the words 'yes I do' to continue"
|
||||
gweiPerEth := params.BeaconConfig().GweiPerEth
|
||||
ethDepositTotal := uint64(len(pubKeys)) * params.BeaconConfig().MaxEffectiveBalance / gweiPerEth
|
||||
if _, err := promptutil.ValidatePrompt(
|
||||
os.Stdin,
|
||||
fmt.Sprintf(confirmDepositPrompt, ethDepositTotal, config.DepositContractAddress, len(pubKeys)),
|
||||
func(input string) error {
|
||||
if input != "yes I do" {
|
||||
return errors.New("please enter 'yes I do' or exit")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
); err != nil {
|
||||
return nil, errors.Wrap(err, "could not confirm deposit acknowledgement")
|
||||
}
|
||||
}
|
||||
|
||||
// If the user passes any of the specified flags, we read them and return the
|
||||
// config struct directly, bypassing any CLI input.
|
||||
hasPrivateKey := cliCtx.IsSet(flags.Eth1PrivateKeyFileFlag.Name)
|
||||
hasEth1Keystore := cliCtx.IsSet(flags.Eth1KeystoreUTCPathFlag.Name)
|
||||
if hasPrivateKey || hasEth1Keystore {
|
||||
if hasPrivateKey {
|
||||
fileBytes, err := fileutil.ReadFileAsBytes(cliCtx.String(flags.Eth1PrivateKeyFileFlag.Name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Eth1PrivateKey = strings.TrimRight(string(fileBytes), "\r\n")
|
||||
} else {
|
||||
config.Eth1KeystoreUTCFile = cliCtx.String(flags.Eth1KeystoreUTCPathFlag.Name)
|
||||
if cliCtx.IsSet(flags.Eth1KeystorePasswordFileFlag.Name) {
|
||||
config.Eth1KeystorePasswordFile = cliCtx.String(flags.Eth1KeystorePasswordFileFlag.Name)
|
||||
} else {
|
||||
config.Eth1KeystorePasswordFile, err = prompt.InputWeakPassword(
|
||||
cliCtx,
|
||||
flags.Eth1KeystorePasswordFileFlag,
|
||||
"Enter the file path of a text file containing your eth1 keystore password",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read eth1 keystore password file path")
|
||||
}
|
||||
}
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
usePrivateKeyPrompt := "Inputting an eth1 private key hex string directly"
|
||||
useEth1KeystorePrompt := "Using an encrypted eth1 keystore UTC file"
|
||||
eth1Prompt := promptui.Select{
|
||||
Label: "Select how you wish to sign your eth1 transaction",
|
||||
Items: []string{
|
||||
usePrivateKeyPrompt,
|
||||
useEth1KeystorePrompt,
|
||||
},
|
||||
}
|
||||
_, selection, err := eth1Prompt.Run()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If the user wants to proceed by inputting their private key directly, ask for it securely.
|
||||
if selection == usePrivateKeyPrompt {
|
||||
eth1PrivateKeyString, err := promptutil.PasswordPrompt(
|
||||
"Enter the hex string value of your eth1 private key",
|
||||
promptutil.NotEmpty,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read eth1 private key string")
|
||||
}
|
||||
config.Eth1PrivateKey = strings.TrimRight(eth1PrivateKeyString, "\r\n")
|
||||
} else if selection == useEth1KeystorePrompt {
|
||||
// Otherwise, ask the user for paths to their keystore UTC file and its password.
|
||||
eth1KeystoreUTCFile, err := promptutil.DefaultAndValidatePrompt(
|
||||
"Enter the file path for your encrypted, eth1 keystore-utc file",
|
||||
cliCtx.String(flags.Eth1KeystoreUTCPathFlag.Name),
|
||||
func(input string) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read eth1 keystore UTC path")
|
||||
}
|
||||
eth1KeystorePasswordFile, err := prompt.InputWeakPassword(
|
||||
cliCtx,
|
||||
flags.Eth1KeystorePasswordFileFlag,
|
||||
"Enter the file path to a text file containing your eth1 keystore password",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read eth1 keystore password file path")
|
||||
}
|
||||
config.Eth1KeystoreUTCFile = eth1KeystoreUTCFile
|
||||
config.Eth1KeystorePasswordFile = eth1KeystorePasswordFile
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
|
||||
"github.com/prysmaticlabs/prysm/shared/testutil/require"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts/v2/wallet"
|
||||
"github.com/prysmaticlabs/prysm/validator/flags"
|
||||
v2keymanager "github.com/prysmaticlabs/prysm/validator/keymanager/v2"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager/v2/derived"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type depositTestWalletConfig struct {
|
||||
walletDir string
|
||||
walletPasswordFile string
|
||||
eth1KeystoreFile string
|
||||
eth1KeystorePasswordFile string
|
||||
eth1PrivateKeyFile string
|
||||
httpWeb3ProviderFlag string
|
||||
publicKeysFlag string
|
||||
depositAllAccountsFlag bool
|
||||
skipDepositConfirmationFlag bool
|
||||
keymanagerKind v2keymanager.Kind
|
||||
}
|
||||
|
||||
func setupWalletCtxforDeposits(
|
||||
t *testing.T,
|
||||
cfg *depositTestWalletConfig,
|
||||
) *cli.Context {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String(flags.WalletDirFlag.Name, cfg.walletDir, "")
|
||||
set.String(flags.KeymanagerKindFlag.Name, cfg.keymanagerKind.String(), "")
|
||||
set.String(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile, "")
|
||||
set.String(flags.HTTPWeb3ProviderFlag.Name, cfg.httpWeb3ProviderFlag, "")
|
||||
set.String(flags.Eth1KeystoreUTCPathFlag.Name, cfg.eth1KeystoreFile, "")
|
||||
set.String(flags.Eth1KeystorePasswordFileFlag.Name, cfg.eth1KeystorePasswordFile, "")
|
||||
set.String(flags.Eth1PrivateKeyFileFlag.Name, cfg.eth1PrivateKeyFile, "")
|
||||
set.String(flags.DepositPublicKeysFlag.Name, cfg.publicKeysFlag, "")
|
||||
set.Bool(flags.DepositAllAccountsFlag.Name, cfg.depositAllAccountsFlag, "")
|
||||
set.Bool(flags.SkipDepositConfirmationFlag.Name, cfg.skipDepositConfirmationFlag, "")
|
||||
assert.NoError(t, set.Set(flags.WalletDirFlag.Name, cfg.walletDir))
|
||||
assert.NoError(t, set.Set(flags.KeymanagerKindFlag.Name, cfg.keymanagerKind.String()))
|
||||
assert.NoError(t, set.Set(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile))
|
||||
assert.NoError(t, set.Set(flags.HTTPWeb3ProviderFlag.Name, cfg.httpWeb3ProviderFlag))
|
||||
if cfg.eth1KeystoreFile != "" {
|
||||
assert.NoError(t, set.Set(flags.Eth1KeystoreUTCPathFlag.Name, cfg.eth1KeystoreFile))
|
||||
assert.NoError(t, set.Set(flags.Eth1KeystorePasswordFileFlag.Name, cfg.eth1KeystorePasswordFile))
|
||||
}
|
||||
if cfg.eth1PrivateKeyFile != "" {
|
||||
assert.NoError(t, set.Set(flags.Eth1PrivateKeyFileFlag.Name, cfg.eth1PrivateKeyFile))
|
||||
}
|
||||
if cfg.publicKeysFlag != "" {
|
||||
assert.NoError(t, set.Set(flags.DepositPublicKeysFlag.Name, cfg.publicKeysFlag))
|
||||
}
|
||||
if cfg.depositAllAccountsFlag == true {
|
||||
assert.NoError(t, set.Set(flags.DepositAllAccountsFlag.Name, strconv.FormatBool(cfg.depositAllAccountsFlag)))
|
||||
}
|
||||
assert.NoError(t, set.Set(flags.SkipDepositConfirmationFlag.Name, strconv.FormatBool(cfg.skipDepositConfirmationFlag)))
|
||||
return cli.NewContext(&app, set, nil)
|
||||
}
|
||||
|
||||
func TestCreateDepositConfig(t *testing.T) {
|
||||
walletDir, _, passwordFilePath := setupWalletAndPasswordsDir(t)
|
||||
|
||||
// First, create the wallet and several accounts
|
||||
cliCtx := setupWalletCtx(t, &testWalletConfig{
|
||||
keymanagerKind: v2keymanager.Derived,
|
||||
walletDir: walletDir,
|
||||
walletPasswordFile: passwordFilePath,
|
||||
skipDepositConfirm: true,
|
||||
})
|
||||
w, err := CreateAndSaveWalletCli(cliCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = CreateAccount(cliCtx.Context, &CreateAccountConfig{
|
||||
Wallet: w,
|
||||
NumAccounts: 3,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
keymanager, err := w.InitializeKeymanager(
|
||||
cliCtx.Context,
|
||||
true, /* skip mnemonic confirm */
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Save public keys for comparison and selection purposes later
|
||||
pubkeys, err := keymanager.FetchValidatingPublicKeys(cliCtx.Context)
|
||||
require.NoError(t, err)
|
||||
var hexPubkeys []string
|
||||
for _, pubkey := range pubkeys {
|
||||
encoded := make([]byte, hex.EncodedLen(len(pubkey)))
|
||||
hex.Encode(encoded, pubkey[:])
|
||||
hexPubkeys = append(hexPubkeys, string(encoded))
|
||||
}
|
||||
// Remove the last key so that we can select a portion and not all of the accounts later
|
||||
hexPubkeys = hexPubkeys[:len(hexPubkeys)-1]
|
||||
hexPubkeysString := strings.Join(hexPubkeys, ",")
|
||||
|
||||
// Create a file holding the test ETH1 private key
|
||||
eth1PrivateKeyFile, err := ioutil.TempFile("", "testing")
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
err = eth1PrivateKeyFile.Close()
|
||||
require.NoError(t, err)
|
||||
err = os.Remove(eth1PrivateKeyFile.Name())
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
_, err = eth1PrivateKeyFile.WriteString("This should be an ETH1 private key")
|
||||
require.NoError(t, err)
|
||||
|
||||
// First we test the behavior when depositAllAccountsFlag is set to true
|
||||
depositConfig := createDepositConfigHelper(t, &depositTestWalletConfig{
|
||||
keymanagerKind: v2keymanager.Derived,
|
||||
walletDir: walletDir,
|
||||
walletPasswordFile: passwordFilePath,
|
||||
skipDepositConfirmationFlag: true,
|
||||
depositAllAccountsFlag: true,
|
||||
httpWeb3ProviderFlag: "http://localhost:8545",
|
||||
eth1PrivateKeyFile: eth1PrivateKeyFile.Name(),
|
||||
})
|
||||
|
||||
require.Equal(t, 3, len(depositConfig.DepositPublicKeys), "wrong number of public keys")
|
||||
require.Equal(t, "This should be an ETH1 private key", depositConfig.Eth1PrivateKey, "eth1 private key does not match")
|
||||
require.Equal(t, "http://localhost:8545", depositConfig.Web3Provider, "web3 provider does not match")
|
||||
require.Equal(t, "", depositConfig.Eth1KeystoreUTCFile, "keystore file path should be empty")
|
||||
require.Equal(t, "", depositConfig.Eth1KeystorePasswordFile, "keystore password file path should be empty")
|
||||
|
||||
// Test the case of providing the public keys via command-line. We also pass in the test eth1 private key file.
|
||||
// hexPubkeysString holds 1 less than all the accounts.
|
||||
depositConfig = createDepositConfigHelper(t, &depositTestWalletConfig{
|
||||
keymanagerKind: v2keymanager.Derived,
|
||||
walletDir: walletDir,
|
||||
walletPasswordFile: passwordFilePath,
|
||||
skipDepositConfirmationFlag: true,
|
||||
publicKeysFlag: hexPubkeysString,
|
||||
httpWeb3ProviderFlag: "http://localhost:8545",
|
||||
eth1PrivateKeyFile: eth1PrivateKeyFile.Name(),
|
||||
})
|
||||
require.Equal(t, 2, len(depositConfig.DepositPublicKeys), "wrong number of public keys")
|
||||
|
||||
// Compare the keys in the config object with the keys we obtained earlier from the keymanager
|
||||
for keyNum, configPubKey := range depositConfig.DepositPublicKeys {
|
||||
for index, eachByte := range bytesutil.ToBytes48(configPubKey.Marshal()) {
|
||||
if eachByte != pubkeys[keyNum][index] {
|
||||
require.NoError(t, errors.New("public keys do not match"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now we test when private key file is not provided but rather the keystore and keystore password files
|
||||
depositConfig = createDepositConfigHelper(t, &depositTestWalletConfig{
|
||||
keymanagerKind: v2keymanager.Derived,
|
||||
walletDir: walletDir,
|
||||
walletPasswordFile: passwordFilePath,
|
||||
skipDepositConfirmationFlag: true,
|
||||
depositAllAccountsFlag: true,
|
||||
httpWeb3ProviderFlag: "http://localhost:8545",
|
||||
eth1KeystoreFile: "This would be eth1 keystore file path",
|
||||
eth1KeystorePasswordFile: "This would be eth1 keystore password file path",
|
||||
})
|
||||
require.Equal(t, 3, len(depositConfig.DepositPublicKeys), "wrong number of public keys")
|
||||
require.Equal(t, "This would be eth1 keystore file path", depositConfig.Eth1KeystoreUTCFile,
|
||||
"eth1 keystore file path incorrect")
|
||||
require.Equal(t, "This would be eth1 keystore password file path", depositConfig.Eth1KeystorePasswordFile,
|
||||
"eth1 keystore password file path incorrect")
|
||||
require.Equal(t, "", depositConfig.Eth1PrivateKey, "eth1 private key should be empty string")
|
||||
}
|
||||
|
||||
// createDepositConfigHelper returns a SendDepositConfig when given a particular wallet configuration.
|
||||
func createDepositConfigHelper(t *testing.T, config *depositTestWalletConfig) *derived.SendDepositConfig {
|
||||
cliCtx := setupWalletCtxforDeposits(t, config)
|
||||
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
|
||||
err := errors.New("could not open wallet")
|
||||
require.NoError(t, err)
|
||||
return nil, err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
keymanager, err := w.InitializeKeymanager(
|
||||
cliCtx.Context,
|
||||
true, /* skip mnemonic confirm */
|
||||
)
|
||||
require.NoError(t, err)
|
||||
km, ok := keymanager.(*derived.Keymanager)
|
||||
require.Equal(t, true, ok, "keymanager must be derived type")
|
||||
|
||||
// Now we finally call the function we are testing.
|
||||
depositConfig, err := createDepositConfig(cliCtx, km)
|
||||
require.NoError(t, err)
|
||||
return depositConfig
|
||||
}
|
||||
@@ -151,33 +151,5 @@ this command outputs a deposit data string which is required to become a validat
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "deposit",
|
||||
Description: "Submits a deposit to the eth2 deposit contract for a validator key by connecting " +
|
||||
"to an eth1 endpoint to submit a transaction. Requires signing the transaction with an eth1 private key",
|
||||
Flags: []cli.Flag{
|
||||
flags.WalletDirFlag,
|
||||
flags.WalletPasswordFileFlag,
|
||||
flags.HTTPWeb3ProviderFlag,
|
||||
flags.Eth1KeystoreUTCPathFlag,
|
||||
flags.Eth1KeystorePasswordFileFlag,
|
||||
flags.Eth1PrivateKeyFileFlag,
|
||||
flags.DepositDelaySecondsFlag,
|
||||
flags.DepositContractAddressFlag,
|
||||
flags.DepositPublicKeysFlag,
|
||||
flags.SkipDepositConfirmationFlag,
|
||||
flags.DepositAllAccountsFlag,
|
||||
featureconfig.AltonaTestnet,
|
||||
featureconfig.OnyxTestnet,
|
||||
featureconfig.SpadinaTestnet,
|
||||
},
|
||||
Action: func(cliCtx *cli.Context) error {
|
||||
featureconfig.ConfigureValidator(cliCtx)
|
||||
if err := SendDepositCli(cliCtx); err != nil {
|
||||
log.Fatalf("Could not send validator deposit(s): %v", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user