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 }