prysm-pulse/validator/accounts/wallet_create_test.go
Raul Jordan f75a8efc0d
Remove Keymanageropts Pattern from Wallets and Remove Enable/Disable Feature for V1 CLI (#7831)
* rem opts

* rem more km opts

* more removal of km opts

* removal of km opts

* definition of internal accounts store

* refactor enable/disable

* enable build

* fix rpc

* remove keymanageropts

* fix imported tests

* table driven tests for enable disable

* table driven tests for disable

* comprehensive tests for disable

* tests complete for enable and disable

* pass enable disable tests

* clarify imported

* fix deadlocks

* imported tests pass

* remove enable disable entrypoints

* better derived text

* deep source suggestions

* gaz

* tidy

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-11-17 06:00:20 +00:00

269 lines
11 KiB
Go

package accounts
import (
"context"
"flag"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"testing"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
"github.com/prysmaticlabs/prysm/validator/flags"
"github.com/prysmaticlabs/prysm/validator/keymanager"
"github.com/prysmaticlabs/prysm/validator/keymanager/remote"
"github.com/sirupsen/logrus"
logTest "github.com/sirupsen/logrus/hooks/test"
"github.com/urfave/cli/v2"
)
const (
walletDirName = "wallet"
passwordFileName = "password.txt"
password = "OhWOWthisisatest42!$"
mnemonicFileName = "mnemonic.txt"
mnemonic = "garage car helmet trade salmon embrace market giant movie wet same champion dawn chair shield drill amazing panther accident puzzle garden mosquito kind arena"
)
func init() {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(ioutil.Discard)
}
type testWalletConfig struct {
walletDir string
passwordsDir string
backupDir string
keysDir string
deletePublicKeys string
enablePublicKeys string
disablePublicKeys 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.DisablePublicKeysFlag.Name, cfg.disablePublicKeys, "")
set.String(flags.EnablePublicKeysFlag.Name, cfg.enablePublicKeys, "")
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, "")
set.Bool(flags.SkipMnemonic25thWordCheckFlag.Name, true, "")
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.SkipMnemonic25thWordCheckFlag.Name, "true"))
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.DisablePublicKeysFlag.Name, cfg.disablePublicKeys))
assert.NoError(tb, set.Set(flags.EnablePublicKeysFlag.Name, cfg.enablePublicKeys))
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, params.BeaconIoConfig().ReadWriteExecutePermissions))
passwordFilePath := filepath.Join(passwordFileDir, passwordFileName)
require.NoError(t, ioutil.WriteFile(passwordFilePath, []byte(password), os.ModePerm))
return walletDir, passwordsDir, passwordFilePath
}
func TestCreateOrOpenWallet(t *testing.T) {
hook := logTest.NewGlobal()
walletDir, passwordsDir, walletPasswordFile := setupWalletAndPasswordsDir(t)
cliCtx := setupWalletCtx(t, &testWalletConfig{
walletDir: walletDir,
passwordsDir: passwordsDir,
keymanagerKind: keymanager.Imported,
walletPasswordFile: walletPasswordFile,
})
createImportedWallet := func(cliCtx *cli.Context) (*wallet.Wallet, error) {
cfg, err := extractWalletCreationConfigFromCli(cliCtx, keymanager.Imported)
if err != nil {
return nil, err
}
w := wallet.New(&wallet.Config{
KeymanagerKind: cfg.WalletCfg.KeymanagerKind,
WalletDir: cfg.WalletCfg.WalletDir,
WalletPassword: cfg.WalletCfg.WalletPassword,
})
if err = createImportedKeymanagerWallet(cliCtx.Context, w); err != nil {
return nil, errors.Wrap(err, "could not create keymanager")
}
log.WithField("wallet-path", cfg.WalletCfg.WalletDir).Info(
"Successfully created new wallet",
)
return w, nil
}
createdWallet, err := wallet.OpenWalletOrElseCli(cliCtx, createImportedWallet)
require.NoError(t, err)
require.LogsContain(t, hook, "Successfully created new wallet")
openedWallet, err := wallet.OpenWalletOrElseCli(cliCtx, createImportedWallet)
require.NoError(t, err)
assert.Equal(t, createdWallet.KeymanagerKind(), openedWallet.KeymanagerKind())
assert.Equal(t, createdWallet.AccountsDir(), openedWallet.AccountsDir())
}
func TestCreateWallet_Imported(t *testing.T) {
walletDir, passwordsDir, walletPasswordFile := setupWalletAndPasswordsDir(t)
cliCtx := setupWalletCtx(t, &testWalletConfig{
walletDir: walletDir,
passwordsDir: passwordsDir,
keymanagerKind: keymanager.Imported,
walletPasswordFile: walletPasswordFile,
})
// We attempt to create the wallet.
_, err := CreateAndSaveWalletCli(cliCtx)
require.NoError(t, err)
// We attempt to open the newly created wallet.
_, err = wallet.OpenWallet(cliCtx.Context, &wallet.Config{
WalletDir: walletDir,
})
assert.NoError(t, err)
}
func TestCreateWallet_Derived(t *testing.T) {
walletDir, passwordsDir, passwordFile := setupWalletAndPasswordsDir(t)
cliCtx := setupWalletCtx(t, &testWalletConfig{
walletDir: walletDir,
passwordsDir: passwordsDir,
walletPasswordFile: passwordFile,
keymanagerKind: keymanager.Derived,
numAccounts: 1,
})
// We attempt to create the wallet.
_, err := CreateAndSaveWalletCli(cliCtx)
require.NoError(t, err)
// We attempt to open the newly created wallet.
_, err = wallet.OpenWallet(cliCtx.Context, &wallet.Config{
WalletDir: walletDir,
})
assert.NoError(t, err)
}
// TestCreateWallet_WalletAlreadyExists checks for expected error if trying to create a wallet when there is one already.
func TestCreateWallet_WalletAlreadyExists(t *testing.T) {
walletDir, passwordsDir, passwordFile := setupWalletAndPasswordsDir(t)
cliCtx := setupWalletCtx(t, &testWalletConfig{
walletDir: walletDir,
passwordsDir: passwordsDir,
walletPasswordFile: passwordFile,
keymanagerKind: keymanager.Derived,
numAccounts: 1,
})
// We attempt to create the wallet.
_, err := CreateAndSaveWalletCli(cliCtx)
require.NoError(t, err)
// We attempt to create another wallet of the same type at the same location. We expect an error.
_, err = CreateAndSaveWalletCli(cliCtx)
require.ErrorContains(t, "already exists", err)
cliCtx = setupWalletCtx(t, &testWalletConfig{
walletDir: walletDir,
passwordsDir: passwordsDir,
walletPasswordFile: passwordFile,
keymanagerKind: keymanager.Imported,
})
// We attempt to create another wallet of different type at the same location. We expect an error.
_, err = CreateAndSaveWalletCli(cliCtx)
require.ErrorContains(t, "already exists", err)
}
func TestCreateWallet_Remote(t *testing.T) {
walletDir, _, walletPasswordFile := setupWalletAndPasswordsDir(t)
wantCfg := &remote.KeymanagerOpts{
RemoteCertificate: &remote.CertificateConfig{
ClientCertPath: "/tmp/client.crt",
ClientKeyPath: "/tmp/client.key",
CACertPath: "/tmp/ca.crt",
},
RemoteAddr: "host.example.com:4000",
}
app := cli.App{}
set := flag.NewFlagSet("test", 0)
keymanagerKind := "remote"
set.String(flags.WalletDirFlag.Name, walletDir, "")
set.String(flags.WalletPasswordFileFlag.Name, walletDir, "")
set.String(flags.KeymanagerKindFlag.Name, keymanagerKind, "")
set.String(flags.GrpcRemoteAddressFlag.Name, wantCfg.RemoteAddr, "")
set.String(flags.RemoteSignerCertPathFlag.Name, wantCfg.RemoteCertificate.ClientCertPath, "")
set.String(flags.RemoteSignerKeyPathFlag.Name, wantCfg.RemoteCertificate.ClientKeyPath, "")
set.String(flags.RemoteSignerCACertPathFlag.Name, wantCfg.RemoteCertificate.CACertPath, "")
assert.NoError(t, set.Set(flags.WalletDirFlag.Name, walletDir))
assert.NoError(t, set.Set(flags.WalletPasswordFileFlag.Name, walletPasswordFile))
assert.NoError(t, set.Set(flags.KeymanagerKindFlag.Name, keymanagerKind))
assert.NoError(t, set.Set(flags.GrpcRemoteAddressFlag.Name, wantCfg.RemoteAddr))
assert.NoError(t, set.Set(flags.RemoteSignerCertPathFlag.Name, wantCfg.RemoteCertificate.ClientCertPath))
assert.NoError(t, set.Set(flags.RemoteSignerKeyPathFlag.Name, wantCfg.RemoteCertificate.ClientKeyPath))
assert.NoError(t, set.Set(flags.RemoteSignerCACertPathFlag.Name, wantCfg.RemoteCertificate.CACertPath))
cliCtx := cli.NewContext(&app, set, nil)
// We attempt to create the wallet.
_, err := CreateAndSaveWalletCli(cliCtx)
require.NoError(t, err)
// We attempt to open the newly created wallet.
ctx := context.Background()
w, err := wallet.OpenWallet(cliCtx.Context, &wallet.Config{
WalletDir: walletDir,
})
assert.NoError(t, err)
// We read the keymanager config for the newly created wallet.
encoded, err := w.ReadKeymanagerConfigFromDisk(ctx)
assert.NoError(t, err)
cfg, err := remote.UnmarshalOptionsFile(encoded)
assert.NoError(t, err)
// We assert the created configuration was as desired.
assert.DeepEqual(t, wantCfg, cfg)
}