Accounts-V2: Add tests for exporting and importing (#6615)

* Add test for exporting and importing
* Add test for non-interactive
* Test import cli
* Merge branch 'master' of github.com:prysmaticlabs/prysm into test-export
* Merge branch 'master' into test-export
* Cleanup tests a bit
* Change to assert
* Fix tests
* Merge branch 'master' of github.com:prysmaticlabs/prysm into test-export
* Fix comment, change constants
* Fixes
* Change to require
* Fix broken test
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
* Merge refs/heads/master into test-export
This commit is contained in:
Ivan Martinez 2020-07-20 17:12:46 -04:00 committed by GitHub
parent d54663a553
commit 93bbb86a30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 210 additions and 17 deletions

View File

@ -22,6 +22,7 @@ go_library(
],
deps = [
"//shared/bytesutil:go_default_library",
"//shared/params:go_default_library",
"//validator/flags:go_default_library",
"//validator/keymanager/v2:go_default_library",
"//validator/keymanager/v2/direct:go_default_library",
@ -40,6 +41,9 @@ go_library(
go_test(
name = "go_default_test",
srcs = [
"consts_test.go",
"export_test.go",
"import_test.go",
"list_test.go",
"new_test.go",
"wallet_create_test.go",

View File

@ -0,0 +1,11 @@
package v2
const (
password = "10testPass!"
walletDirName = "wallet"
passwordDirName = "walletpasswords"
exportDirName = "export"
importDirName = "import"
importPasswordDirName = "importpasswords"
passwordFileName = "password.txt"
)

View File

@ -13,6 +13,7 @@ import (
"github.com/logrusorgru/aurora"
"github.com/manifoldco/promptui"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/validator/flags"
"github.com/urfave/cli/v2"
)
@ -25,7 +26,7 @@ func ExportAccount(cliCtx *cli.Context) error {
// Read a wallet's directory from user input.
walletDir, err := inputWalletDir(cliCtx)
if errors.Is(err, ErrNoWalletFound) {
return errors.New("no wallet found, create a new one with ./prysm.sh validator wallet-v2 create")
log.Fatal("no wallet found, create a new one with ./prysm.sh validator wallet-v2 create")
} else if err != nil {
log.WithError(err).Fatal("Could not parse wallet directory")
}
@ -51,6 +52,9 @@ func ExportAccount(cliCtx *cli.Context) error {
if err != nil {
log.WithError(err).Fatal("Could not select accounts")
}
if len(accounts) == 0 {
return errors.New("no accounts to export")
}
if err := wallet.zipAccounts(accounts, outputDir); err != nil {
log.WithError(err).Error("Could not export accounts")
@ -59,6 +63,7 @@ func ExportAccount(cliCtx *cli.Context) error {
if err := logAccountsExported(wallet, accounts); err != nil {
log.WithError(err).Fatal("Could not log out exported accounts")
}
return nil
}
@ -119,6 +124,9 @@ func selectAccounts(cliCtx *cli.Context, accounts []string) ([]string, error) {
func (w *Wallet) zipAccounts(accounts []string, targetPath string) error {
sourcePath := w.accountsPath
archivePath := filepath.Join(targetPath, archiveFilename)
if err := os.MkdirAll(targetPath, params.BeaconIoConfig().ReadWriteExecutePermissions); err != nil {
return errors.Wrap(err, "could not create target folder")
}
zipfile, err := os.Create(archivePath)
if err != nil {
return errors.Wrap(err, "could not create zip file")

View File

@ -0,0 +1,108 @@
package v2
import (
"context"
"flag"
"os"
"path/filepath"
"strings"
"testing"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/validator/flags"
v2 "github.com/prysmaticlabs/prysm/validator/keymanager/v2"
"github.com/urfave/cli/v2"
)
func setupWallet(t *testing.T, testDir string) *Wallet {
walletDir := filepath.Join(testDir, walletDirName)
passwordsDir := filepath.Join(testDir, passwordDirName)
ctx := context.Background()
assert.NoError(t, initializeDirectWallet(walletDir, passwordsDir))
cfg := &WalletConfig{
WalletDir: walletDir,
PasswordsDir: passwordsDir,
KeymanagerKind: v2.Direct,
}
w, err := NewWallet(ctx, cfg)
require.NoError(t, err)
keymanager, err := w.InitializeKeymanager(ctx, true)
require.NoError(t, err)
_, err = keymanager.CreateAccount(ctx, password)
require.NoError(t, err)
return w
}
func TestZipAndUnzip(t *testing.T) {
testDir := testutil.TempDir()
walletDir := filepath.Join(testDir, walletDirName)
passwordsDir := filepath.Join(testDir, passwordDirName)
exportDir := filepath.Join(testDir, exportDirName)
importDir := filepath.Join(testDir, importDirName)
defer func() {
assert.NoError(t, os.RemoveAll(walletDir))
assert.NoError(t, os.RemoveAll(passwordsDir))
assert.NoError(t, os.RemoveAll(exportDir))
assert.NoError(t, os.RemoveAll(importDir))
}()
wallet := setupWallet(t, testDir)
accounts, err := wallet.AccountNames()
require.NoError(t, err)
if len(accounts) == 0 {
t.Fatal("Expected more accounts, received 0")
}
err = wallet.zipAccounts(accounts, exportDir)
require.NoError(t, err)
if _, err := os.Stat(filepath.Join(exportDir, archiveFilename)); os.IsNotExist(err) {
t.Fatal("Expected file to exist")
}
importedAccounts, err := unzipArchiveToTarget(exportDir, importDir)
require.NoError(t, err)
allAccountsStr := strings.Join(accounts, " ")
for _, importedAccount := range importedAccounts {
if !strings.Contains(allAccountsStr, importedAccount) {
t.Fatalf("Expected %s to be in %s", importedAccount, allAccountsStr)
}
}
}
func TestExport_Noninteractive(t *testing.T) {
testDir := testutil.TempDir()
walletDir := filepath.Join(testDir, walletDirName)
passwordsDir := filepath.Join(testDir, passwordDirName)
exportDir := filepath.Join(testDir, exportDirName)
accounts := "all"
defer func() {
assert.NoError(t, os.RemoveAll(walletDir))
assert.NoError(t, os.RemoveAll(passwordsDir))
assert.NoError(t, os.RemoveAll(exportDir))
}()
setupWallet(t, testDir)
app := cli.App{}
set := flag.NewFlagSet("test", 0)
set.String(flags.WalletDirFlag.Name, walletDir, "")
set.String(flags.WalletPasswordsDirFlag.Name, passwordsDir, "")
set.String(flags.BackupPathFlag.Name, exportDir, "")
set.String(flags.AccountsFlag.Name, accounts, "")
assert.NoError(t, set.Set(flags.WalletDirFlag.Name, walletDir))
assert.NoError(t, set.Set(flags.WalletPasswordsDirFlag.Name, passwordsDir))
assert.NoError(t, set.Set(flags.BackupPathFlag.Name, exportDir))
assert.NoError(t, set.Set(flags.AccountsFlag.Name, accounts))
cliCtx := cli.NewContext(&app, set, nil)
require.NoError(t, ExportAccount(cliCtx))
if _, err := os.Stat(filepath.Join(exportDir, archiveFilename)); os.IsNotExist(err) {
t.Fatal("Expected file to exist")
}
}

View File

@ -23,9 +23,7 @@ import (
func ImportAccount(cliCtx *cli.Context) error {
// Read a wallet's directory from user input.
walletDir, err := inputWalletDir(cliCtx)
if errors.Is(err, ErrNoWalletFound) {
return errors.New("no wallet found, create a new one with ./prysm.sh validator wallet-v2 create")
} else if err != nil {
if err != nil {
return errors.Wrap(err, "could not parse wallet directory")
}

View File

@ -0,0 +1,59 @@
package v2
import (
"flag"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/validator/flags"
"github.com/urfave/cli/v2"
)
func TestImport_Noninteractive(t *testing.T) {
testDir := testutil.TempDir()
walletDir := filepath.Join(testDir, walletDirName)
passwordsDir := filepath.Join(testDir, passwordDirName)
exportDir := filepath.Join(testDir, exportDirName)
importDir := filepath.Join(testDir, importDirName)
importPasswordDir := filepath.Join(testDir, importPasswordDirName)
passwordFilePath := filepath.Join(testDir, passwordFileName)
require.NoError(t, ioutil.WriteFile(passwordFilePath, []byte(password), os.ModePerm))
defer func() {
assert.NoError(t, os.RemoveAll(walletDir))
assert.NoError(t, os.RemoveAll(passwordsDir))
assert.NoError(t, os.RemoveAll(exportDir))
assert.NoError(t, os.RemoveAll(importDir))
assert.NoError(t, os.RemoveAll(importPasswordDir))
}()
wallet := setupWallet(t, testDir)
accounts, err := wallet.AccountNames()
require.NoError(t, err)
assert.Equal(t, len(accounts), 1)
require.NoError(t, wallet.zipAccounts(accounts, exportDir))
if _, err := os.Stat(filepath.Join(exportDir, archiveFilename)); os.IsNotExist(err) {
t.Fatal("Expected file to exist")
}
app := cli.App{}
set := flag.NewFlagSet("test", 0)
set.String(flags.WalletDirFlag.Name, importDir, "")
set.String(flags.WalletPasswordsDirFlag.Name, importPasswordDir, "")
set.String(flags.BackupPathFlag.Name, exportDir, "")
set.String(flags.PasswordFileFlag.Name, passwordFilePath, "")
assert.NoError(t, set.Set(flags.WalletDirFlag.Name, importDir))
assert.NoError(t, set.Set(flags.WalletPasswordsDirFlag.Name, importPasswordDir))
assert.NoError(t, set.Set(flags.BackupPathFlag.Name, exportDir))
assert.NoError(t, set.Set(flags.PasswordFileFlag.Name, passwordFilePath))
cliCtx := cli.NewContext(&app, set, nil)
require.NoError(t, ImportAccount(cliCtx))
}

View File

@ -32,7 +32,6 @@ func TestListAccounts_DirectKeymanager(t *testing.T) {
numAccounts := 5
accountNames := make([]string, numAccounts)
pubKeys := make([][48]byte, numAccounts)
password := "passw0rd2020%%"
depositDataForAccounts := make([][]byte, numAccounts)
for i := 0; i < numAccounts; i++ {
// Generate a new account name and write the account

View File

@ -11,11 +11,11 @@ import (
"path"
"strings"
"github.com/logrusorgru/aurora"
petname "github.com/dustinkirkland/golang-petname"
"github.com/logrusorgru/aurora"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/validator/flags"
v2keymanager "github.com/prysmaticlabs/prysm/validator/keymanager/v2"
"github.com/prysmaticlabs/prysm/validator/keymanager/v2/direct"
@ -46,8 +46,8 @@ var (
// WalletConfig for a wallet struct, containing important information
// such as the passwords directory, the wallet's directory, and keymanager.
type WalletConfig struct {
PasswordsDir string
WalletDir string
PasswordsDir string
KeymanagerKind v2keymanager.Kind
CanUnlockAccounts bool
}
@ -309,6 +309,10 @@ func (w *Wallet) enterPasswordForAccount(cliCtx *cli.Context, accountName string
attemptingPassword = false
}
}
if err := os.MkdirAll(w.passwordsDir, params.BeaconIoConfig().ReadWriteExecutePermissions); err != nil {
return err
}
if err := w.writePasswordToFile(accountName, password); err != nil {
return errors.Wrap(err, "could not write password to disk")
}

View File

@ -43,7 +43,8 @@ func CreateWallet(cliCtx *cli.Context) error {
}
switch keymanagerKind {
case v2keymanager.Direct:
if err = initializeDirectWallet(cliCtx, walletDir); err != nil {
passwordsDirPath := inputPasswordsDirectory(cliCtx)
if err = initializeDirectWallet(walletDir, passwordsDirPath); err != nil {
log.Fatalf("Could not initialize wallet with direct keymanager: %v", err)
}
log.WithField("wallet-path", walletDir).Infof(
@ -65,11 +66,10 @@ func CreateWallet(cliCtx *cli.Context) error {
return nil
}
func initializeDirectWallet(cliCtx *cli.Context, walletDir string) error {
passwordsDirPath := inputPasswordsDirectory(cliCtx)
func initializeDirectWallet(walletDir string, passwordsDir string) error {
walletConfig := &WalletConfig{
PasswordsDir: passwordsDirPath,
WalletDir: walletDir,
PasswordsDir: passwordsDir,
KeymanagerKind: v2keymanager.Direct,
CanUnlockAccounts: true,
}

View File

@ -4,6 +4,7 @@ import (
"context"
"flag"
"os"
"path/filepath"
"testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
@ -17,8 +18,8 @@ import (
)
func TestCreateWallet_Direct(t *testing.T) {
walletDir := testutil.TempDir() + "/wallet"
passwordsDir := testutil.TempDir() + "/walletpasswords"
walletDir := filepath.Join(testutil.TempDir(), walletDirName)
passwordsDir := filepath.Join(testutil.TempDir(), passwordDirName)
defer func() {
assert.NoError(t, os.RemoveAll(walletDir))
assert.NoError(t, os.RemoveAll(passwordsDir))
@ -29,10 +30,10 @@ func TestCreateWallet_Direct(t *testing.T) {
keymanagerKind := "direct"
set.String(flags.WalletDirFlag.Name, walletDir, "")
set.String(flags.KeymanagerKindFlag.Name, keymanagerKind, "")
set.String(flags.WalletPasswordsDirFlag.Name, keymanagerKind, "")
set.String(flags.WalletPasswordsDirFlag.Name, passwordsDir, "")
assert.NoError(t, set.Set(flags.WalletDirFlag.Name, walletDir))
assert.NoError(t, set.Set(flags.WalletPasswordsDirFlag.Name, passwordsDir))
assert.NoError(t, set.Set(flags.KeymanagerKindFlag.Name, keymanagerKind))
assert.NoError(t, set.Set(flags.WalletPasswordsDirFlag.Name, passwordsDir))
cliCtx := cli.NewContext(&app, set, nil)
// We attempt to create the wallet.

View File

@ -4,6 +4,7 @@ import (
"context"
"flag"
"os"
"path/filepath"
"testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
@ -15,7 +16,7 @@ import (
)
func TestEditWalletConfiguration(t *testing.T) {
walletDir := testutil.TempDir() + "/wallet"
walletDir := filepath.Join(testutil.TempDir(), walletDirName)
defer func() {
assert.NoError(t, os.RemoveAll(walletDir))
}()