github.com/prysmaticlabs/prysm@v1.4.4/validator/keymanager/imported/import.go (about) 1 package imported 2 3 import ( 4 "context" 5 "encoding/hex" 6 "encoding/json" 7 "fmt" 8 "strings" 9 10 "github.com/k0kubun/go-ansi" 11 "github.com/pkg/errors" 12 "github.com/prysmaticlabs/prysm/shared/bls" 13 "github.com/prysmaticlabs/prysm/shared/promptutil" 14 "github.com/prysmaticlabs/prysm/validator/keymanager" 15 "github.com/schollz/progressbar/v3" 16 keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4" 17 ) 18 19 // ImportKeystores into the imported keymanager from an external source. 20 func (km *Keymanager) ImportKeystores( 21 ctx context.Context, 22 keystores []*keymanager.Keystore, 23 importsPassword string, 24 ) error { 25 decryptor := keystorev4.New() 26 bar := initializeProgressBar(len(keystores), "Importing accounts...") 27 keys := map[string]string{} 28 var err error 29 for i := 0; i < len(keystores); i++ { 30 var privKeyBytes []byte 31 var pubKeyBytes []byte 32 privKeyBytes, pubKeyBytes, importsPassword, err = km.attemptDecryptKeystore(decryptor, keystores[i], importsPassword) 33 if err != nil { 34 return err 35 } 36 // if key exists prior to being added then output log that duplicate key was found 37 if _, ok := keys[string(pubKeyBytes)]; ok { 38 log.Warnf("Duplicate key in import folder will be ignored: %#x", pubKeyBytes) 39 } 40 keys[string(pubKeyBytes)] = string(privKeyBytes) 41 if err := bar.Add(1); err != nil { 42 return errors.Wrap(err, "could not add to progress bar") 43 } 44 } 45 privKeys := make([][]byte, 0) 46 pubKeys := make([][]byte, 0) 47 for pubKey, privKey := range keys { 48 pubKeys = append(pubKeys, []byte(pubKey)) 49 privKeys = append(privKeys, []byte(privKey)) 50 } 51 52 // Write the accounts to disk into a single keystore. 53 accountsKeystore, err := km.CreateAccountsKeystore(ctx, privKeys, pubKeys) 54 if err != nil { 55 return err 56 } 57 encodedAccounts, err := json.MarshalIndent(accountsKeystore, "", "\t") 58 if err != nil { 59 return err 60 } 61 return km.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encodedAccounts) 62 } 63 64 // ImportKeypairs directly into the keymanager. 65 func (km *Keymanager) ImportKeypairs(ctx context.Context, privKeys, pubKeys [][]byte) error { 66 // Write the accounts to disk into a single keystore. 67 accountsKeystore, err := km.CreateAccountsKeystore(ctx, privKeys, pubKeys) 68 if err != nil { 69 return errors.Wrap(err, "could not import account keypairs") 70 } 71 encodedAccounts, err := json.MarshalIndent(accountsKeystore, "", "\t") 72 if err != nil { 73 return errors.Wrap(err, "could not marshal accounts keystore into JSON") 74 } 75 return km.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encodedAccounts) 76 } 77 78 // Retrieves the private key and public key from an EIP-2335 keystore file 79 // by decrypting using a specified password. If the password fails, 80 // it prompts the user for the correct password until it confirms. 81 func (km *Keymanager) attemptDecryptKeystore( 82 enc *keystorev4.Encryptor, keystore *keymanager.Keystore, password string, 83 ) ([]byte, []byte, string, error) { 84 // Attempt to decrypt the keystore with the specifies password. 85 var privKeyBytes []byte 86 var err error 87 privKeyBytes, err = enc.Decrypt(keystore.Crypto, password) 88 doesNotDecrypt := err != nil && strings.Contains(err.Error(), "invalid checksum") 89 for doesNotDecrypt { 90 password, err = promptutil.PasswordPrompt( 91 fmt.Sprintf("Password incorrect for key 0x%s, input correct password", keystore.Pubkey), promptutil.NotEmpty, 92 ) 93 if err != nil { 94 return nil, nil, "", fmt.Errorf("could not read keystore password: %w", err) 95 } 96 privKeyBytes, err = enc.Decrypt(keystore.Crypto, password) 97 doesNotDecrypt = err != nil && strings.Contains(err.Error(), "invalid checksum") 98 if err != nil && !strings.Contains(err.Error(), "invalid checksum") { 99 return nil, nil, "", errors.Wrap(err, "could not decrypt keystore") 100 } 101 } 102 if err != nil && !strings.Contains(err.Error(), "invalid checksum") { 103 return nil, nil, "", errors.Wrap(err, "could not decrypt keystore") 104 } 105 var pubKeyBytes []byte 106 // Attempt to use the pubkey present in the keystore itself as a field. If unavailable, 107 // then utilize the public key directly from the private key. 108 if keystore.Pubkey != "" { 109 pubKeyBytes, err = hex.DecodeString(keystore.Pubkey) 110 if err != nil { 111 return nil, nil, "", errors.Wrap(err, "could not decode pubkey from keystore") 112 } 113 } else { 114 privKey, err := bls.SecretKeyFromBytes(privKeyBytes) 115 if err != nil { 116 return nil, nil, "", errors.Wrap(err, "could not initialize private key from bytes") 117 } 118 pubKeyBytes = privKey.PublicKey().Marshal() 119 } 120 return privKeyBytes, pubKeyBytes, password, nil 121 } 122 123 func initializeProgressBar(numItems int, msg string) *progressbar.ProgressBar { 124 return progressbar.NewOptions( 125 numItems, 126 progressbar.OptionFullWidth(), 127 progressbar.OptionSetWriter(ansi.NewAnsiStdout()), 128 progressbar.OptionEnableColorCodes(true), 129 progressbar.OptionSetTheme(progressbar.Theme{ 130 Saucer: "[green]=[reset]", 131 SaucerHead: "[green]>[reset]", 132 SaucerPadding: " ", 133 BarStart: "[", 134 BarEnd: "]", 135 }), 136 progressbar.OptionOnCompletion(func() { fmt.Println() }), 137 progressbar.OptionSetDescription(msg), 138 ) 139 }