mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
106 lines
3.4 KiB
Go
106 lines
3.4 KiB
Go
package direct
|
|
|
|
import (
|
|
"context"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/logrusorgru/aurora"
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/shared/roughtime"
|
|
v2keymanager "github.com/prysmaticlabs/prysm/validator/keymanager/v2"
|
|
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
|
|
)
|
|
|
|
// Migrates the old format for validator direct-keymanaged accounts into a new, more
|
|
// efficient format which stores only a single keystore all accounts, encrypted using
|
|
// a high-entropy password. This allows for incredibly fast startup-time, requiring only
|
|
// a single decryption operation to obtain all validator accounts. This migration process
|
|
// is meant to happen only once, ensuring all future restarts of the validator client utilize
|
|
// the fast, efficient format.
|
|
//
|
|
// Old format:
|
|
// wallet/
|
|
// direct/
|
|
// perfectly-intense-mosquito/
|
|
// keystore-2909299.json
|
|
// personally-conscious-echidna/
|
|
// keystore-20390922.json
|
|
// passwords/
|
|
// perfectly-intense-mosquito.pass
|
|
// personally-conscious-echidna.pass
|
|
//
|
|
// New format:
|
|
// wallet/
|
|
// direct/
|
|
// accounts/
|
|
// all-accounts.keystore-2983823.json
|
|
func (dr *Keymanager) migrateToSingleKeystore(ctx context.Context) error {
|
|
accountNames, err := dr.wallet.ListDirs()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(accountNames) == 0 {
|
|
return nil
|
|
}
|
|
for _, name := range accountNames {
|
|
// If the user is already using the single keystore format,
|
|
// we have no need to migrate and we exit normally.
|
|
if strings.Contains(name, AccountsPath) {
|
|
return nil
|
|
}
|
|
}
|
|
au := aurora.NewAurora(true)
|
|
log.Infof(
|
|
"Now migrating accounts to a more efficient format, this is a %s setup\n",
|
|
au.BrightRed("one-time"),
|
|
)
|
|
bar := initializeProgressBar(len(accountNames), "Migrating accounts...")
|
|
decryptor := keystorev4.New()
|
|
privKeys := make([][]byte, len(accountNames))
|
|
pubKeys := make([][]byte, len(accountNames))
|
|
// Next up, we retrieve every single keystore for each
|
|
// account and attempt to unlock.
|
|
for i, name := range accountNames {
|
|
password, err := dr.wallet.ReadPasswordFromDisk(ctx, name+PasswordFileSuffix)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not read password for account %s", name)
|
|
}
|
|
encoded, err := dr.wallet.ReadFileAtPath(ctx, name, KeystoreFileName)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not read keystore file for account %s", name)
|
|
}
|
|
keystoreFile := &v2keymanager.Keystore{}
|
|
if err := json.Unmarshal(encoded, keystoreFile); err != nil {
|
|
return errors.Wrapf(err, "could not decode keystore file for account %s", name)
|
|
}
|
|
// We extract the validator signing private key from the keystore
|
|
// by utilizing the password.
|
|
privKeyBytes, err := decryptor.Decrypt(keystoreFile.Crypto, password)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not decrypt signing key for account %s", name)
|
|
}
|
|
publicKeyBytes, err := hex.DecodeString(keystoreFile.Pubkey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
privKeys[i] = privKeyBytes
|
|
pubKeys[i] = publicKeyBytes
|
|
if err := bar.Add(1); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
accountsKeystore, err := dr.createAccountsKeystore(ctx, privKeys, pubKeys)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
encodedAccounts, err := json.MarshalIndent(accountsKeystore, "", "\t")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fileName := fmt.Sprintf(accountsKeystoreFileNameFormat, roughtime.Now().Unix())
|
|
return dr.wallet.WriteFileAtPath(ctx, AccountsPath, fileName, encodedAccounts)
|
|
}
|