mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 07:58:22 -05:00
Use Password Specific to Web UI Instead of Wallet Password (#7569)
* use password specific to web UI * fix up a few more tests * tests passing * gaz * fix fmt
This commit is contained in:
@@ -186,7 +186,7 @@ func TestBackupAccounts_Noninteractive_Imported(t *testing.T) {
|
||||
backupPasswordFile: backupPasswordFile,
|
||||
backupDir: backupDir,
|
||||
})
|
||||
w, err := CreateWalletWithKeymanager(cliCtx.Context, &CreateWalletConfig{
|
||||
_, err = CreateWalletWithKeymanager(cliCtx.Context, &CreateWalletConfig{
|
||||
WalletCfg: &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
KeymanagerKind: keymanager.Imported,
|
||||
@@ -194,7 +194,6 @@ func TestBackupAccounts_Noninteractive_Imported(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(cliCtx.Context))
|
||||
|
||||
// We attempt to import accounts we wrote to the keys directory
|
||||
// into our newly created wallet.
|
||||
|
||||
@@ -59,7 +59,6 @@ func TestDeleteAccounts_Noninteractive(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(cliCtx.Context))
|
||||
|
||||
// We attempt to import accounts.
|
||||
require.NoError(t, ImportAccountsCli(cliCtx))
|
||||
|
||||
@@ -72,7 +72,7 @@ func TestExitAccountsCli_Ok(t *testing.T) {
|
||||
// Flag required for ExitAccounts to work.
|
||||
voluntaryExitPublicKeys: keystore.Pubkey,
|
||||
})
|
||||
w, err := CreateWalletWithKeymanager(cliCtx.Context, &CreateWalletConfig{
|
||||
_, err = CreateWalletWithKeymanager(cliCtx.Context, &CreateWalletConfig{
|
||||
WalletCfg: &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
KeymanagerKind: keymanager.Imported,
|
||||
@@ -80,7 +80,6 @@ func TestExitAccountsCli_Ok(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(cliCtx.Context))
|
||||
require.NoError(t, ImportAccountsCli(cliCtx))
|
||||
|
||||
validatingPublicKeys, keymanager, err := prepareWallet(cliCtx)
|
||||
@@ -128,5 +127,5 @@ func TestPrepareWallet_EmptyWalletReturnsError(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, _, err = prepareWallet(cliCtx)
|
||||
assert.ErrorContains(t, "please recreate your wallet", err)
|
||||
assert.ErrorContains(t, "wallet is empty", err)
|
||||
}
|
||||
|
||||
@@ -90,10 +90,6 @@ func ImportAccountsCli(cliCtx *cli.Context) error {
|
||||
if err = createImportedKeymanagerWallet(cliCtx.Context, w); err != nil {
|
||||
return nil, errors.Wrap(err, "could not create keymanager")
|
||||
}
|
||||
// We store the hashed password to disk.
|
||||
if err := w.SaveHashedPassword(cliCtx.Context); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.WithField("wallet-path", cfg.WalletCfg.WalletDir).Info(
|
||||
"Successfully created new wallet",
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -54,7 +53,6 @@ func TestImport_Noninteractive(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(context.Background()))
|
||||
keymanager, err := imported.NewKeymanager(
|
||||
cliCtx.Context,
|
||||
&imported.SetupConfig{
|
||||
@@ -116,7 +114,6 @@ func TestImport_Noninteractive_RandomName(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(context.Background()))
|
||||
keymanager, err := imported.NewKeymanager(
|
||||
cliCtx.Context,
|
||||
&imported.SetupConfig{
|
||||
@@ -179,7 +176,6 @@ func TestImport_Noninteractive_Filepath(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(context.Background()))
|
||||
keymanager, err := imported.NewKeymanager(
|
||||
cliCtx.Context,
|
||||
&imported.SetupConfig{
|
||||
@@ -306,7 +302,6 @@ func Test_importPrivateKeyAsAccount(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, wallet.SaveHashedPassword(context.Background()))
|
||||
keymanager, err := imported.NewKeymanager(
|
||||
cliCtx.Context,
|
||||
&imported.SetupConfig{
|
||||
|
||||
@@ -14,7 +14,6 @@ type Wallet interface {
|
||||
// Methods to retrieve wallet and accounts metadata.
|
||||
AccountsDir() string
|
||||
Password() string
|
||||
SetPassword(newPass string)
|
||||
// Read methods for important wallet and accounts-related files.
|
||||
ReadEncryptedSeedFromDisk(ctx context.Context) (io.ReadCloser, error)
|
||||
ReadFileAtPath(ctx context.Context, filePath string, fileName string) ([]byte, error)
|
||||
|
||||
@@ -50,11 +50,6 @@ func (m *Wallet) Password() string {
|
||||
return m.WalletPassword
|
||||
}
|
||||
|
||||
// SetPassword sets a new password for the wallet.
|
||||
func (m *Wallet) SetPassword(newPass string) {
|
||||
m.WalletPassword = newPass
|
||||
}
|
||||
|
||||
// WriteFileAtPath --
|
||||
func (m *Wallet) WriteFileAtPath(_ context.Context, pathName, fileName string, data []byte) error {
|
||||
m.lock.Lock()
|
||||
|
||||
@@ -20,7 +20,6 @@ go_library(
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
"@org_golang_x_crypto//bcrypt:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager/remote"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var log = logrus.WithField("prefix", "wallet")
|
||||
@@ -30,8 +29,6 @@ var log = logrus.WithField("prefix", "wallet")
|
||||
const (
|
||||
// KeymanagerConfigFileName for the keymanager used by the wallet: imported, derived, or remote.
|
||||
KeymanagerConfigFileName = "keymanageropts.json"
|
||||
// HashedPasswordFileName for the wallet.
|
||||
HashedPasswordFileName = "hash"
|
||||
// DirectoryPermissions for directories created under the wallet path.
|
||||
DirectoryPermissions = os.ModePerm
|
||||
// NewWalletPasswordPromptText for wallet creation.
|
||||
@@ -192,16 +189,6 @@ func OpenWalletOrElseCli(cliCtx *cli.Context, otherwise func(cliCtx *cli.Context
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fileutil.FileExists(filepath.Join(walletDir, HashedPasswordFileName)) {
|
||||
hashedPassword, err := fileutil.ReadFileAsBytes(filepath.Join(walletDir, HashedPasswordFileName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Compare the wallet password here.
|
||||
if err := bcrypt.CompareHashAndPassword(hashedPassword, []byte(walletPassword)); err != nil {
|
||||
return nil, errors.Wrap(err, "wrong password for wallet")
|
||||
}
|
||||
}
|
||||
return OpenWallet(cliCtx.Context, &Config{
|
||||
WalletDir: walletDir,
|
||||
WalletPassword: walletPassword,
|
||||
@@ -267,11 +254,6 @@ func (w *Wallet) Password() string {
|
||||
return w.walletPassword
|
||||
}
|
||||
|
||||
// SetPassword sets a new password for the wallet.
|
||||
func (w *Wallet) SetPassword(newPass string) {
|
||||
w.walletPassword = newPass
|
||||
}
|
||||
|
||||
// InitializeKeymanager reads a keymanager config from disk at the wallet path,
|
||||
// unmarshals it based on the wallet's keymanager kind, and returns its value.
|
||||
func (w *Wallet) InitializeKeymanager(
|
||||
@@ -296,18 +278,6 @@ func (w *Wallet) InitializeKeymanager(
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not initialize imported keymanager")
|
||||
}
|
||||
if !fileutil.FileExists(filepath.Join(w.walletDir, HashedPasswordFileName)) {
|
||||
keys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return nil, errors.New("please recreate your wallet with wallet create")
|
||||
}
|
||||
if err := w.SaveHashedPassword(ctx); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save hashed password to disk")
|
||||
}
|
||||
}
|
||||
case keymanager.Derived:
|
||||
opts, err := derived.UnmarshalOptionsFile(configFile)
|
||||
if err != nil {
|
||||
@@ -321,11 +291,6 @@ func (w *Wallet) InitializeKeymanager(
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not initialize derived keymanager")
|
||||
}
|
||||
if !fileutil.FileExists(filepath.Join(w.walletDir, HashedPasswordFileName)) {
|
||||
if err := w.SaveHashedPassword(ctx); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save hashed password to disk")
|
||||
}
|
||||
}
|
||||
case keymanager.Remote:
|
||||
opts, err := remote.UnmarshalOptionsFile(configFile)
|
||||
if err != nil {
|
||||
@@ -471,20 +436,6 @@ func (w *Wallet) WriteEncryptedSeedToDisk(_ context.Context, encoded []byte) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveHashedPassword to disk for the wallet.
|
||||
func (w *Wallet) SaveHashedPassword(_ context.Context) error {
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(w.walletPassword), hashCost)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not generate hashed password")
|
||||
}
|
||||
hashFilePath := filepath.Join(w.walletDir, HashedPasswordFileName)
|
||||
// Write the config file to disk.
|
||||
if err := ioutil.WriteFile(hashFilePath, hashedPassword, params.BeaconIoConfig().ReadWritePermissions); err != nil {
|
||||
return errors.Wrap(err, "could not write hashed password for wallet to disk")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readKeymanagerKindFromWalletPath(walletPath string) (keymanager.Kind, error) {
|
||||
walletItem, err := os.Open(walletPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -51,10 +51,6 @@ func CreateAndSaveWalletCli(cliCtx *cli.Context) (*wallet.Wallet, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create wallet with keymanager")
|
||||
}
|
||||
// We store the hashed password to disk.
|
||||
if err := w.SaveHashedPassword(cliCtx.Context); err != nil {
|
||||
return nil, errors.Wrap(err, "could not save hashed password to database")
|
||||
}
|
||||
return w, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func RecoverWalletCli(cliCtx *cli.Context) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not get number of accounts to recover")
|
||||
}
|
||||
w, _, err := RecoverWallet(cliCtx.Context, &RecoverWalletConfig{
|
||||
_, _, err = RecoverWallet(cliCtx.Context, &RecoverWalletConfig{
|
||||
WalletDir: walletDir,
|
||||
WalletPassword: walletPassword,
|
||||
Mnemonic: mnemonic,
|
||||
@@ -67,10 +67,6 @@ func RecoverWalletCli(cliCtx *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// We store the hashed password to disk.
|
||||
if err := w.SaveHashedPassword(cliCtx.Context); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof(
|
||||
"Successfully recovered HD wallet and saved configuration to disk. " +
|
||||
"Make a new validator account with ./prysm.sh validator accounts create",
|
||||
|
||||
@@ -90,6 +90,9 @@ func (v *validator) WaitForWalletInitialization(ctx context.Context) error {
|
||||
if !v.useWeb {
|
||||
return nil
|
||||
}
|
||||
if v.keyManager != nil {
|
||||
return nil
|
||||
}
|
||||
walletChan := make(chan *wallet.Wallet)
|
||||
sub := v.walletInitializedFeed.Subscribe(walletChan)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
@@ -432,12 +432,6 @@ func (dr *Keymanager) DepositDataForAccount(accountIndex uint64) ([]byte, error)
|
||||
return tx.Data(), nil
|
||||
}
|
||||
|
||||
// RefreshWalletPassword encrypts the seed config with the wallet password and
|
||||
// writes it to disk, such as when the wallet password was modified by the user.
|
||||
func (dr *Keymanager) RefreshWalletPassword(ctx context.Context) error {
|
||||
return dr.rewriteSeedConfig(ctx)
|
||||
}
|
||||
|
||||
func (dr *Keymanager) rewriteSeedConfig(ctx context.Context) error {
|
||||
encryptor := keystorev4.New()
|
||||
encryptedFields, err := encryptor.Encrypt(dr.seed, dr.wallet.Password())
|
||||
|
||||
@@ -270,47 +270,3 @@ func TestDerivedKeymanager_Sign_NoPublicKeyInCache(t *testing.T) {
|
||||
_, err := dr.Sign(context.Background(), req)
|
||||
assert.ErrorContains(t, "no signing key found", err)
|
||||
}
|
||||
|
||||
func TestDerivedKeymanager_RefreshWalletPassword(t *testing.T) {
|
||||
password := "secretPassw0rd$1999"
|
||||
wallet := &mock.Wallet{
|
||||
Files: make(map[string]map[string][]byte),
|
||||
AccountPasswords: make(map[string]string),
|
||||
WalletPassword: password,
|
||||
}
|
||||
dr := &Keymanager{
|
||||
wallet: wallet,
|
||||
opts: DefaultKeymanagerOpts(),
|
||||
}
|
||||
seedCfg, err := initializeWalletSeedFile(wallet.Password(), true /* skip mnemonic confirm */)
|
||||
require.NoError(t, err)
|
||||
dr.seedCfg = seedCfg
|
||||
decryptor := keystorev4.New()
|
||||
seed, err := decryptor.Decrypt(dr.seedCfg.Crypto, wallet.Password())
|
||||
require.NoError(t, err)
|
||||
dr.seed = seed
|
||||
require.NoError(t, dr.initializeKeysCachesFromSeed())
|
||||
|
||||
// First, generate some accounts.
|
||||
numAccounts := 2
|
||||
ctx := context.Background()
|
||||
for i := 0; i < numAccounts; i++ {
|
||||
_, _, err := dr.CreateAccount(ctx)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// We attempt to decrypt with the wallet password and expect no error.
|
||||
_, err = decryptor.Decrypt(dr.seedCfg.Crypto, dr.wallet.Password())
|
||||
require.NoError(t, err)
|
||||
|
||||
// We change the wallet password.
|
||||
wallet.WalletPassword = "NewPassw0rdz9**#"
|
||||
// Attempting to decrypt with this new wallet password should fail.
|
||||
_, err = decryptor.Decrypt(dr.seedCfg.Crypto, dr.wallet.Password())
|
||||
require.ErrorContains(t, "invalid checksum", err)
|
||||
|
||||
// Call the refresh wallet password method, then attempting to decrypt should work.
|
||||
require.NoError(t, dr.RefreshWalletPassword(ctx))
|
||||
_, err = decryptor.Decrypt(dr.seedCfg.Crypto, dr.wallet.Password())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -311,12 +311,6 @@ func (dr *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (b
|
||||
return secretKey.Sign(req.SigningRoot), nil
|
||||
}
|
||||
|
||||
// RefreshWalletPassword re-encrypts the accounts store and stores
|
||||
// it to disk using a wallet's password which was recently changed.
|
||||
func (dr *Keymanager) RefreshWalletPassword(ctx context.Context) error {
|
||||
return dr.rewriteAccountsKeystore(ctx)
|
||||
}
|
||||
|
||||
func (dr *Keymanager) rewriteAccountsKeystore(ctx context.Context) error {
|
||||
newStore, err := dr.createAccountsKeystore(ctx, dr.accountsStore.PrivateKeys, dr.accountsStore.PublicKeys)
|
||||
if err != nil {
|
||||
|
||||
@@ -218,56 +218,3 @@ func TestImportedKeymanager_Sign_NoPublicKeyInCache(t *testing.T) {
|
||||
_, err := dr.Sign(context.Background(), req)
|
||||
assert.ErrorContains(t, "no signing key found in keys cache", err)
|
||||
}
|
||||
|
||||
func TestImportedKeymanager_RefreshWalletPassword(t *testing.T) {
|
||||
password := "secretPassw0rd$1999"
|
||||
wallet := &mock.Wallet{
|
||||
Files: make(map[string]map[string][]byte),
|
||||
AccountPasswords: make(map[string]string),
|
||||
WalletPassword: password,
|
||||
}
|
||||
dr := &Keymanager{
|
||||
wallet: wallet,
|
||||
accountsStore: &AccountStore{},
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
numAccounts := 5
|
||||
keystores := make([]*keymanager.Keystore, numAccounts)
|
||||
for i := 0; i < numAccounts; i++ {
|
||||
keystores[i] = createRandomKeystore(t, password)
|
||||
}
|
||||
require.NoError(t, dr.ImportKeystores(ctx, keystores, password))
|
||||
|
||||
var encodedKeystore []byte
|
||||
for k, v := range wallet.Files[AccountsPath] {
|
||||
if strings.Contains(k, "keystore") {
|
||||
encodedKeystore = v
|
||||
}
|
||||
}
|
||||
keystoreFile := &keymanager.Keystore{}
|
||||
require.NoError(t, json.Unmarshal(encodedKeystore, keystoreFile))
|
||||
|
||||
// We attempt to decrypt with the wallet password and expect no error.
|
||||
decryptor := keystorev4.New()
|
||||
_, err := decryptor.Decrypt(keystoreFile.Crypto, dr.wallet.Password())
|
||||
require.NoError(t, err)
|
||||
|
||||
// We change the wallet password.
|
||||
wallet.WalletPassword = "NewPassw0rdz9**#"
|
||||
// Attempting to decrypt with this new wallet password should fail.
|
||||
_, err = decryptor.Decrypt(keystoreFile.Crypto, dr.wallet.Password())
|
||||
require.ErrorContains(t, "invalid checksum", err)
|
||||
|
||||
// Call the refresh wallet password method, then attempting to decrypt should work.
|
||||
require.NoError(t, dr.RefreshWalletPassword(ctx))
|
||||
for k, v := range wallet.Files[AccountsPath] {
|
||||
if strings.Contains(k, "keystore") {
|
||||
encodedKeystore = v
|
||||
}
|
||||
}
|
||||
keystoreFile = &keymanager.Keystore{}
|
||||
require.NoError(t, json.Unmarshal(encodedKeystore, keystoreFile))
|
||||
_, err = decryptor.Decrypt(keystoreFile.Crypto, dr.wallet.Password())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -263,6 +263,32 @@ func moveDb(cliCtx *cli.Context, accountsDir string) string {
|
||||
}
|
||||
|
||||
func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
var keyManager keymanager.IKeymanager
|
||||
var err error
|
||||
// Read the wallet from the specified path.
|
||||
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
|
||||
return nil, nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not open wallet")
|
||||
}
|
||||
if w != nil {
|
||||
s.wallet = w
|
||||
log.WithFields(logrus.Fields{
|
||||
"wallet": w.AccountsDir(),
|
||||
"keymanager-kind": w.KeymanagerKind().String(),
|
||||
}).Info("Opened validator wallet")
|
||||
keyManager, err = w.InitializeKeymanager(
|
||||
cliCtx.Context, false, /* skipMnemonicConfirm */
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not read keymanager for wallet")
|
||||
}
|
||||
if err := w.LockWalletConfigFile(cliCtx.Context); err != nil {
|
||||
log.Fatalf("Could not get a lock on wallet file. Please check if you have another validator instance running and using the same wallet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
clearFlag := cliCtx.Bool(cmd.ClearDB.Name)
|
||||
forceClearFlag := cliCtx.Bool(cmd.ForceClearDB.Name)
|
||||
dataDir := cliCtx.String(cmd.DataDirFlag.Name)
|
||||
@@ -297,7 +323,7 @@ func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := s.registerClientService(nil); err != nil {
|
||||
if err := s.registerClientService(keyManager); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.registerRPCService(cliCtx); err != nil {
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestNode_Builds(t *testing.T) {
|
||||
set.String("verbosity", "debug", "log verbosity")
|
||||
require.NoError(t, set.Set(flags.WalletPasswordFileFlag.Name, passwordFile))
|
||||
context := cli.NewContext(&app, set, nil)
|
||||
w, err := accounts.CreateWalletWithKeymanager(context.Context, &accounts.CreateWalletConfig{
|
||||
_, err := accounts.CreateWalletWithKeymanager(context.Context, &accounts.CreateWalletConfig{
|
||||
WalletCfg: &wallet.Config{
|
||||
WalletDir: dir,
|
||||
KeymanagerKind: keymanager.Imported,
|
||||
@@ -55,7 +55,6 @@ func TestNode_Builds(t *testing.T) {
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(context.Context))
|
||||
|
||||
valClient, err := NewValidatorClient(context)
|
||||
require.NoError(t, err, "Failed to create ValidatorClient")
|
||||
|
||||
@@ -213,7 +213,6 @@ func TestServer_DeleteAccounts_FailedPreconditions_WrongKeymanagerKind(t *testin
|
||||
SkipMnemonicConfirm: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(ctx))
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
require.NoError(t, err)
|
||||
ss := &Server{
|
||||
|
||||
@@ -9,13 +9,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"github.com/prysmaticlabs/prysm/shared/promptutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/timeutils"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -26,6 +26,11 @@ var (
|
||||
hashCost = 8
|
||||
)
|
||||
|
||||
const (
|
||||
// HashedRPCPassword for the validator RPC access.
|
||||
HashedRPCPassword = "rpc-password-hash"
|
||||
)
|
||||
|
||||
// Signup to authenticate access to the validator RPC API using bcrypt and
|
||||
// a sufficiently strong password check.
|
||||
func (s *Server) Signup(ctx context.Context, req *pb.AuthRequest) (*pb.AuthResponse, error) {
|
||||
@@ -35,25 +40,26 @@ func (s *Server) Signup(ctx context.Context, req *pb.AuthRequest) (*pb.AuthRespo
|
||||
}
|
||||
// First, we check if the validator already has a password. In this case,
|
||||
// the user should be logged in as normal.
|
||||
if fileutil.FileExists(filepath.Join(walletDir, wallet.HashedPasswordFileName)) {
|
||||
if fileutil.FileExists(filepath.Join(walletDir, HashedRPCPassword)) {
|
||||
return s.Login(ctx, req)
|
||||
}
|
||||
// We check the strength of the password to ensure it is high-entropy,
|
||||
// has the required character count, and contains only unicode characters.
|
||||
if err := promptutil.ValidatePasswordInput(req.Password); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Could not validate wallet password input")
|
||||
return nil, status.Error(codes.InvalidArgument, "Could not validate RPC password input")
|
||||
}
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), hashCost)
|
||||
hasDir, err := fileutil.HasDir(walletDir)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not generate hashed password")
|
||||
return nil, status.Error(codes.FailedPrecondition, "Could not check if wallet directory exists")
|
||||
}
|
||||
hashFilePath := filepath.Join(walletDir, wallet.HashedPasswordFileName)
|
||||
// Write the config file to disk.
|
||||
if err := os.MkdirAll(walletDir, os.ModePerm); err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
if !hasDir {
|
||||
if err := os.MkdirAll(walletDir, params.BeaconIoConfig().ReadWritePermissions); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "could not write directory %s to disk: %v", walletDir, err)
|
||||
}
|
||||
}
|
||||
if err := ioutil.WriteFile(hashFilePath, hashedPassword, params.BeaconIoConfig().ReadWritePermissions); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "could not write hashed password for wallet to disk: %v", err)
|
||||
// Write the password hash to disk.
|
||||
if err := s.SaveHashedPassword(req.Password); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "could not write hashed password to disk: %v", err)
|
||||
}
|
||||
return s.sendAuthResponse()
|
||||
}
|
||||
@@ -67,9 +73,9 @@ func (s *Server) Login(ctx context.Context, req *pb.AuthRequest) (*pb.AuthRespon
|
||||
// We check the strength of the password to ensure it is high-entropy,
|
||||
// has the required character count, and contains only unicode characters.
|
||||
if err := promptutil.ValidatePasswordInput(req.Password); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Could not validate wallet password input")
|
||||
return nil, status.Error(codes.InvalidArgument, "Could not validate RPC password input")
|
||||
}
|
||||
hashedPasswordPath := filepath.Join(walletDir, wallet.HashedPasswordFileName)
|
||||
hashedPasswordPath := filepath.Join(walletDir, HashedRPCPassword)
|
||||
if !fileutil.FileExists(hashedPasswordPath) {
|
||||
return nil, status.Error(codes.Internal, "Could not find hashed password on disk")
|
||||
}
|
||||
@@ -79,16 +85,7 @@ func (s *Server) Login(ctx context.Context, req *pb.AuthRequest) (*pb.AuthRespon
|
||||
}
|
||||
// Compare the stored hashed password, with the hashed version of the password that was received.
|
||||
if err := bcrypt.CompareHashAndPassword(hashedPassword, []byte(req.Password)); err != nil {
|
||||
return nil, status.Error(codes.Unauthenticated, "Incorrect password")
|
||||
}
|
||||
if err := s.initializeWallet(ctx, &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
WalletPassword: req.Password,
|
||||
}); err != nil {
|
||||
if strings.Contains(err.Error(), "invalid checksum") {
|
||||
return nil, status.Error(codes.Unauthenticated, "Incorrect password")
|
||||
}
|
||||
return nil, status.Errorf(codes.Internal, "Could not initialize wallet: %v", err)
|
||||
return nil, status.Error(codes.Unauthenticated, "Incorrect validator RPC password")
|
||||
}
|
||||
return s.sendAuthResponse()
|
||||
}
|
||||
@@ -106,6 +103,35 @@ func (s *Server) sendAuthResponse() (*pb.AuthResponse, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ChangePassword allows changing the RPC password via the API as an authenticated method.
|
||||
func (s *Server) ChangePassword(ctx context.Context, req *pb.ChangePasswordRequest) (*ptypes.Empty, error) {
|
||||
if req.CurrentPassword == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "Current password cannot be empty")
|
||||
}
|
||||
hashedPasswordPath := filepath.Join(s.walletDir, HashedRPCPassword)
|
||||
if !fileutil.FileExists(hashedPasswordPath) {
|
||||
return nil, status.Error(codes.FailedPrecondition, "Could not compare password from disk")
|
||||
}
|
||||
hashedPassword, err := fileutil.ReadFileAsBytes(hashedPasswordPath)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.FailedPrecondition, "Could not retrieve hashed password from disk")
|
||||
}
|
||||
if err := bcrypt.CompareHashAndPassword(hashedPassword, []byte(req.CurrentPassword)); err != nil {
|
||||
return nil, status.Error(codes.Unauthenticated, "Incorrect password")
|
||||
}
|
||||
if req.Password != req.PasswordConfirmation {
|
||||
return nil, status.Error(codes.InvalidArgument, "Password does not match confirmation")
|
||||
}
|
||||
if err := promptutil.ValidatePasswordInput(req.Password); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Could not validate password input")
|
||||
}
|
||||
// Write the new password hash to disk.
|
||||
if err := s.SaveHashedPassword(req.Password); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "could not write hashed password to disk: %v", err)
|
||||
}
|
||||
return &ptypes.Empty{}, nil
|
||||
}
|
||||
|
||||
// Creates a JWT token string using the JWT key with an expiration timestamp.
|
||||
func (s *Server) createTokenString() (string, uint64, error) {
|
||||
// Create a new token object, specifying signing method and the claims
|
||||
@@ -122,53 +148,12 @@ func (s *Server) createTokenString() (string, uint64, error) {
|
||||
return tokenString, uint64(expirationTime.Unix()), nil
|
||||
}
|
||||
|
||||
// Initialize a wallet and send it over a global feed.
|
||||
func (s *Server) initializeWallet(ctx context.Context, cfg *wallet.Config) error {
|
||||
// We first ensure the user has a wallet.
|
||||
exists, err := wallet.Exists(cfg.WalletDir)
|
||||
// SaveHashedPassword to disk for the validator RPC.
|
||||
func (s *Server) SaveHashedPassword(password string) error {
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), hashCost)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, wallet.CheckExistsErrMsg)
|
||||
return errors.Wrap(err, "could not generate hashed password")
|
||||
}
|
||||
if !exists {
|
||||
return wallet.ErrNoWalletFound
|
||||
}
|
||||
valid, err := wallet.IsValid(cfg.WalletDir)
|
||||
if errors.Is(err, wallet.ErrNoWalletFound) {
|
||||
return wallet.ErrNoWalletFound
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, wallet.CheckValidityErrMsg)
|
||||
}
|
||||
if !valid {
|
||||
return errors.New(wallet.InvalidWalletErrMsg)
|
||||
}
|
||||
|
||||
// We fire an event with the opened wallet over
|
||||
// a global feed signifying wallet initialization.
|
||||
w, err := wallet.OpenWallet(ctx, &wallet.Config{
|
||||
WalletDir: cfg.WalletDir,
|
||||
WalletPassword: cfg.WalletPassword,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not open wallet")
|
||||
}
|
||||
|
||||
s.walletInitialized = true
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize keymanager")
|
||||
}
|
||||
s.keymanager = km
|
||||
s.wallet = w
|
||||
s.walletDir = cfg.WalletDir
|
||||
|
||||
// Only send over feed if we have validating keys.
|
||||
validatingPublicKeys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check for validating public keys")
|
||||
}
|
||||
if len(validatingPublicKeys) > 0 {
|
||||
s.walletInitializedFeed.Send(w)
|
||||
}
|
||||
return nil
|
||||
hashFilePath := filepath.Join(s.walletDir, HashedRPCPassword)
|
||||
return ioutil.WriteFile(hashFilePath, hashedPassword, params.BeaconIoConfig().ReadWritePermissions)
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestServer_SignupAndLogin_RoundTrip(t *testing.T) {
|
||||
_, err := ss.Signup(ctx, &pb.AuthRequest{
|
||||
Password: weakPass,
|
||||
})
|
||||
require.ErrorContains(t, "Could not validate wallet password input", err)
|
||||
require.ErrorContains(t, "Could not validate RPC password input", err)
|
||||
|
||||
// We assert we are able to signup with a strong password.
|
||||
_, err = ss.Signup(ctx, &pb.AuthRequest{
|
||||
@@ -58,7 +58,7 @@ func TestServer_SignupAndLogin_RoundTrip(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Assert we stored the hashed password.
|
||||
passwordHashExists := fileutil.FileExists(filepath.Join(defaultWalletPath, wallet.HashedPasswordFileName))
|
||||
passwordHashExists := fileutil.FileExists(filepath.Join(defaultWalletPath, HashedRPCPassword))
|
||||
assert.Equal(t, true, passwordHashExists)
|
||||
|
||||
// We attempt to create the wallet.
|
||||
@@ -78,3 +78,47 @@ func TestServer_SignupAndLogin_RoundTrip(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestServer_ChangePassword_Preconditions(t *testing.T) {
|
||||
localWalletDir := setupWalletDir(t)
|
||||
defaultWalletPath = localWalletDir
|
||||
ctx := context.Background()
|
||||
strongPass := "29384283xasjasd32%%&*@*#*"
|
||||
ss := &Server{
|
||||
walletDir: defaultWalletPath,
|
||||
}
|
||||
require.NoError(t, ss.SaveHashedPassword(strongPass))
|
||||
_, err := ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
|
||||
CurrentPassword: strongPass,
|
||||
Password: "",
|
||||
})
|
||||
assert.ErrorContains(t, "Could not validate password input", err)
|
||||
_, err = ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
|
||||
CurrentPassword: strongPass,
|
||||
Password: "abc",
|
||||
PasswordConfirmation: "def",
|
||||
})
|
||||
assert.ErrorContains(t, "does not match", err)
|
||||
}
|
||||
|
||||
func TestServer_ChangePassword_OK(t *testing.T) {
|
||||
localWalletDir := setupWalletDir(t)
|
||||
defaultWalletPath = localWalletDir
|
||||
ss := &Server{
|
||||
walletDir: defaultWalletPath,
|
||||
}
|
||||
password := "Passw0rdz%%%%pass"
|
||||
newPassword := "NewPassw0rdz%%%%pass"
|
||||
ctx := context.Background()
|
||||
require.NoError(t, ss.SaveHashedPassword(password))
|
||||
_, err := ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
|
||||
CurrentPassword: password,
|
||||
Password: newPassword,
|
||||
PasswordConfirmation: newPassword,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = ss.Login(ctx, &pb.AuthRequest{
|
||||
Password: newPassword,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -4,23 +4,18 @@ import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
|
||||
"github.com/prysmaticlabs/prysm/shared/fileutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/promptutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/rand"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts"
|
||||
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager/derived"
|
||||
"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
|
||||
"github.com/tyler-smith/go-bip39"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -83,7 +78,7 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
|
||||
}
|
||||
switch req.Keymanager {
|
||||
case pb.KeymanagerKind_IMPORTED:
|
||||
w, err := accounts.CreateWalletWithKeymanager(ctx, &accounts.CreateWalletConfig{
|
||||
_, err := accounts.CreateWalletWithKeymanager(ctx, &accounts.CreateWalletConfig{
|
||||
WalletCfg: &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
KeymanagerKind: keymanager.Imported,
|
||||
@@ -94,9 +89,6 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := w.SaveHashedPassword(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.initializeWallet(ctx, &wallet.Config{
|
||||
WalletDir: walletDir,
|
||||
KeymanagerKind: keymanager.Imported,
|
||||
@@ -237,77 +229,6 @@ func (s *Server) GenerateMnemonic(_ context.Context, _ *ptypes.Empty) (*pb.Gener
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ChangePassword allows changing a wallet password via the API as
|
||||
// an authenticated method.
|
||||
func (s *Server) ChangePassword(ctx context.Context, req *pb.ChangePasswordRequest) (*ptypes.Empty, error) {
|
||||
exists, err := wallet.Exists(s.walletDir)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, checkExistsErrMsg)
|
||||
}
|
||||
if !exists {
|
||||
return nil, status.Errorf(codes.FailedPrecondition, noWalletMsg)
|
||||
}
|
||||
valid, err := wallet.IsValid(s.walletDir)
|
||||
if errors.Is(err, wallet.ErrNoWalletFound) {
|
||||
return nil, status.Errorf(codes.FailedPrecondition, noWalletMsg)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, checkValidityErrMsg)
|
||||
}
|
||||
if !valid {
|
||||
return nil, status.Errorf(codes.FailedPrecondition, invalidWalletMsg)
|
||||
}
|
||||
if req.CurrentPassword == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "Current wallet password cannot be empty")
|
||||
}
|
||||
hashedPasswordPath := filepath.Join(s.walletDir, wallet.HashedPasswordFileName)
|
||||
if !fileutil.FileExists(hashedPasswordPath) {
|
||||
return nil, status.Error(codes.FailedPrecondition, "Could not compare password from disk")
|
||||
}
|
||||
hashedPassword, err := fileutil.ReadFileAsBytes(hashedPasswordPath)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.FailedPrecondition, "Could not retrieve hashed password from disk")
|
||||
}
|
||||
if err := bcrypt.CompareHashAndPassword(hashedPassword, []byte(req.CurrentPassword)); err != nil {
|
||||
return nil, status.Error(codes.Unauthenticated, "Incorrect wallet password")
|
||||
}
|
||||
if req.Password != req.PasswordConfirmation {
|
||||
return nil, status.Error(codes.InvalidArgument, "Password does not match confirmation")
|
||||
}
|
||||
if err := promptutil.ValidatePasswordInput(req.Password); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Could not validate wallet password input")
|
||||
}
|
||||
switch s.wallet.KeymanagerKind() {
|
||||
case keymanager.Imported:
|
||||
km, ok := s.keymanager.(*imported.Keymanager)
|
||||
if !ok {
|
||||
return nil, status.Error(codes.FailedPrecondition, "Not a valid imported keymanager")
|
||||
}
|
||||
s.wallet.SetPassword(req.Password)
|
||||
if err := s.wallet.SaveHashedPassword(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not save hashed password: %v", err)
|
||||
}
|
||||
if err := km.RefreshWalletPassword(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not refresh wallet password: %v", err)
|
||||
}
|
||||
case keymanager.Derived:
|
||||
km, ok := s.keymanager.(*derived.Keymanager)
|
||||
if !ok {
|
||||
return nil, status.Error(codes.FailedPrecondition, "Not a valid derived keymanager")
|
||||
}
|
||||
s.wallet.SetPassword(req.Password)
|
||||
if err := s.wallet.SaveHashedPassword(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not save hashed password: %v", err)
|
||||
}
|
||||
if err := km.RefreshWalletPassword(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not refresh wallet password: %v", err)
|
||||
}
|
||||
case keymanager.Remote:
|
||||
return nil, status.Error(codes.Internal, "Cannot change password for remote keymanager")
|
||||
}
|
||||
return &ptypes.Empty{}, nil
|
||||
}
|
||||
|
||||
// ImportKeystores allows importing new keystores via RPC into the wallet
|
||||
// which will be decrypted using the specified password .
|
||||
func (s *Server) ImportKeystores(
|
||||
@@ -355,3 +276,54 @@ func (s *Server) ImportKeystores(
|
||||
ImportedPublicKeys: importedPubKeys,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Initialize a wallet and send it over a global feed.
|
||||
func (s *Server) initializeWallet(ctx context.Context, cfg *wallet.Config) error {
|
||||
// We first ensure the user has a wallet.
|
||||
exists, err := wallet.Exists(cfg.WalletDir)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, wallet.CheckExistsErrMsg)
|
||||
}
|
||||
if !exists {
|
||||
return wallet.ErrNoWalletFound
|
||||
}
|
||||
valid, err := wallet.IsValid(cfg.WalletDir)
|
||||
if errors.Is(err, wallet.ErrNoWalletFound) {
|
||||
return wallet.ErrNoWalletFound
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, wallet.CheckValidityErrMsg)
|
||||
}
|
||||
if !valid {
|
||||
return errors.New(wallet.InvalidWalletErrMsg)
|
||||
}
|
||||
|
||||
// We fire an event with the opened wallet over
|
||||
// a global feed signifying wallet initialization.
|
||||
w, err := wallet.OpenWallet(ctx, &wallet.Config{
|
||||
WalletDir: cfg.WalletDir,
|
||||
WalletPassword: cfg.WalletPassword,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not open wallet")
|
||||
}
|
||||
|
||||
s.walletInitialized = true
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize keymanager")
|
||||
}
|
||||
s.keymanager = km
|
||||
s.wallet = w
|
||||
s.walletDir = cfg.WalletDir
|
||||
|
||||
// Only send over feed if we have validating keys.
|
||||
validatingPublicKeys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not check for validating public keys")
|
||||
}
|
||||
if len(validatingPublicKeys) > 0 {
|
||||
s.walletInitializedFeed.Send(w)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ func createImportedWalletWithAccounts(t testing.TB, numAccounts int) (*Server, [
|
||||
SkipMnemonicConfirm: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(ctx))
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
require.NoError(t, err)
|
||||
ss := &Server{
|
||||
@@ -192,7 +191,6 @@ func TestServer_WalletConfig(t *testing.T) {
|
||||
SkipMnemonicConfirm: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(ctx))
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
require.NoError(t, err)
|
||||
s.wallet = w
|
||||
@@ -212,92 +210,6 @@ func TestServer_WalletConfig(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestServer_ChangePassword_Preconditions(t *testing.T) {
|
||||
localWalletDir := setupWalletDir(t)
|
||||
defaultWalletPath = localWalletDir
|
||||
ctx := context.Background()
|
||||
strongPass := "29384283xasjasd32%%&*@*#*"
|
||||
ss := &Server{
|
||||
walletDir: defaultWalletPath,
|
||||
}
|
||||
_, err := ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
|
||||
CurrentPassword: strongPass,
|
||||
Password: "",
|
||||
})
|
||||
assert.ErrorContains(t, noWalletMsg, err)
|
||||
// We attempt to create the wallet.
|
||||
w, err := accounts.CreateWalletWithKeymanager(ctx, &accounts.CreateWalletConfig{
|
||||
WalletCfg: &wallet.Config{
|
||||
WalletDir: defaultWalletPath,
|
||||
KeymanagerKind: keymanager.Derived,
|
||||
WalletPassword: strongPass,
|
||||
},
|
||||
SkipMnemonicConfirm: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
require.NoError(t, err)
|
||||
ss.wallet = w
|
||||
ss.walletInitialized = true
|
||||
ss.keymanager = km
|
||||
_, err = ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
|
||||
CurrentPassword: strongPass,
|
||||
Password: "",
|
||||
})
|
||||
assert.ErrorContains(t, "Could not validate wallet password", err)
|
||||
_, err = ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
|
||||
CurrentPassword: strongPass,
|
||||
Password: "abc",
|
||||
PasswordConfirmation: "def",
|
||||
})
|
||||
assert.ErrorContains(t, "does not match", err)
|
||||
}
|
||||
|
||||
func TestServer_ChangePassword_ImportedKeymanager(t *testing.T) {
|
||||
ss, _ := createImportedWalletWithAccounts(t, 1)
|
||||
newPassword := "NewPassw0rdz%%%%pass"
|
||||
_, err := ss.ChangePassword(context.Background(), &pb.ChangePasswordRequest{
|
||||
CurrentPassword: ss.wallet.Password(),
|
||||
Password: newPassword,
|
||||
PasswordConfirmation: newPassword,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, ss.wallet.Password(), newPassword)
|
||||
}
|
||||
|
||||
func TestServer_ChangePassword_DerivedKeymanager(t *testing.T) {
|
||||
localWalletDir := setupWalletDir(t)
|
||||
defaultWalletPath = localWalletDir
|
||||
ctx := context.Background()
|
||||
strongPass := "29384283xasjasd32%%&*@*#*"
|
||||
// We attempt to create the wallet.
|
||||
w, err := accounts.CreateWalletWithKeymanager(ctx, &accounts.CreateWalletConfig{
|
||||
WalletCfg: &wallet.Config{
|
||||
WalletDir: defaultWalletPath,
|
||||
KeymanagerKind: keymanager.Derived,
|
||||
WalletPassword: strongPass,
|
||||
},
|
||||
SkipMnemonicConfirm: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
require.NoError(t, err)
|
||||
ss := &Server{
|
||||
walletDir: defaultWalletPath,
|
||||
}
|
||||
ss.wallet = w
|
||||
ss.walletInitialized = true
|
||||
ss.keymanager = km
|
||||
newPassword := "NewPassw0rdz%%%%pass"
|
||||
_, err = ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
|
||||
CurrentPassword: strongPass,
|
||||
Password: newPassword,
|
||||
PasswordConfirmation: newPassword,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, w.Password(), newPassword)
|
||||
}
|
||||
|
||||
func TestServer_HasWallet(t *testing.T) {
|
||||
localWalletDir := setupWalletDir(t)
|
||||
defaultWalletPath = localWalletDir
|
||||
@@ -378,7 +290,6 @@ func TestServer_ImportKeystores_FailedPreconditions(t *testing.T) {
|
||||
SkipMnemonicConfirm: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(ctx))
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
require.NoError(t, err)
|
||||
ss := &Server{
|
||||
@@ -415,7 +326,6 @@ func TestServer_ImportKeystores_OK(t *testing.T) {
|
||||
SkipMnemonicConfirm: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.SaveHashedPassword(ctx))
|
||||
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
|
||||
require.NoError(t, err)
|
||||
ss := &Server{
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/shared"
|
||||
"github.com/prysmaticlabs/prysm/shared/browser"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -36,21 +35,13 @@ func NewServer(addr string) *Server {
|
||||
// Start the web server.
|
||||
func (s *Server) Start() {
|
||||
go func() {
|
||||
log.WithField("address", s.http.Addr).Info("Starting Prysm web UI")
|
||||
log.WithField("address", "http://"+s.http.Addr).Info(
|
||||
"Starting Prysm web UI on address, open in browser to access",
|
||||
)
|
||||
if err := s.http.ListenAndServe(); err != nil {
|
||||
log.WithError(err).Error("Failed to start validator web server")
|
||||
log.WithError(err).Error("Failed to run validator web server")
|
||||
}
|
||||
}()
|
||||
time.Sleep(time.Second * 1)
|
||||
cmd, err := browser.Command("http://" + s.http.Addr)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("Could not open Prysm web UI in browser")
|
||||
return
|
||||
}
|
||||
if err := cmd.Run(); err != nil {
|
||||
log.WithError(err).Errorf("Could not open Prysm web UI in browser")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the web server gracefully with 1s timeout.
|
||||
|
||||
Reference in New Issue
Block a user