mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-05-02 03:02:54 -04:00
* Migrating Keymanager account list functionality into each keymanager type * Addressing review comments * Adding newline at end of BUILD.bazel * bazel run //:gazelle -- fix * account deleter cleanup * bazel run //:gazelle -- fix * remove stale logging statement * adding deleter interface to mock functions * fixing deepsource findings * go.sum * bazel run //:gazelle -- fix * go mod t-dy -compat=1.17 Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com> Co-authored-by: prestonvanloon <preston@prysmaticlabs.com>
527 lines
18 KiB
Go
527 lines
18 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/golang/protobuf/ptypes/empty"
|
|
"github.com/google/uuid"
|
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
|
"github.com/prysmaticlabs/prysm/crypto/bls"
|
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
|
ethpbservice "github.com/prysmaticlabs/prysm/proto/eth/service"
|
|
validatorpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/validator-client"
|
|
"github.com/prysmaticlabs/prysm/testing/require"
|
|
"github.com/prysmaticlabs/prysm/validator/accounts"
|
|
"github.com/prysmaticlabs/prysm/validator/accounts/iface"
|
|
mock "github.com/prysmaticlabs/prysm/validator/accounts/testing"
|
|
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
|
|
"github.com/prysmaticlabs/prysm/validator/client"
|
|
"github.com/prysmaticlabs/prysm/validator/db/kv"
|
|
"github.com/prysmaticlabs/prysm/validator/keymanager"
|
|
"github.com/prysmaticlabs/prysm/validator/keymanager/derived"
|
|
remote_web3signer "github.com/prysmaticlabs/prysm/validator/keymanager/remote-web3signer"
|
|
"github.com/prysmaticlabs/prysm/validator/slashing-protection-history/format"
|
|
mocks "github.com/prysmaticlabs/prysm/validator/testing"
|
|
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
|
|
)
|
|
|
|
func TestServer_ListKeystores(t *testing.T) {
|
|
t.Run("wallet not ready", func(t *testing.T) {
|
|
s := Server{}
|
|
_, err := s.ListKeystores(context.Background(), &empty.Empty{})
|
|
require.ErrorContains(t, "Prysm Wallet not initialized. Please create a new wallet.", err)
|
|
})
|
|
ctx := context.Background()
|
|
localWalletDir := setupWalletDir(t)
|
|
defaultWalletPath = localWalletDir
|
|
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, iface.InitKeymanagerConfig{ListenForChanges: false})
|
|
require.NoError(t, err)
|
|
vs, err := client.NewValidatorService(ctx, &client.Config{
|
|
Wallet: w,
|
|
Validator: &mock.MockValidator{
|
|
Km: km,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
s := &Server{
|
|
walletInitialized: true,
|
|
wallet: w,
|
|
validatorService: vs,
|
|
}
|
|
numAccounts := 50
|
|
dr, ok := km.(*derived.Keymanager)
|
|
require.Equal(t, true, ok)
|
|
err = dr.RecoverAccountsFromMnemonic(ctx, mocks.TestMnemonic, "", numAccounts)
|
|
require.NoError(t, err)
|
|
expectedKeys, err := dr.FetchValidatingPublicKeys(ctx)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("returns proper data with existing keystores", func(t *testing.T) {
|
|
resp, err := s.ListKeystores(context.Background(), &empty.Empty{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, numAccounts, len(resp.Data))
|
|
for i := 0; i < numAccounts; i++ {
|
|
require.DeepEqual(t, expectedKeys[i][:], resp.Data[i].ValidatingPubkey)
|
|
require.Equal(
|
|
t,
|
|
fmt.Sprintf(derived.ValidatingKeyDerivationPathTemplate, i),
|
|
resp.Data[i].DerivationPath,
|
|
)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestServer_ImportKeystores(t *testing.T) {
|
|
t.Run("wallet not ready", func(t *testing.T) {
|
|
s := Server{}
|
|
response, err := s.ImportKeystores(context.Background(), ðpbservice.ImportKeystoresRequest{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, len(response.Data))
|
|
})
|
|
ctx := context.Background()
|
|
localWalletDir := setupWalletDir(t)
|
|
defaultWalletPath = localWalletDir
|
|
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, iface.InitKeymanagerConfig{ListenForChanges: false})
|
|
require.NoError(t, err)
|
|
vs, err := client.NewValidatorService(ctx, &client.Config{
|
|
Wallet: w,
|
|
Validator: &mock.MockValidator{
|
|
Km: km,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
s := &Server{
|
|
walletInitialized: true,
|
|
wallet: w,
|
|
validatorService: vs,
|
|
}
|
|
t.Run("200 response even if faulty keystore in request", func(t *testing.T) {
|
|
response, err := s.ImportKeystores(context.Background(), ðpbservice.ImportKeystoresRequest{
|
|
Keystores: []string{"hi"},
|
|
Passwords: []string{"hi"},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(response.Data))
|
|
require.Equal(t, ethpbservice.ImportedKeystoreStatus_ERROR, response.Data[0].Status)
|
|
})
|
|
t.Run("200 response even if no passwords in request", func(t *testing.T) {
|
|
response, err := s.ImportKeystores(context.Background(), ðpbservice.ImportKeystoresRequest{
|
|
Keystores: []string{"hi"},
|
|
Passwords: []string{},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(response.Data))
|
|
require.Equal(t, ethpbservice.ImportedKeystoreStatus_ERROR, response.Data[0].Status)
|
|
})
|
|
t.Run("200 response even if keystores more than passwords in request", func(t *testing.T) {
|
|
response, err := s.ImportKeystores(context.Background(), ðpbservice.ImportKeystoresRequest{
|
|
Keystores: []string{"hi", "hi"},
|
|
Passwords: []string{"hi"},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 2, len(response.Data))
|
|
require.Equal(t, ethpbservice.ImportedKeystoreStatus_ERROR, response.Data[0].Status)
|
|
})
|
|
t.Run("200 response even if number of passwords does not match number of keystores", func(t *testing.T) {
|
|
response, err := s.ImportKeystores(context.Background(), ðpbservice.ImportKeystoresRequest{
|
|
Keystores: []string{"hi"},
|
|
Passwords: []string{"hi", "hi"},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(response.Data))
|
|
require.Equal(t, ethpbservice.ImportedKeystoreStatus_ERROR, response.Data[0].Status)
|
|
})
|
|
t.Run("200 response even if faulty slashing protection data", func(t *testing.T) {
|
|
numKeystores := 5
|
|
password := "12345678"
|
|
encodedKeystores := make([]string, numKeystores)
|
|
passwords := make([]string, numKeystores)
|
|
for i := 0; i < numKeystores; i++ {
|
|
enc, err := json.Marshal(createRandomKeystore(t, password))
|
|
encodedKeystores[i] = string(enc)
|
|
require.NoError(t, err)
|
|
passwords[i] = password
|
|
}
|
|
resp, err := s.ImportKeystores(context.Background(), ðpbservice.ImportKeystoresRequest{
|
|
Keystores: encodedKeystores,
|
|
Passwords: passwords,
|
|
SlashingProtection: "foobar",
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, numKeystores, len(resp.Data))
|
|
for _, st := range resp.Data {
|
|
require.Equal(t, ethpbservice.ImportedKeystoreStatus_ERROR, st.Status)
|
|
}
|
|
})
|
|
t.Run("returns proper statuses for keystores in request", func(t *testing.T) {
|
|
numKeystores := 5
|
|
password := "12345678"
|
|
keystores := make([]*keymanager.Keystore, numKeystores)
|
|
passwords := make([]string, numKeystores)
|
|
publicKeys := make([][fieldparams.BLSPubkeyLength]byte, numKeystores)
|
|
for i := 0; i < numKeystores; i++ {
|
|
keystores[i] = createRandomKeystore(t, password)
|
|
pubKey, err := hex.DecodeString(keystores[i].Pubkey)
|
|
require.NoError(t, err)
|
|
publicKeys[i] = bytesutil.ToBytes48(pubKey)
|
|
passwords[i] = password
|
|
}
|
|
|
|
// Create a validator database.
|
|
validatorDB, err := kv.NewKVStore(ctx, defaultWalletPath, &kv.Config{
|
|
PubKeys: publicKeys,
|
|
})
|
|
require.NoError(t, err)
|
|
s.valDB = validatorDB
|
|
|
|
// Have to close it after import is done otherwise it complains db is not open.
|
|
defer func() {
|
|
require.NoError(t, validatorDB.Close())
|
|
}()
|
|
encodedKeystores := make([]string, numKeystores)
|
|
for i := 0; i < numKeystores; i++ {
|
|
enc, err := json.Marshal(keystores[i])
|
|
require.NoError(t, err)
|
|
encodedKeystores[i] = string(enc)
|
|
}
|
|
|
|
// Generate mock slashing history.
|
|
attestingHistory := make([][]*kv.AttestationRecord, 0)
|
|
proposalHistory := make([]kv.ProposalHistoryForPubkey, len(publicKeys))
|
|
for i := 0; i < len(publicKeys); i++ {
|
|
proposalHistory[i].Proposals = make([]kv.Proposal, 0)
|
|
}
|
|
mockJSON, err := mocks.MockSlashingProtectionJSON(publicKeys, attestingHistory, proposalHistory)
|
|
require.NoError(t, err)
|
|
|
|
// JSON encode the protection JSON and save it.
|
|
encodedSlashingProtection, err := json.Marshal(mockJSON)
|
|
require.NoError(t, err)
|
|
|
|
resp, err := s.ImportKeystores(context.Background(), ðpbservice.ImportKeystoresRequest{
|
|
Keystores: encodedKeystores,
|
|
Passwords: passwords,
|
|
SlashingProtection: string(encodedSlashingProtection),
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, numKeystores, len(resp.Data))
|
|
for _, status := range resp.Data {
|
|
require.Equal(t, ethpbservice.ImportedKeystoreStatus_IMPORTED, status.Status)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestServer_ImportKeystores_WrongKeymanagerKind(t *testing.T) {
|
|
ctx := context.Background()
|
|
w := wallet.NewWalletForWeb3Signer()
|
|
root := make([]byte, fieldparams.RootLength)
|
|
root[0] = 1
|
|
km, err := w.InitializeKeymanager(ctx, iface.InitKeymanagerConfig{ListenForChanges: false, Web3SignerConfig: &remote_web3signer.SetupConfig{
|
|
BaseEndpoint: "http://example.com",
|
|
GenesisValidatorsRoot: root,
|
|
PublicKeysURL: "http://example.com/public_keys",
|
|
}})
|
|
require.NoError(t, err)
|
|
vs, err := client.NewValidatorService(ctx, &client.Config{
|
|
Wallet: w,
|
|
Validator: &mock.MockValidator{
|
|
Km: km,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
s := &Server{
|
|
walletInitialized: true,
|
|
wallet: w,
|
|
validatorService: vs,
|
|
}
|
|
response, err := s.ImportKeystores(context.Background(), ðpbservice.ImportKeystoresRequest{
|
|
Keystores: []string{"hi"},
|
|
Passwords: []string{"hi"},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(response.Data))
|
|
require.Equal(t, ethpbservice.ImportedKeystoreStatus_ERROR, response.Data[0].Status)
|
|
require.Equal(t, "Keymanager kind cannot import keys", response.Data[0].Message)
|
|
}
|
|
|
|
func TestServer_DeleteKeystores(t *testing.T) {
|
|
t.Run("wallet not ready", func(t *testing.T) {
|
|
s := Server{}
|
|
response, err := s.DeleteKeystores(context.Background(), ðpbservice.DeleteKeystoresRequest{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, len(response.Data))
|
|
})
|
|
ctx := context.Background()
|
|
srv := setupServerWithWallet(t)
|
|
|
|
// We recover 3 accounts from a test mnemonic.
|
|
numAccounts := 3
|
|
km, er := srv.validatorService.Keymanager()
|
|
require.NoError(t, er)
|
|
dr, ok := km.(*derived.Keymanager)
|
|
require.Equal(t, true, ok)
|
|
err := dr.RecoverAccountsFromMnemonic(ctx, mocks.TestMnemonic, "", numAccounts)
|
|
require.NoError(t, err)
|
|
publicKeys, err := dr.FetchValidatingPublicKeys(ctx)
|
|
require.NoError(t, err)
|
|
|
|
// Create a validator database.
|
|
validatorDB, err := kv.NewKVStore(ctx, defaultWalletPath, &kv.Config{
|
|
PubKeys: publicKeys,
|
|
})
|
|
require.NoError(t, err)
|
|
srv.valDB = validatorDB
|
|
|
|
// Have to close it after import is done otherwise it complains db is not open.
|
|
defer func() {
|
|
require.NoError(t, validatorDB.Close())
|
|
}()
|
|
|
|
// Generate mock slashing history.
|
|
attestingHistory := make([][]*kv.AttestationRecord, 0)
|
|
proposalHistory := make([]kv.ProposalHistoryForPubkey, len(publicKeys))
|
|
for i := 0; i < len(publicKeys); i++ {
|
|
proposalHistory[i].Proposals = make([]kv.Proposal, 0)
|
|
}
|
|
mockJSON, err := mocks.MockSlashingProtectionJSON(publicKeys, attestingHistory, proposalHistory)
|
|
require.NoError(t, err)
|
|
|
|
// JSON encode the protection JSON and save it.
|
|
encoded, err := json.Marshal(mockJSON)
|
|
require.NoError(t, err)
|
|
|
|
_, err = srv.ImportSlashingProtection(ctx, &validatorpb.ImportSlashingProtectionRequest{
|
|
SlashingProtectionJson: string(encoded),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("no slashing protection response if no keys in request even if we have a history in DB", func(t *testing.T) {
|
|
resp, err := srv.DeleteKeystores(context.Background(), ðpbservice.DeleteKeystoresRequest{
|
|
Pubkeys: nil,
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "", resp.SlashingProtection)
|
|
})
|
|
|
|
// For ease of test setup, we'll give each public key a string identifier.
|
|
publicKeysWithId := map[string][fieldparams.BLSPubkeyLength]byte{
|
|
"a": publicKeys[0],
|
|
"b": publicKeys[1],
|
|
"c": publicKeys[2],
|
|
}
|
|
|
|
type keyCase struct {
|
|
id string
|
|
wantProtectionData bool
|
|
}
|
|
tests := []struct {
|
|
keys []*keyCase
|
|
wantStatuses []ethpbservice.DeletedKeystoreStatus_Status
|
|
}{
|
|
{
|
|
keys: []*keyCase{
|
|
{id: "a", wantProtectionData: true},
|
|
{id: "a", wantProtectionData: true},
|
|
{id: "d"},
|
|
{id: "c", wantProtectionData: true},
|
|
},
|
|
wantStatuses: []ethpbservice.DeletedKeystoreStatus_Status{
|
|
ethpbservice.DeletedKeystoreStatus_DELETED,
|
|
ethpbservice.DeletedKeystoreStatus_NOT_ACTIVE,
|
|
ethpbservice.DeletedKeystoreStatus_NOT_FOUND,
|
|
ethpbservice.DeletedKeystoreStatus_DELETED,
|
|
},
|
|
},
|
|
{
|
|
keys: []*keyCase{
|
|
{id: "a", wantProtectionData: true},
|
|
{id: "c", wantProtectionData: true},
|
|
},
|
|
wantStatuses: []ethpbservice.DeletedKeystoreStatus_Status{
|
|
ethpbservice.DeletedKeystoreStatus_NOT_ACTIVE,
|
|
ethpbservice.DeletedKeystoreStatus_NOT_ACTIVE,
|
|
},
|
|
},
|
|
{
|
|
keys: []*keyCase{
|
|
{id: "x"},
|
|
},
|
|
wantStatuses: []ethpbservice.DeletedKeystoreStatus_Status{
|
|
ethpbservice.DeletedKeystoreStatus_NOT_FOUND,
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range tests {
|
|
keys := make([][]byte, len(tc.keys))
|
|
for i := 0; i < len(tc.keys); i++ {
|
|
pk := publicKeysWithId[tc.keys[i].id]
|
|
keys[i] = pk[:]
|
|
}
|
|
resp, err := srv.DeleteKeystores(ctx, ðpbservice.DeleteKeystoresRequest{Pubkeys: keys})
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(keys), len(resp.Data))
|
|
slashingProtectionData := &format.EIPSlashingProtectionFormat{}
|
|
require.NoError(t, json.Unmarshal([]byte(resp.SlashingProtection), slashingProtectionData))
|
|
require.Equal(t, true, len(slashingProtectionData.Data) > 0)
|
|
|
|
for i := 0; i < len(tc.keys); i++ {
|
|
require.Equal(
|
|
t,
|
|
tc.wantStatuses[i],
|
|
resp.Data[i].Status,
|
|
fmt.Sprintf("Checking status for key %s", tc.keys[i].id),
|
|
)
|
|
if tc.keys[i].wantProtectionData {
|
|
// We check that we can find the key in the slashing protection data.
|
|
var found bool
|
|
for _, dt := range slashingProtectionData.Data {
|
|
if dt.Pubkey == fmt.Sprintf("%#x", keys[i]) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
require.Equal(t, true, found)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestServer_DeleteKeystores_FailedSlashingProtectionExport(t *testing.T) {
|
|
ctx := context.Background()
|
|
srv := setupServerWithWallet(t)
|
|
|
|
// We recover 3 accounts from a test mnemonic.
|
|
numAccounts := 3
|
|
km, er := srv.validatorService.Keymanager()
|
|
require.NoError(t, er)
|
|
dr, ok := km.(*derived.Keymanager)
|
|
require.Equal(t, true, ok)
|
|
err := dr.RecoverAccountsFromMnemonic(ctx, mocks.TestMnemonic, "", numAccounts)
|
|
require.NoError(t, err)
|
|
publicKeys, err := dr.FetchValidatingPublicKeys(ctx)
|
|
require.NoError(t, err)
|
|
|
|
// Create a validator database.
|
|
validatorDB, err := kv.NewKVStore(ctx, defaultWalletPath, &kv.Config{
|
|
PubKeys: publicKeys,
|
|
})
|
|
require.NoError(t, err)
|
|
err = validatorDB.SaveGenesisValidatorsRoot(ctx, make([]byte, fieldparams.RootLength))
|
|
require.NoError(t, err)
|
|
srv.valDB = validatorDB
|
|
|
|
// Have to close it after import is done otherwise it complains db is not open.
|
|
defer func() {
|
|
require.NoError(t, validatorDB.Close())
|
|
}()
|
|
|
|
response, err := srv.DeleteKeystores(context.Background(), ðpbservice.DeleteKeystoresRequest{
|
|
Pubkeys: [][]byte{[]byte("a")},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(response.Data))
|
|
require.Equal(t, ethpbservice.DeletedKeystoreStatus_ERROR, response.Data[0].Status)
|
|
require.Equal(t, "Non duplicate keys that were existing were deleted, but could not export slashing protection history.",
|
|
response.Data[0].Message,
|
|
)
|
|
}
|
|
|
|
func TestServer_DeleteKeystores_WrongKeymanagerKind(t *testing.T) {
|
|
ctx := context.Background()
|
|
w := wallet.NewWalletForWeb3Signer()
|
|
root := make([]byte, fieldparams.RootLength)
|
|
root[0] = 1
|
|
km, err := w.InitializeKeymanager(ctx, iface.InitKeymanagerConfig{ListenForChanges: false,
|
|
Web3SignerConfig: &remote_web3signer.SetupConfig{
|
|
BaseEndpoint: "http://example.com",
|
|
GenesisValidatorsRoot: root,
|
|
PublicKeysURL: "http://example.com/public_keys",
|
|
}})
|
|
require.NoError(t, err)
|
|
vs, err := client.NewValidatorService(ctx, &client.Config{
|
|
Wallet: w,
|
|
Validator: &mock.MockValidator{
|
|
Km: km,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
s := &Server{
|
|
walletInitialized: true,
|
|
wallet: w,
|
|
validatorService: vs,
|
|
}
|
|
_, err = s.DeleteKeystores(ctx, ðpbservice.DeleteKeystoresRequest{Pubkeys: [][]byte{[]byte("a")}})
|
|
require.ErrorContains(t, "Wrong wallet type", err)
|
|
require.ErrorContains(t, "Only Imported or Derived wallets can delete accounts", err)
|
|
}
|
|
|
|
func setupServerWithWallet(t testing.TB) *Server {
|
|
ctx := context.Background()
|
|
localWalletDir := setupWalletDir(t)
|
|
defaultWalletPath = localWalletDir
|
|
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, iface.InitKeymanagerConfig{ListenForChanges: false})
|
|
require.NoError(t, err)
|
|
vs, err := client.NewValidatorService(ctx, &client.Config{
|
|
Wallet: w,
|
|
Validator: &mock.MockValidator{
|
|
Km: km,
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
return &Server{
|
|
walletInitialized: true,
|
|
wallet: w,
|
|
validatorService: vs,
|
|
}
|
|
}
|
|
|
|
func createRandomKeystore(t testing.TB, password string) *keymanager.Keystore {
|
|
encryptor := keystorev4.New()
|
|
id, err := uuid.NewRandom()
|
|
require.NoError(t, err)
|
|
validatingKey, err := bls.RandKey()
|
|
require.NoError(t, err)
|
|
pubKey := validatingKey.PublicKey().Marshal()
|
|
cryptoFields, err := encryptor.Encrypt(validatingKey.Marshal(), password)
|
|
require.NoError(t, err)
|
|
return &keymanager.Keystore{
|
|
Crypto: cryptoFields,
|
|
Pubkey: fmt.Sprintf("%x", pubKey),
|
|
ID: id.String(),
|
|
Version: encryptor.Version(),
|
|
Name: encryptor.Name(),
|
|
}
|
|
}
|