github.com/prysmaticlabs/prysm@v1.4.4/validator/keymanager/derived/keymanager.go (about)

     1  package derived
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/pkg/errors"
     8  	validatorpb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
     9  	"github.com/prysmaticlabs/prysm/shared/bls"
    10  	"github.com/prysmaticlabs/prysm/shared/event"
    11  	"github.com/prysmaticlabs/prysm/validator/accounts/iface"
    12  	"github.com/prysmaticlabs/prysm/validator/keymanager"
    13  	"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
    14  	util "github.com/wealdtech/go-eth2-util"
    15  )
    16  
    17  const (
    18  	// DerivationPathFormat describes the structure of how keys are derived from a master key.
    19  	DerivationPathFormat = "m / purpose / coin_type / account_index / withdrawal_key / validating_key"
    20  	// ValidatingKeyDerivationPathTemplate defining the hierarchical path for validating
    21  	// keys for Prysm Ethereum validators. According to EIP-2334, the format is as follows:
    22  	// m / purpose / coin_type / account_index / withdrawal_key / validating_key
    23  	ValidatingKeyDerivationPathTemplate = "m/12381/3600/%d/0/0"
    24  )
    25  
    26  // SetupConfig includes configuration values for initializing
    27  // a keymanager, such as passwords, the wallet, and more.
    28  type SetupConfig struct {
    29  	Wallet           iface.Wallet
    30  	ListenForChanges bool
    31  }
    32  
    33  // Keymanager implementation for derived, HD keymanager using EIP-2333 and EIP-2334.
    34  type Keymanager struct {
    35  	importedKM *imported.Keymanager
    36  }
    37  
    38  // NewKeymanager instantiates a new derived keymanager from configuration options.
    39  func NewKeymanager(
    40  	ctx context.Context,
    41  	cfg *SetupConfig,
    42  ) (*Keymanager, error) {
    43  	importedKM, err := imported.NewKeymanager(ctx, &imported.SetupConfig{
    44  		Wallet:           cfg.Wallet,
    45  		ListenForChanges: cfg.ListenForChanges,
    46  	})
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	return &Keymanager{
    51  		importedKM: importedKM,
    52  	}, nil
    53  }
    54  
    55  // RecoverAccountsFromMnemonic given a mnemonic phrase, is able to regenerate N accounts
    56  // from a derived seed, encrypt them according to the EIP-2334 JSON standard, and write them
    57  // to disk. Then, the mnemonic is never stored nor used by the validator.
    58  func (km *Keymanager) RecoverAccountsFromMnemonic(
    59  	ctx context.Context, mnemonic, mnemonicPassphrase string, numAccounts int,
    60  ) error {
    61  	seed, err := seedFromMnemonic(mnemonic, mnemonicPassphrase)
    62  	if err != nil {
    63  		return errors.Wrap(err, "could not initialize new wallet seed file")
    64  	}
    65  	privKeys := make([][]byte, numAccounts)
    66  	pubKeys := make([][]byte, numAccounts)
    67  	for i := 0; i < numAccounts; i++ {
    68  		privKey, err := util.PrivateKeyFromSeedAndPath(
    69  			seed, fmt.Sprintf(ValidatingKeyDerivationPathTemplate, i),
    70  		)
    71  		if err != nil {
    72  			return err
    73  		}
    74  		privKeys[i] = privKey.Marshal()
    75  		pubKeys[i] = privKey.PublicKey().Marshal()
    76  	}
    77  	return km.importedKM.ImportKeypairs(ctx, privKeys, pubKeys)
    78  }
    79  
    80  // ExtractKeystores retrieves the secret keys for specified public keys
    81  // in the function input, encrypts them using the specified password,
    82  // and returns their respective EIP-2335 keystores.
    83  func (km *Keymanager) ExtractKeystores(
    84  	ctx context.Context, publicKeys []bls.PublicKey, password string,
    85  ) ([]*keymanager.Keystore, error) {
    86  	return km.importedKM.ExtractKeystores(ctx, publicKeys, password)
    87  }
    88  
    89  // ValidatingAccountNames for the derived keymanager.
    90  func (km *Keymanager) ValidatingAccountNames(_ context.Context) ([]string, error) {
    91  	return km.importedKM.ValidatingAccountNames()
    92  }
    93  
    94  // Sign signs a message using a validator key.
    95  func (km *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (bls.Signature, error) {
    96  	return km.importedKM.Sign(ctx, req)
    97  }
    98  
    99  // FetchValidatingPublicKeys fetches the list of validating public keys from the keymanager.
   100  func (km *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
   101  	return km.importedKM.FetchValidatingPublicKeys(ctx)
   102  }
   103  
   104  // FetchValidatingPrivateKeys fetches the list of validating private keys from the keymanager.
   105  func (km *Keymanager) FetchValidatingPrivateKeys(ctx context.Context) ([][32]byte, error) {
   106  	return km.importedKM.FetchValidatingPrivateKeys(ctx)
   107  }
   108  
   109  // DeleteAccounts for a derived keymanager.
   110  func (km *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) error {
   111  	return km.importedKM.DeleteAccounts(ctx, publicKeys)
   112  }
   113  
   114  // SubscribeAccountChanges creates an event subscription for a channel
   115  // to listen for public key changes at runtime, such as when new validator accounts
   116  // are imported into the keymanager while the validator process is running.
   117  func (km *Keymanager) SubscribeAccountChanges(pubKeysChan chan [][48]byte) event.Subscription {
   118  	return km.importedKM.SubscribeAccountChanges(pubKeysChan)
   119  }