github.com/prysmaticlabs/prysm@v1.4.4/validator/accounts/accounts_list.go (about)

     1  package accounts
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/logrusorgru/aurora"
    11  	"github.com/pkg/errors"
    12  	"github.com/prysmaticlabs/prysm/cmd/validator/flags"
    13  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    14  	"github.com/prysmaticlabs/prysm/shared/petnames"
    15  	"github.com/prysmaticlabs/prysm/validator/accounts/iface"
    16  	"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
    17  	"github.com/prysmaticlabs/prysm/validator/keymanager"
    18  	"github.com/prysmaticlabs/prysm/validator/keymanager/derived"
    19  	"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
    20  	"github.com/prysmaticlabs/prysm/validator/keymanager/remote"
    21  	"github.com/urfave/cli/v2"
    22  )
    23  
    24  // ListAccountsCli displays all available validator accounts in a Prysm wallet.
    25  func ListAccountsCli(cliCtx *cli.Context) error {
    26  	w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
    27  		return nil, wallet.ErrNoWalletFound
    28  	})
    29  	if err != nil {
    30  		return errors.Wrap(err, "could not open wallet")
    31  	}
    32  	km, err := w.InitializeKeymanager(cliCtx.Context, iface.InitKeymanagerConfig{ListenForChanges: false})
    33  	if err != nil && strings.Contains(err.Error(), "invalid checksum") {
    34  		return errors.New("wrong wallet password entered")
    35  	}
    36  	if err != nil {
    37  		return errors.Wrap(err, ErrCouldNotInitializeKeymanager)
    38  	}
    39  	showDepositData := cliCtx.Bool(flags.ShowDepositDataFlag.Name)
    40  	showPrivateKeys := cliCtx.Bool(flags.ShowPrivateKeysFlag.Name)
    41  	listIndices := cliCtx.Bool(flags.ListValidatorIndices.Name)
    42  
    43  	if listIndices {
    44  		client, _, err := prepareClients(cliCtx)
    45  		if err != nil {
    46  			return err
    47  		}
    48  		return listValidatorIndices(cliCtx.Context, km, *client)
    49  	}
    50  
    51  	switch w.KeymanagerKind() {
    52  	case keymanager.Imported:
    53  		km, ok := km.(*imported.Keymanager)
    54  		if !ok {
    55  			return errors.New("could not assert keymanager interface to concrete type")
    56  		}
    57  		if err := listImportedKeymanagerAccounts(cliCtx.Context, showDepositData, showPrivateKeys, km); err != nil {
    58  			return errors.Wrap(err, "could not list validator accounts with imported keymanager")
    59  		}
    60  	case keymanager.Derived:
    61  		km, ok := km.(*derived.Keymanager)
    62  		if !ok {
    63  			return errors.New("could not assert keymanager interface to concrete type")
    64  		}
    65  		if err := listDerivedKeymanagerAccounts(cliCtx.Context, showPrivateKeys, km); err != nil {
    66  			return errors.Wrap(err, "could not list validator accounts with derived keymanager")
    67  		}
    68  	case keymanager.Remote:
    69  		km, ok := km.(*remote.Keymanager)
    70  		if !ok {
    71  			return errors.New("could not assert keymanager interface to concrete type")
    72  		}
    73  		if err := listRemoteKeymanagerAccounts(cliCtx.Context, w, km, km.KeymanagerOpts()); err != nil {
    74  			return errors.Wrap(err, "could not list validator accounts with remote keymanager")
    75  		}
    76  	default:
    77  		return fmt.Errorf(errKeymanagerNotSupported, w.KeymanagerKind().String())
    78  	}
    79  	return nil
    80  }
    81  
    82  func listImportedKeymanagerAccounts(
    83  	ctx context.Context,
    84  	showDepositData,
    85  	showPrivateKeys bool,
    86  	keymanager *imported.Keymanager,
    87  ) error {
    88  	// We initialize the wallet's keymanager.
    89  	accountNames, err := keymanager.ValidatingAccountNames()
    90  	if err != nil {
    91  		return errors.Wrap(err, "could not fetch account names")
    92  	}
    93  	numAccounts := au.BrightYellow(len(accountNames))
    94  	fmt.Printf("(keymanager kind) %s\n", au.BrightGreen("imported wallet").Bold())
    95  	fmt.Println("")
    96  	if len(accountNames) == 1 {
    97  		fmt.Printf("Showing %d validator account\n", numAccounts)
    98  	} else {
    99  		fmt.Printf("Showing %d validator accounts\n", numAccounts)
   100  	}
   101  	fmt.Println(
   102  		au.BrightRed("View the eth1 deposit transaction data for your accounts " +
   103  			"by running `validator accounts list --show-deposit-data`"),
   104  	)
   105  
   106  	pubKeys, err := keymanager.FetchValidatingPublicKeys(ctx)
   107  	if err != nil {
   108  		return errors.Wrap(err, "could not fetch validating public keys")
   109  	}
   110  	var privateKeys [][32]byte
   111  	if showPrivateKeys {
   112  		privateKeys, err = keymanager.FetchValidatingPrivateKeys(ctx)
   113  		if err != nil {
   114  			return errors.Wrap(err, "could not fetch private keys")
   115  		}
   116  	}
   117  	for i := 0; i < len(accountNames); i++ {
   118  		fmt.Println("")
   119  		fmt.Printf("%s | %s\n", au.BrightBlue(fmt.Sprintf("Account %d", i)).Bold(), au.BrightGreen(accountNames[i]).Bold())
   120  		fmt.Printf("%s %#x\n", au.BrightMagenta("[validating public key]").Bold(), pubKeys[i])
   121  		if showPrivateKeys {
   122  			if len(privateKeys) > i {
   123  				fmt.Printf("%s %#x\n", au.BrightRed("[validating private key]").Bold(), privateKeys[i])
   124  			}
   125  		}
   126  		if !showDepositData {
   127  			continue
   128  		}
   129  		fmt.Printf(
   130  			"%s\n",
   131  			au.BrightRed("If you imported your account coming from the eth2 launchpad, you will find your "+
   132  				"deposit_data.json in the eth2.0-deposit-cli's validator_keys folder"),
   133  		)
   134  		fmt.Println("")
   135  	}
   136  	fmt.Println("")
   137  	return nil
   138  }
   139  
   140  func listDerivedKeymanagerAccounts(
   141  	ctx context.Context,
   142  	showPrivateKeys bool,
   143  	keymanager *derived.Keymanager,
   144  ) error {
   145  	au := aurora.NewAurora(true)
   146  	fmt.Printf("(keymanager kind) %s\n", au.BrightGreen("derived, (HD) hierarchical-deterministic").Bold())
   147  	fmt.Printf("(derivation format) %s\n", au.BrightGreen(derived.DerivationPathFormat).Bold())
   148  	validatingPubKeys, err := keymanager.FetchValidatingPublicKeys(ctx)
   149  	if err != nil {
   150  		return errors.Wrap(err, "could not fetch validating public keys")
   151  	}
   152  	var validatingPrivateKeys [][32]byte
   153  	if showPrivateKeys {
   154  		validatingPrivateKeys, err = keymanager.FetchValidatingPrivateKeys(ctx)
   155  		if err != nil {
   156  			return errors.Wrap(err, "could not fetch validating private keys")
   157  		}
   158  	}
   159  	accountNames, err := keymanager.ValidatingAccountNames(ctx)
   160  	if err != nil {
   161  		return err
   162  	}
   163  	if len(accountNames) == 1 {
   164  		fmt.Print("Showing 1 validator account\n")
   165  	} else if len(accountNames) == 0 {
   166  		fmt.Print("No accounts found\n")
   167  		return nil
   168  	} else {
   169  		fmt.Printf("Showing %d validator accounts\n", len(accountNames))
   170  	}
   171  	for i := 0; i < len(accountNames); i++ {
   172  		fmt.Println("")
   173  		validatingKeyPath := fmt.Sprintf(derived.ValidatingKeyDerivationPathTemplate, i)
   174  
   175  		// Retrieve the withdrawal key account metadata.
   176  		fmt.Printf("%s | %s\n", au.BrightBlue(fmt.Sprintf("Account %d", i)).Bold(), au.BrightGreen(accountNames[i]).Bold())
   177  		// Retrieve the validating key account metadata.
   178  		fmt.Printf("%s %#x\n", au.BrightCyan("[validating public key]").Bold(), validatingPubKeys[i])
   179  		if showPrivateKeys && validatingPrivateKeys != nil {
   180  			fmt.Printf("%s %#x\n", au.BrightRed("[validating private key]").Bold(), validatingPrivateKeys[i])
   181  		}
   182  		fmt.Printf("%s %s\n", au.BrightCyan("[derivation path]").Bold(), validatingKeyPath)
   183  		fmt.Println(" ")
   184  	}
   185  	return nil
   186  }
   187  
   188  func listRemoteKeymanagerAccounts(
   189  	ctx context.Context,
   190  	w *wallet.Wallet,
   191  	keymanager keymanager.IKeymanager,
   192  	opts *remote.KeymanagerOpts,
   193  ) error {
   194  	au := aurora.NewAurora(true)
   195  	fmt.Printf("(keymanager kind) %s\n", au.BrightGreen("remote signer").Bold())
   196  	fmt.Printf(
   197  		"(configuration file path) %s\n",
   198  		au.BrightGreen(filepath.Join(w.AccountsDir(), wallet.KeymanagerConfigFileName)).Bold(),
   199  	)
   200  	fmt.Println(" ")
   201  	fmt.Printf("%s\n", au.BrightGreen("Configuration options").Bold())
   202  	fmt.Println(opts)
   203  	validatingPubKeys, err := keymanager.FetchValidatingPublicKeys(ctx)
   204  	if err != nil {
   205  		return errors.Wrap(err, "could not fetch validating public keys")
   206  	}
   207  	if len(validatingPubKeys) == 1 {
   208  		fmt.Print("Showing 1 validator account\n")
   209  	} else if len(validatingPubKeys) == 0 {
   210  		fmt.Print("No accounts found\n")
   211  		return nil
   212  	} else {
   213  		fmt.Printf("Showing %d validator accounts\n", len(validatingPubKeys))
   214  	}
   215  	for i := 0; i < len(validatingPubKeys); i++ {
   216  		fmt.Println("")
   217  		fmt.Printf(
   218  			"%s\n", au.BrightGreen(petnames.DeterministicName(validatingPubKeys[i][:], "-")).Bold(),
   219  		)
   220  		// Retrieve the validating key account metadata.
   221  		fmt.Printf("%s %#x\n", au.BrightCyan("[validating public key]").Bold(), validatingPubKeys[i])
   222  		fmt.Println(" ")
   223  	}
   224  	return nil
   225  }
   226  
   227  func listValidatorIndices(ctx context.Context, km keymanager.IKeymanager, client ethpb.BeaconNodeValidatorClient) error {
   228  	pubKeys, err := km.FetchValidatingPublicKeys(ctx)
   229  	if err != nil {
   230  		return errors.Wrap(err, "could not get validating public keys")
   231  	}
   232  	var pks [][]byte
   233  	for i := range pubKeys {
   234  		pks = append(pks, pubKeys[i][:])
   235  	}
   236  	req := &ethpb.MultipleValidatorStatusRequest{PublicKeys: pks}
   237  	resp, err := client.MultipleValidatorStatus(ctx, req)
   238  	if err != nil {
   239  		return errors.Wrap(err, "could not request validator indices")
   240  	}
   241  	fmt.Println(au.BrightGreen("Validator indices:").Bold())
   242  	for i, idx := range resp.Indices {
   243  		if idx != math.MaxUint64 {
   244  			fmt.Printf("%#x: %d\n", pubKeys[i][0:4], idx)
   245  		}
   246  	}
   247  	return nil
   248  }