package wallet_test import ( "flag" "io/ioutil" "os" "path/filepath" "strconv" "testing" "github.com/prysmaticlabs/prysm/shared/params" "github.com/prysmaticlabs/prysm/shared/testutil/assert" "github.com/prysmaticlabs/prysm/shared/testutil/assertions" "github.com/prysmaticlabs/prysm/shared/testutil/require" "github.com/prysmaticlabs/prysm/validator/accounts" "github.com/prysmaticlabs/prysm/validator/accounts/iface" "github.com/prysmaticlabs/prysm/validator/accounts/wallet" "github.com/prysmaticlabs/prysm/validator/flags" "github.com/prysmaticlabs/prysm/validator/keymanager" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) const ( passwordFileName = "password.txt" password = "OhWOWthisisatest42!$" ) func init() { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(ioutil.Discard) } type testWalletConfig struct { walletDir string passwordsDir string backupDir string keysDir string deletePublicKeys string voluntaryExitPublicKeys string backupPublicKeys string backupPasswordFile string walletPasswordFile string accountPasswordFile string privateKeyFile string skipDepositConfirm bool numAccounts int64 keymanagerKind keymanager.Kind } func setupWalletCtx( tb testing.TB, cfg *testWalletConfig, ) *cli.Context { app := cli.App{} set := flag.NewFlagSet("test", 0) set.String(flags.WalletDirFlag.Name, cfg.walletDir, "") set.String(flags.KeysDirFlag.Name, cfg.keysDir, "") set.String(flags.KeymanagerKindFlag.Name, cfg.keymanagerKind.String(), "") set.String(flags.DeletePublicKeysFlag.Name, cfg.deletePublicKeys, "") set.String(flags.VoluntaryExitPublicKeysFlag.Name, cfg.voluntaryExitPublicKeys, "") set.String(flags.BackupDirFlag.Name, cfg.backupDir, "") set.String(flags.BackupPasswordFile.Name, cfg.backupPasswordFile, "") set.String(flags.BackupPublicKeysFlag.Name, cfg.backupPublicKeys, "") set.String(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile, "") set.String(flags.AccountPasswordFileFlag.Name, cfg.accountPasswordFile, "") set.Int64(flags.NumAccountsFlag.Name, cfg.numAccounts, "") set.Bool(flags.SkipDepositConfirmationFlag.Name, cfg.skipDepositConfirm, "") if cfg.privateKeyFile != "" { set.String(flags.ImportPrivateKeyFileFlag.Name, cfg.privateKeyFile, "") assert.NoError(tb, set.Set(flags.ImportPrivateKeyFileFlag.Name, cfg.privateKeyFile)) } assert.NoError(tb, set.Set(flags.WalletDirFlag.Name, cfg.walletDir)) assert.NoError(tb, set.Set(flags.KeysDirFlag.Name, cfg.keysDir)) assert.NoError(tb, set.Set(flags.KeymanagerKindFlag.Name, cfg.keymanagerKind.String())) assert.NoError(tb, set.Set(flags.DeletePublicKeysFlag.Name, cfg.deletePublicKeys)) assert.NoError(tb, set.Set(flags.VoluntaryExitPublicKeysFlag.Name, cfg.voluntaryExitPublicKeys)) assert.NoError(tb, set.Set(flags.BackupDirFlag.Name, cfg.backupDir)) assert.NoError(tb, set.Set(flags.BackupPublicKeysFlag.Name, cfg.backupPublicKeys)) assert.NoError(tb, set.Set(flags.BackupPasswordFile.Name, cfg.backupPasswordFile)) assert.NoError(tb, set.Set(flags.WalletPasswordFileFlag.Name, cfg.walletPasswordFile)) assert.NoError(tb, set.Set(flags.AccountPasswordFileFlag.Name, cfg.accountPasswordFile)) assert.NoError(tb, set.Set(flags.NumAccountsFlag.Name, strconv.Itoa(int(cfg.numAccounts)))) assert.NoError(tb, set.Set(flags.SkipDepositConfirmationFlag.Name, strconv.FormatBool(cfg.skipDepositConfirm))) return cli.NewContext(&app, set, nil) } func setupWalletAndPasswordsDir(t testing.TB) (string, string, string) { walletDir := filepath.Join(t.TempDir(), "wallet") passwordsDir := filepath.Join(t.TempDir(), "passwords") passwordFileDir := filepath.Join(t.TempDir(), "passwordFile") require.NoError(t, os.MkdirAll(passwordFileDir, os.ModePerm)) passwordFilePath := filepath.Join(passwordFileDir, passwordFileName) require.NoError(t, ioutil.WriteFile(passwordFilePath, []byte(password), os.ModePerm)) return walletDir, passwordsDir, passwordFilePath } func Test_Exists_RandomFiles(t *testing.T) { path := filepath.Join(t.TempDir(), "wallet") exists, err := wallet.Exists(path) require.Equal(t, false, exists) require.NoError(t, err) require.NoError(t, os.MkdirAll(path+"/direct", params.BeaconIoConfig().ReadWriteExecutePermissions), "Failed to create directory") exists, err = wallet.Exists(path) require.NoError(t, err) require.Equal(t, true, exists) } func Test_IsValid_RandomFiles(t *testing.T) { path := filepath.Join(t.TempDir(), "wallet") valid, err := wallet.IsValid(path) require.NoError(t, err) require.Equal(t, false, valid) require.NoError(t, os.MkdirAll(path, params.BeaconIoConfig().ReadWriteExecutePermissions), "Failed to create directory") valid, err = wallet.IsValid(path) require.ErrorContains(t, "no wallet found", err) require.Equal(t, false, valid) walletDir := filepath.Join(path, "direct") require.NoError(t, os.MkdirAll(walletDir, params.BeaconIoConfig().ReadWriteExecutePermissions), "Failed to create directory") valid, err = wallet.IsValid(path) require.NoError(t, err) require.Equal(t, true, valid) } func Test_LockUnlockFile(t *testing.T) { walletDir, passwordsDir, passwordFile := setupWalletAndPasswordsDir(t) numAccounts := int64(5) cliCtx := setupWalletCtx(t, &testWalletConfig{ walletDir: walletDir, passwordsDir: passwordsDir, walletPasswordFile: passwordFile, accountPasswordFile: passwordFile, keymanagerKind: keymanager.Imported, numAccounts: numAccounts, }) // We attempt to create the wallet. _, err := accounts.CreateAndSaveWalletCli(cliCtx) require.NoError(t, err) // We attempt to open the newly created wallet. w, err := wallet.OpenWallet(cliCtx.Context, &wallet.Config{ WalletDir: walletDir, WalletPassword: password, }) require.NoError(t, err) defer unlock(t, w) _, err = w.InitializeKeymanager(cliCtx.Context, &iface.InitializeKeymanagerConfig{ SkipMnemonicConfirm: true, }) require.NoError(t, err) assert.NoError(t, err) err = w.LockWalletConfigFile(cliCtx.Context) assert.NoError(t, err) err = w.LockWalletConfigFile(cliCtx.Context) assert.ErrorContains(t, "failed to lock wallet config file", err) unlock(t, w) err = w.LockWalletConfigFile(cliCtx.Context) assert.NoError(t, err) } func unlock(tb assertions.AssertionTestingTB, wallet *wallet.Wallet) { err := wallet.UnlockWalletConfigFile() require.NoError(tb, err) }