Resolve Web UI Beta Testing Bugs (#7471)

* more descriptive password validation error

* include change wallet password fixes

* balance and jwt improvements

* allow for different wallet dirs specified on startup

* ensure wallet password is always validated

* fix up prysm tests

* gaz

* test pass

* pass balances tests

* wrap up fixes

* radek feedback

* fix up tests

* cors fix

* add tests for validator status

* pass tests

* fix n

* skip content type test

* package level cache and send over feed

* package level cache for derived

* all tests passing

* gofmt

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
Raul Jordan
2020-10-09 21:07:28 -05:00
committed by GitHub
parent c4e64afd07
commit 551b03d6e6
35 changed files with 1255 additions and 1004 deletions

View File

@@ -79,6 +79,7 @@ go_test(
"//validator/accounts/v2/wallet:go_default_library",
"//validator/client:go_default_library",
"//validator/db/testing:go_default_library",
"//validator/flags:go_default_library",
"//validator/keymanager/v2:go_default_library",
"//validator/keymanager/v2/derived:go_default_library",
"//validator/keymanager/v2/direct:go_default_library",

View File

@@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"path/filepath"
"testing"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
@@ -17,10 +18,12 @@ import (
"github.com/prysmaticlabs/prysm/shared/testutil/require"
v2 "github.com/prysmaticlabs/prysm/validator/accounts/v2"
"github.com/prysmaticlabs/prysm/validator/accounts/v2/wallet"
"github.com/prysmaticlabs/prysm/validator/flags"
v2keymanager "github.com/prysmaticlabs/prysm/validator/keymanager/v2"
"github.com/prysmaticlabs/prysm/validator/keymanager/v2/derived"
)
var defaultWalletPath = filepath.Join(flags.DefaultValidatorDir(), flags.WalletDefaultDirName)
var _ accountCreator = (*mockAccountCreator)(nil)
type mockAccountCreator struct {

View File

@@ -22,30 +22,34 @@ import (
)
var (
tokenExpiryLength = 20 * time.Minute
tokenExpiryLength = time.Hour
hashCost = 8
)
// 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) {
walletDir := s.walletDir
if strings.TrimSpace(req.WalletDir) != "" {
walletDir = req.WalletDir
}
// First, we check if the validator already has a password. In this case,
// the user should NOT be able to signup and the function will return an error.
if fileutil.FileExists(filepath.Join(defaultWalletPath, wallet.HashedPasswordFileName)) {
return nil, status.Error(codes.PermissionDenied, "Validator already has a password set, cannot signup")
// the user should be logged in as normal.
if fileutil.FileExists(filepath.Join(walletDir, wallet.HashedPasswordFileName)) {
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 password input")
return nil, status.Error(codes.InvalidArgument, "Could not validate wallet password input")
}
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), hashCost)
if err != nil {
return nil, errors.Wrap(err, "could not generate hashed password")
}
hashFilePath := filepath.Join(defaultWalletPath, wallet.HashedPasswordFileName)
hashFilePath := filepath.Join(walletDir, wallet.HashedPasswordFileName)
// Write the config file to disk.
if err := os.MkdirAll(defaultWalletPath, os.ModePerm); err != nil {
if err := os.MkdirAll(walletDir, os.ModePerm); err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
if err := ioutil.WriteFile(hashFilePath, hashedPassword, params.BeaconIoConfig().ReadWritePermissions); err != nil {
@@ -56,19 +60,29 @@ func (s *Server) Signup(ctx context.Context, req *pb.AuthRequest) (*pb.AuthRespo
// Login to authenticate with the validator RPC API using a password.
func (s *Server) Login(ctx context.Context, req *pb.AuthRequest) (*pb.AuthResponse, error) {
hashedPasswordPath := filepath.Join(defaultWalletPath, wallet.HashedPasswordFileName)
if fileutil.FileExists(hashedPasswordPath) {
hashedPassword, err := fileutil.ReadFileAsBytes(hashedPasswordPath)
if err != nil {
return nil, status.Error(codes.Internal, "Could not retrieve hashed password from disk")
}
// 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")
}
walletDir := s.walletDir
if strings.TrimSpace(req.WalletDir) != "" {
walletDir = req.WalletDir
}
// 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")
}
hashedPasswordPath := filepath.Join(walletDir, wallet.HashedPasswordFileName)
if !fileutil.FileExists(hashedPasswordPath) {
return nil, status.Error(codes.Internal, "Could not find hashed password on disk")
}
hashedPassword, err := fileutil.ReadFileAsBytes(hashedPasswordPath)
if err != nil {
return nil, status.Error(codes.Internal, "Could not retrieve hashed password from disk")
}
// 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: defaultWalletPath,
WalletDir: walletDir,
WalletPassword: req.Password,
}); err != nil {
if strings.Contains(err.Error(), "invalid checksum") {
@@ -146,6 +160,15 @@ func (s *Server) initializeWallet(ctx context.Context, cfg *wallet.Config) error
}
s.keymanager = km
s.wallet = w
s.walletInitializedFeed.Send(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
}

View File

@@ -4,7 +4,6 @@ import (
"context"
"crypto/rand"
"fmt"
"io/ioutil"
"math/big"
"os"
"path/filepath"
@@ -13,7 +12,6 @@ import (
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/fileutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
@@ -34,32 +32,6 @@ func setupWalletDir(t testing.TB) string {
return walletDir
}
func TestServer_Signup_PasswordAlreadyExists(t *testing.T) {
valDB := dbtest.SetupDB(t, [][48]byte{})
ctx := context.Background()
ss := &Server{
valDB: valDB,
}
// Save a hash password preemptively to the database.
localWalletDir := setupWalletDir(t)
defaultWalletPath = localWalletDir
hashedPassword := []byte("2093402934902839489238492")
require.NoError(t, ioutil.WriteFile(
filepath.Join(defaultWalletPath, wallet.HashedPasswordFileName),
hashedPassword,
params.BeaconIoConfig().ReadWritePermissions,
))
// Attempt to signup despite already having a hashed password in the DB
// which should immediately fail.
strongPass := "29384283xasjasd32%%&*@*#*"
_, err := ss.Signup(ctx, &pb.AuthRequest{
Password: strongPass,
})
require.ErrorContains(t, "Validator already has a password set, cannot signup", err)
}
func TestServer_SignupAndLogin_RoundTrip(t *testing.T) {
valDB := dbtest.SetupDB(t, [][48]byte{})
ctx := context.Background()
@@ -71,12 +43,13 @@ func TestServer_SignupAndLogin_RoundTrip(t *testing.T) {
ss := &Server{
valDB: valDB,
walletInitializedFeed: new(event.Feed),
walletDir: defaultWalletPath,
}
weakPass := "password"
_, err := ss.Signup(ctx, &pb.AuthRequest{
Password: weakPass,
})
require.ErrorContains(t, "Could not validate password input", err)
require.ErrorContains(t, "Could not validate wallet password input", err)
// We assert we are able to signup with a strong password.
_, err = ss.Signup(ctx, &pb.AuthRequest{

View File

@@ -6,7 +6,6 @@ import (
"sync"
"github.com/dgrijalva/jwt-go"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
@@ -17,10 +16,11 @@ import (
// authentication from our API.
var (
noAuthPaths = map[string]bool{
"/ethereum.validator.accounts.v2.Auth/Signup": true,
"/ethereum.validator.accounts.v2.Auth/Login": true,
"/ethereum.validator.accounts.v2.Wallet/HasWallet": true,
"/ethereum.validator.accounts.v2.Wallet/GenerateMnemonic": true,
"/ethereum.validator.accounts.v2.Auth/Signup": true,
"/ethereum.validator.accounts.v2.Auth/Login": true,
"/ethereum.validator.accounts.v2.Wallet/HasWallet": true,
"/ethereum.validator.accounts.v2.Wallet/GenerateMnemonic": true,
"/ethereum.validator.accounts.v2.Wallet/DefaultWalletPath": true,
}
authLock sync.RWMutex
)
@@ -70,7 +70,7 @@ func (s *Server) authorize(ctx context.Context) error {
token := strings.Split(authHeader[0], "Bearer ")[1]
_, err := jwt.Parse(token, checkParsedKey)
if err != nil {
return errors.Wrap(err, "Could not parse JWT token")
return status.Errorf(codes.Unauthenticated, "Could not parse JWT token: %v", err)
}
return nil
}

View File

@@ -37,6 +37,7 @@ type Config struct {
CertFlag string
KeyFlag string
ValDB db.Database
WalletDir string
ValidatorService *client.ValidatorService
SyncChecker client.SyncChecker
GenesisFetcher client.GenesisFetcher
@@ -61,6 +62,7 @@ type Server struct {
validatorService *client.ValidatorService
syncChecker client.SyncChecker
genesisFetcher client.GenesisFetcher
walletDir string
wallet *v2.Wallet
walletInitializedFeed *event.Feed
walletInitialized bool
@@ -81,6 +83,7 @@ func NewServer(ctx context.Context, cfg *Config) *Server {
validatorService: cfg.ValidatorService,
syncChecker: cfg.SyncChecker,
genesisFetcher: cfg.GenesisFetcher,
walletDir: cfg.WalletDir,
walletInitializedFeed: cfg.WalletInitializedFeed,
walletInitialized: false,
nodeGatewayEndpoint: cfg.NodeGatewayEndpoint,

View File

@@ -6,9 +6,12 @@ import (
"encoding/json"
"io/ioutil"
"path/filepath"
"strings"
ptypes "github.com/gogo/protobuf/types"
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"
v2 "github.com/prysmaticlabs/prysm/validator/accounts/v2"
"github.com/prysmaticlabs/prysm/validator/accounts/v2/wallet"
@@ -17,12 +20,11 @@ import (
"github.com/prysmaticlabs/prysm/validator/keymanager/v2/derived"
"github.com/prysmaticlabs/prysm/validator/keymanager/v2/direct"
"github.com/tyler-smith/go-bip39"
"golang.org/x/crypto/bcrypt"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var defaultWalletPath = filepath.Join(flags.DefaultValidatorDir(), flags.WalletDefaultDirName)
const (
checkExistsErrMsg = "Could not check if wallet exists"
checkValidityErrMsg = "Could not check if wallet is valid"
@@ -33,7 +35,7 @@ const (
// HasWallet checks if a user has created a wallet before as well as whether or not
// they have used the web UI before to set a wallet password.
func (s *Server) HasWallet(ctx context.Context, _ *ptypes.Empty) (*pb.HasWalletResponse, error) {
exists, err := wallet.Exists(defaultWalletPath)
exists, err := wallet.Exists(s.walletDir)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if wallet exists: %v", err)
}
@@ -47,35 +49,50 @@ func (s *Server) HasWallet(ctx context.Context, _ *ptypes.Empty) (*pb.HasWalletR
}, nil
}
// DefaultWalletPath for the user, which is dependent on operating system.
func (s *Server) DefaultWalletPath(ctx context.Context, _ *ptypes.Empty) (*pb.DefaultWalletResponse, error) {
return &pb.DefaultWalletResponse{
WalletDir: filepath.Join(flags.DefaultValidatorDir(), flags.WalletDefaultDirName),
}, nil
}
// CreateWallet via an API request, allowing a user to save a new
// derived, direct, or remote wallet.
func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest) (*pb.CreateWalletResponse, error) {
// Currently defaultWalletPath is used as the wallet directory and req's WalletPath is ignored for simplicity
exists, err := wallet.Exists(defaultWalletPath)
walletDir := s.walletDir
if strings.TrimSpace(req.WalletPath) != "" {
walletDir = req.WalletPath
}
exists, err := wallet.Exists(walletDir)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check for existing wallet: %v", err)
}
if exists {
return nil, status.Error(codes.AlreadyExists, "A wallet already exists at this location.")
if err := s.initializeWallet(ctx, &wallet.Config{
WalletDir: walletDir,
WalletPassword: req.WalletPassword,
}); err != nil {
return nil, err
}
keymanagerKind := pb.KeymanagerKind_DIRECT
switch s.wallet.KeymanagerKind() {
case v2keymanager.Derived:
keymanagerKind = pb.KeymanagerKind_DERIVED
case v2keymanager.Remote:
keymanagerKind = pb.KeymanagerKind_REMOTE
}
return &pb.CreateWalletResponse{
Wallet: &pb.WalletResponse{
WalletPath: walletDir,
KeymanagerKind: keymanagerKind,
},
}, nil
}
switch req.Keymanager {
case pb.KeymanagerKind_DIRECT:
// Needs to unmarshal the keystores from the requests.
if req.KeystoresImported == nil || len(req.KeystoresImported) < 1 {
return nil, status.Error(codes.InvalidArgument, "No keystores included for import")
}
keystores := make([]*v2keymanager.Keystore, len(req.KeystoresImported))
for i := 0; i < len(req.KeystoresImported); i++ {
encoded := req.KeystoresImported[i]
keystore := &v2keymanager.Keystore{}
if err := json.Unmarshal([]byte(encoded), &keystore); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Not a valid EIP-2335 keystore JSON file: %v", err)
}
keystores[i] = keystore
}
w, err := v2.CreateWalletWithKeymanager(ctx, &v2.CreateWalletConfig{
WalletCfg: &wallet.Config{
WalletDir: defaultWalletPath,
WalletDir: walletDir,
KeymanagerKind: v2keymanager.Direct,
WalletPassword: req.WalletPassword,
},
@@ -84,16 +101,11 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
if err != nil {
return nil, err
}
// Import the uploaded accounts.
if err := v2.ImportAccounts(ctx, &v2.ImportAccountsConfig{
Wallet: w,
Keystores: keystores,
AccountPassword: req.KeystoresPassword,
}); err != nil {
if err := w.SaveHashedPassword(ctx); err != nil {
return nil, err
}
if err := s.initializeWallet(ctx, &wallet.Config{
WalletDir: defaultWalletPath,
WalletDir: walletDir,
KeymanagerKind: v2keymanager.Direct,
WalletPassword: req.WalletPassword,
}); err != nil {
@@ -101,7 +113,7 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
}
return &pb.CreateWalletResponse{
Wallet: &pb.WalletResponse{
WalletPath: defaultWalletPath,
WalletPath: walletDir,
KeymanagerKind: pb.KeymanagerKind_DIRECT,
},
}, nil
@@ -113,7 +125,7 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
return nil, status.Error(codes.InvalidArgument, "Must include mnemonic in request")
}
_, depositData, err := v2.RecoverWallet(ctx, &v2.RecoverWalletConfig{
WalletDir: defaultWalletPath,
WalletDir: walletDir,
WalletPassword: req.WalletPassword,
Mnemonic: req.Mnemonic,
NumAccounts: int64(req.NumAccounts),
@@ -122,7 +134,7 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
return nil, err
}
if err := s.initializeWallet(ctx, &wallet.Config{
WalletDir: defaultWalletPath,
WalletDir: walletDir,
KeymanagerKind: v2keymanager.Direct,
WalletPassword: req.WalletPassword,
}); err != nil {
@@ -141,7 +153,7 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
}
return &pb.CreateWalletResponse{
Wallet: &pb.WalletResponse{
WalletPath: defaultWalletPath,
WalletPath: walletDir,
KeymanagerKind: pb.KeymanagerKind_DERIVED,
},
AccountsCreated: &pb.DepositDataResponse{
@@ -162,7 +174,7 @@ func (s *Server) EditConfig(ctx context.Context, req *pb.EditWalletConfigRequest
// WalletConfig returns the wallet's configuration. If no wallet exists, we return an empty response.
func (s *Server) WalletConfig(ctx context.Context, _ *ptypes.Empty) (*pb.WalletResponse, error) {
exists, err := wallet.Exists(defaultWalletPath)
exists, err := wallet.Exists(s.walletDir)
if err != nil {
return nil, status.Errorf(codes.Internal, checkExistsErrMsg)
}
@@ -170,7 +182,7 @@ func (s *Server) WalletConfig(ctx context.Context, _ *ptypes.Empty) (*pb.WalletR
// If no wallet is found, we simply return an empty response.
return &pb.WalletResponse{}, nil
}
valid, err := wallet.IsValid(defaultWalletPath)
valid, err := wallet.IsValid(s.walletDir)
if err == wallet.ErrNoWalletFound {
return &pb.WalletResponse{}, nil
}
@@ -207,7 +219,7 @@ func (s *Server) WalletConfig(ctx context.Context, _ *ptypes.Empty) (*pb.WalletR
return nil, status.Errorf(codes.Internal, "Could not JSON unmarshal keymanager config: %v", err)
}
return &pb.WalletResponse{
WalletPath: defaultWalletPath,
WalletPath: s.walletDir,
KeymanagerKind: keymanagerKind,
KeymanagerConfig: config,
}, nil
@@ -235,14 +247,14 @@ func (s *Server) GenerateMnemonic(ctx context.Context, _ *ptypes.Empty) (*pb.Gen
// 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(defaultWalletPath)
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(defaultWalletPath)
valid, err := wallet.IsValid(s.walletDir)
if err == wallet.ErrNoWalletFound {
return nil, status.Errorf(codes.FailedPrecondition, noWalletMsg)
}
@@ -252,12 +264,26 @@ func (s *Server) ChangePassword(ctx context.Context, req *pb.ChangePasswordReque
if !valid {
return nil, status.Errorf(codes.FailedPrecondition, invalidWalletMsg)
}
if req.Password == "" {
return nil, status.Error(codes.InvalidArgument, "Password cannot be empty")
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 v2keymanager.Direct:
km, ok := s.keymanager.(*direct.Keymanager)
@@ -297,7 +323,8 @@ func (s *Server) ImportKeystores(
if s.wallet == nil {
return nil, status.Error(codes.FailedPrecondition, "No wallet initialized")
}
if s.wallet.KeymanagerKind() != v2keymanager.Direct {
keymanager, ok := s.keymanager.(*direct.Keymanager)
if !ok {
return nil, status.Error(codes.FailedPrecondition, "Only Non-HD wallets can import keystores")
}
if req.KeystoresPassword == "" {
@@ -324,12 +351,13 @@ func (s *Server) ImportKeystores(
}
// Import the uploaded accounts.
if err := v2.ImportAccounts(ctx, &v2.ImportAccountsConfig{
Wallet: s.wallet,
Keymanager: keymanager,
Keystores: keystores,
AccountPassword: req.KeystoresPassword,
}); err != nil {
return nil, err
}
s.walletInitializedFeed.Send(s.wallet)
return &pb.ImportKeystoresResponse{
ImportedPublicKeys: importedPubKeys,
}, nil

View File

@@ -39,8 +39,10 @@ func createDirectWalletWithAccounts(t testing.TB, numAccounts int) (*Server, [][
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
require.NoError(t, err)
ss := &Server{
keymanager: km,
wallet: w,
keymanager: km,
wallet: w,
walletDir: defaultWalletPath,
walletInitializedFeed: new(event.Feed),
}
// First we import accounts into the wallet.
encryptor := keystorev4.New()
@@ -82,21 +84,29 @@ func TestServer_CreateWallet_Direct(t *testing.T) {
strongPass := "29384283xasjasd32%%&*@*#*"
s := &Server{
walletInitializedFeed: new(event.Feed),
walletDir: defaultWalletPath,
}
_, err := s.Signup(ctx, &pb.AuthRequest{
Password: strongPass,
WalletDir: defaultWalletPath,
})
require.NoError(t, err)
req := &pb.CreateWalletRequest{
WalletPath: localWalletDir,
Keymanager: pb.KeymanagerKind_DIRECT,
WalletPassword: strongPass,
KeystoresPassword: strongPass,
WalletPath: localWalletDir,
Keymanager: pb.KeymanagerKind_DIRECT,
WalletPassword: strongPass,
}
// We delete the directory at defaultWalletPath as CreateWallet will return an error if it tries to create a wallet
// where a directory already exists
require.NoError(t, os.RemoveAll(defaultWalletPath))
_, err := s.CreateWallet(ctx, req)
require.ErrorContains(t, "No keystores included for import", err)
req.KeystoresImported = []string{"badjson"}
_, err = s.CreateWallet(ctx, req)
require.NoError(t, err)
importReq := &pb.ImportKeystoresRequest{
KeystoresPassword: strongPass,
KeystoresImported: []string{"badjson"},
}
_, err = s.ImportKeystores(ctx, importReq)
require.ErrorContains(t, "Not a valid EIP-2335 keystore", err)
encryptor := keystorev4.New()
@@ -119,8 +129,8 @@ func TestServer_CreateWallet_Direct(t *testing.T) {
require.NoError(t, err)
keystores[i] = string(encodedFile)
}
req.KeystoresImported = keystores
_, err = s.CreateWallet(ctx, req)
importReq.KeystoresImported = keystores
_, err = s.ImportKeystores(ctx, importReq)
require.NoError(t, err)
}
@@ -154,10 +164,6 @@ func TestServer_CreateWallet_Derived(t *testing.T) {
_, err = s.CreateWallet(ctx, req)
require.NoError(t, err)
// Now trying to create a wallet where a previous wallet already exists. We expect an error.
_, err = s.CreateWallet(ctx, req)
require.ErrorContains(t, "wallet already exists at this location", err)
}
func TestServer_WalletConfig_NoWalletFound(t *testing.T) {
@@ -174,6 +180,7 @@ func TestServer_WalletConfig(t *testing.T) {
strongPass := "29384283xasjasd32%%&*@*#*"
s := &Server{
walletInitializedFeed: new(event.Feed),
walletDir: defaultWalletPath,
}
// We attempt to create the wallet.
w, err := v2.CreateWalletWithKeymanager(ctx, &v2.CreateWalletConfig{
@@ -210,9 +217,12 @@ func TestServer_ChangePassword_Preconditions(t *testing.T) {
defaultWalletPath = localWalletDir
ctx := context.Background()
strongPass := "29384283xasjasd32%%&*@*#*"
ss := &Server{}
ss := &Server{
walletDir: defaultWalletPath,
}
_, err := ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
Password: "",
CurrentPassword: strongPass,
Password: "",
})
assert.ErrorContains(t, noWalletMsg, err)
// We attempt to create the wallet.
@@ -231,10 +241,12 @@ func TestServer_ChangePassword_Preconditions(t *testing.T) {
ss.walletInitialized = true
ss.keymanager = km
_, err = ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
Password: "",
CurrentPassword: strongPass,
Password: "",
})
assert.ErrorContains(t, "cannot be empty", err)
assert.ErrorContains(t, "Could not validate wallet password", err)
_, err = ss.ChangePassword(ctx, &pb.ChangePasswordRequest{
CurrentPassword: strongPass,
Password: "abc",
PasswordConfirmation: "def",
})
@@ -245,6 +257,7 @@ func TestServer_ChangePassword_DirectKeymanager(t *testing.T) {
ss, _ := createDirectWalletWithAccounts(t, 1)
newPassword := "NewPassw0rdz%%%%pass"
_, err := ss.ChangePassword(context.Background(), &pb.ChangePasswordRequest{
CurrentPassword: ss.wallet.Password(),
Password: newPassword,
PasswordConfirmation: newPassword,
})
@@ -269,12 +282,15 @@ func TestServer_ChangePassword_DerivedKeymanager(t *testing.T) {
require.NoError(t, err)
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
require.NoError(t, err)
ss := &Server{}
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,
})
@@ -287,7 +303,9 @@ func TestServer_HasWallet(t *testing.T) {
defaultWalletPath = localWalletDir
ctx := context.Background()
strongPass := "29384283xasjasd32%%&*@*#*"
ss := &Server{}
ss := &Server{
walletDir: defaultWalletPath,
}
// First delete the created folder and check the response
require.NoError(t, os.RemoveAll(defaultWalletPath))
resp, err := ss.HasWallet(ctx, &ptypes.Empty{})
@@ -383,6 +401,7 @@ func TestServer_ImportKeystores_FailedPreconditions(t *testing.T) {
}
func TestServer_ImportKeystores_OK(t *testing.T) {
direct.ResetCaches()
localWalletDir := setupWalletDir(t)
defaultWalletPath = localWalletDir
ctx := context.Background()
@@ -400,8 +419,9 @@ func TestServer_ImportKeystores_OK(t *testing.T) {
km, err := w.InitializeKeymanager(ctx, true /* skip mnemonic confirm */)
require.NoError(t, err)
ss := &Server{
keymanager: km,
wallet: w,
keymanager: km,
wallet: w,
walletInitializedFeed: new(event.Feed),
}
// Create 3 keystores.