add selected wallet and selected chat accounts (#1326)

* use keyStore.ImportExtendedKeyForPurpose when creating keys

* rename selectecAccount to selectedWalletAccount

* add selectedChatAccount

* update e2e test to check that injected whisper key is the chat public key

* update TestSelectedAccountOnRestart to check that chat key is used in whisper

* use chat account in api/backend

* update mocks

* temporarily update VERSION to build a release

* check that chat/wallet keys are the same in a different test

* add account test to check that wallet and chat keys are the same

* test only that the chat key is injected in whisper

* put back the right VERSION
This commit is contained in:
Andrea Franz 2019-01-09 09:47:06 +01:00 committed by GitHub
parent 54022561f5
commit 06d4a99c09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 79 deletions

View File

@ -36,7 +36,8 @@ type Manager struct {
geth GethServiceProvider geth GethServiceProvider
mu sync.RWMutex mu sync.RWMutex
selectedAccount *SelectedExtKey // account that was processed during the last call to SelectAccount() selectedWalletAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
selectedChatAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
} }
// NewManager returns new node account manager. // NewManager returns new node account manager.
@ -69,7 +70,7 @@ func (m *Manager) CreateAccount(password string) (address, pubKey, mnemonic stri
} }
// import created key into account keystore // import created key into account keystore
address, pubKey, err = m.importExtendedKey(extKey, password) address, pubKey, err = m.importExtendedKey(extkeys.KeyPurposeWallet, extKey, password)
if err != nil { if err != nil {
return "", "", "", err return "", "", "", err
} }
@ -89,8 +90,8 @@ func (m *Manager) CreateChildAccount(parentAddress, password string) (address, p
return "", "", err return "", "", err
} }
if parentAddress == "" && m.selectedAccount != nil { // derive from selected account by default if parentAddress == "" && m.selectedWalletAccount != nil { // derive from selected account by default
parentAddress = m.selectedAccount.Address.Hex() parentAddress = m.selectedWalletAccount.Address.Hex()
} }
if parentAddress == "" { if parentAddress == "" {
@ -124,14 +125,14 @@ func (m *Manager) CreateChildAccount(parentAddress, password string) (address, p
accountKey.SubAccountIndex++ accountKey.SubAccountIndex++
// import derived key into account keystore // import derived key into account keystore
address, pubKey, err = m.importExtendedKey(childKey, password) address, pubKey, err = m.importExtendedKey(extkeys.KeyPurposeWallet, childKey, password)
if err != nil { if err != nil {
return return
} }
// update in-memory selected account // update in-memory selected account
if m.selectedAccount != nil { if m.selectedWalletAccount != nil {
m.selectedAccount.AccountKey = accountKey m.selectedWalletAccount.AccountKey = accountKey
} }
return address, pubKey, nil return address, pubKey, nil
@ -148,7 +149,7 @@ func (m *Manager) RecoverAccount(password, mnemonic string) (address, pubKey str
} }
// import re-created key into account keystore // import re-created key into account keystore
address, pubKey, err = m.importExtendedKey(extKey, password) address, pubKey, err = m.importExtendedKey(extkeys.KeyPurposeWallet, extKey, password)
if err != nil { if err != nil {
return return
} }
@ -240,7 +241,16 @@ func (m *Manager) SelectAccount(address, password string) error {
if err != nil { if err != nil {
return err return err
} }
m.selectedAccount = &SelectedExtKey{
m.selectedWalletAccount = &SelectedExtKey{
Address: account.Address,
AccountKey: accountKey,
SubAccounts: subAccounts,
}
// Before completely decoupling the wallet and chat keys,
// we have a selectedChatAccount with the same key used for the wallet.
m.selectedChatAccount = &SelectedExtKey{
Address: account.Address, Address: account.Address,
AccountKey: accountKey, AccountKey: accountKey,
SubAccounts: subAccounts, SubAccounts: subAccounts,
@ -249,35 +259,47 @@ func (m *Manager) SelectAccount(address, password string) error {
return nil return nil
} }
// SelectedAccount returns currently selected account // SelectedWalletAccount returns currently selected wallet account
func (m *Manager) SelectedAccount() (*SelectedExtKey, error) { func (m *Manager) SelectedWalletAccount() (*SelectedExtKey, error) {
m.mu.RLock() m.mu.RLock()
defer m.mu.RUnlock() defer m.mu.RUnlock()
if m.selectedAccount == nil { if m.selectedWalletAccount == nil {
return nil, ErrNoAccountSelected return nil, ErrNoAccountSelected
} }
return m.selectedAccount, nil return m.selectedWalletAccount, nil
} }
// Logout clears selectedAccount. // SelectedChatAccount returns currently selected chat account
func (m *Manager) SelectedChatAccount() (*SelectedExtKey, error) {
m.mu.RLock()
defer m.mu.RUnlock()
if m.selectedChatAccount == nil {
return nil, ErrNoAccountSelected
}
return m.selectedChatAccount, nil
}
// Logout clears selectedWalletAccount.
func (m *Manager) Logout() { func (m *Manager) Logout() {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
m.selectedAccount = nil m.selectedWalletAccount = nil
m.selectedChatAccount = nil
} }
// importExtendedKey processes incoming extended key, extracts required info and creates corresponding account key. // importExtendedKey processes incoming extended key, extracts required info and creates corresponding account key.
// Once account key is formed, that key is put (if not already) into keystore i.e. key is *encoded* into key file. // Once account key is formed, that key is put (if not already) into keystore i.e. key is *encoded* into key file.
func (m *Manager) importExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error) { func (m *Manager) importExtendedKey(keyPurpose extkeys.KeyPurpose, extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error) {
keyStore, err := m.geth.AccountKeyStore() keyStore, err := m.geth.AccountKeyStore()
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
// imports extended key, create key file (if necessary) // imports extended key, create key file (if necessary)
account, err := keyStore.ImportExtendedKey(extKey, password) account, err := keyStore.ImportExtendedKeyForPurpose(keyPurpose, extKey, password)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -311,20 +333,20 @@ func (m *Manager) Accounts() ([]gethcommon.Address, error) {
} }
} }
if m.selectedAccount == nil { if m.selectedWalletAccount == nil {
return []gethcommon.Address{}, nil return []gethcommon.Address{}, nil
} }
m.refreshSelectedAccount() m.refreshSelectedWalletAccount()
filtered := make([]gethcommon.Address, 0) filtered := make([]gethcommon.Address, 0)
for _, account := range addresses { for _, account := range addresses {
// main account // main account
if m.selectedAccount.Address.Hex() == account.Hex() { if m.selectedWalletAccount.Address.Hex() == account.Hex() {
filtered = append(filtered, account) filtered = append(filtered, account)
} else { } else {
// sub accounts // sub accounts
for _, subAccount := range m.selectedAccount.SubAccounts { for _, subAccount := range m.selectedWalletAccount.SubAccounts {
if subAccount.Address.Hex() == account.Hex() { if subAccount.Address.Hex() == account.Hex() {
filtered = append(filtered, account) filtered = append(filtered, account)
} }
@ -335,13 +357,13 @@ func (m *Manager) Accounts() ([]gethcommon.Address, error) {
return filtered, nil return filtered, nil
} }
// refreshSelectedAccount re-populates list of sub-accounts of the currently selected account (if any) // refreshSelectedWalletAccount re-populates list of sub-accounts of the currently selected account (if any)
func (m *Manager) refreshSelectedAccount() { func (m *Manager) refreshSelectedWalletAccount() {
if m.selectedAccount == nil { if m.selectedWalletAccount == nil {
return return
} }
accountKey := m.selectedAccount.AccountKey accountKey := m.selectedWalletAccount.AccountKey
if accountKey == nil { if accountKey == nil {
return return
} }
@ -351,9 +373,9 @@ func (m *Manager) refreshSelectedAccount() {
if err != nil { if err != nil {
return return
} }
m.selectedAccount = &SelectedExtKey{ m.selectedWalletAccount = &SelectedExtKey{
Address: m.selectedAccount.Address, Address: m.selectedWalletAccount.Address,
AccountKey: m.selectedAccount.AccountKey, AccountKey: m.selectedWalletAccount.AccountKey,
SubAccounts: subAccounts, SubAccounts: subAccounts,
} }
} }

View File

@ -254,6 +254,13 @@ func (s *ManagerTestSuite) TestSelectAccount() {
s.gethServiceProvider.EXPECT().AccountKeyStore().Return(testCase.accountKeyStoreReturn...).AnyTimes() s.gethServiceProvider.EXPECT().AccountKeyStore().Return(testCase.accountKeyStoreReturn...).AnyTimes()
err := s.accManager.SelectAccount(testCase.address, testCase.password) err := s.accManager.SelectAccount(testCase.address, testCase.password)
s.Equal(testCase.expectedError, err) s.Equal(testCase.expectedError, err)
selectedWalletAccount, err := s.accManager.SelectedWalletAccount()
s.NoError(err)
selectedChatAccount, err := s.accManager.SelectedChatAccount()
s.NoError(err)
s.Equal(selectedWalletAccount.AccountKey, selectedChatAccount.AccountKey)
}) })
} }
} }
@ -261,7 +268,7 @@ func (s *ManagerTestSuite) TestSelectAccount() {
func (s *ManagerTestSuite) TestCreateChildAccount() { func (s *ManagerTestSuite) TestCreateChildAccount() {
// First, test the negative case where an account is not selected // First, test the negative case where an account is not selected
// and an address is not provided. // and an address is not provided.
s.accManager.selectedAccount = nil s.accManager.selectedWalletAccount = nil
s.T().Run("fail_noAccount", func(t *testing.T) { s.T().Run("fail_noAccount", func(t *testing.T) {
s.gethServiceProvider.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes() s.gethServiceProvider.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes()
_, _, err := s.accManager.CreateChildAccount("", s.password) _, _, err := s.accManager.CreateChildAccount("", s.password)
@ -329,7 +336,7 @@ func (s *ManagerTestSuite) TestCreateChildAccount() {
func (s *ManagerTestSuite) TestLogout() { func (s *ManagerTestSuite) TestLogout() {
s.accManager.Logout() s.accManager.Logout()
s.Nil(s.accManager.selectedAccount) s.Nil(s.accManager.selectedWalletAccount)
} }
// TestAccounts tests cases for (*Manager).Accounts. // TestAccounts tests cases for (*Manager).Accounts.
@ -351,7 +358,7 @@ func (s *ManagerTestSuite) TestAccounts() {
s.Equal(errAccManager, err) s.Equal(errAccManager, err)
// Selected account is nil but doesn't fail // Selected account is nil but doesn't fail
s.accManager.selectedAccount = nil s.accManager.selectedWalletAccount = nil
s.gethServiceProvider.EXPECT().AccountManager().Return(s.gethAccManager, nil) s.gethServiceProvider.EXPECT().AccountManager().Return(s.gethAccManager, nil)
accs, err = s.accManager.Accounts() accs, err = s.accManager.Accounts()
s.NoError(err) s.NoError(err)

View File

@ -12,7 +12,6 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
gethnode "github.com/ethereum/go-ethereum/node" gethnode "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/status-im/status-go/account" "github.com/status-im/status-go/account"
"github.com/status-im/status-go/node" "github.com/status-im/status-go/node"
"github.com/status-im/status-go/notifications/push/fcm" "github.com/status-im/status-go/notifications/push/fcm"
@ -247,7 +246,7 @@ func (b *StatusBackend) CallPrivateRPC(inputJSON string) (string, error) {
// SendTransaction creates a new transaction and waits until it's complete. // SendTransaction creates a new transaction and waits until it's complete.
func (b *StatusBackend) SendTransaction(sendArgs transactions.SendTxArgs, password string) (hash gethcommon.Hash, err error) { func (b *StatusBackend) SendTransaction(sendArgs transactions.SendTxArgs, password string) (hash gethcommon.Hash, err error) {
verifiedAccount, err := b.getVerifiedAccount(password) verifiedAccount, err := b.getVerifiedWalletAccount(password)
if err != nil { if err != nil {
return hash, err return hash, err
} }
@ -265,7 +264,7 @@ func (b *StatusBackend) SendTransaction(sendArgs transactions.SendTxArgs, passwo
// SignMessage checks the pwd vs the selected account and passes on the signParams // SignMessage checks the pwd vs the selected account and passes on the signParams
// to personalAPI for message signature // to personalAPI for message signature
func (b *StatusBackend) SignMessage(rpcParams personal.SignParams) (hexutil.Bytes, error) { func (b *StatusBackend) SignMessage(rpcParams personal.SignParams) (hexutil.Bytes, error) {
verifiedAccount, err := b.getVerifiedAccount(rpcParams.Password) verifiedAccount, err := b.getVerifiedWalletAccount(rpcParams.Password)
if err != nil { if err != nil {
return hexutil.Bytes{}, err return hexutil.Bytes{}, err
} }
@ -280,7 +279,7 @@ func (b *StatusBackend) Recover(rpcParams personal.RecoverParams) (gethcommon.Ad
// SignTypedData accepts data and password. Gets verified account and signs typed data. // SignTypedData accepts data and password. Gets verified account and signs typed data.
func (b *StatusBackend) SignTypedData(typed typeddata.TypedData, password string) (hexutil.Bytes, error) { func (b *StatusBackend) SignTypedData(typed typeddata.TypedData, password string) (hexutil.Bytes, error) {
account, err := b.getVerifiedAccount(password) account, err := b.getVerifiedWalletAccount(password)
if err != nil { if err != nil {
return hexutil.Bytes{}, err return hexutil.Bytes{}, err
} }
@ -292,19 +291,19 @@ func (b *StatusBackend) SignTypedData(typed typeddata.TypedData, password string
return hexutil.Bytes(sig), err return hexutil.Bytes(sig), err
} }
func (b *StatusBackend) getVerifiedAccount(password string) (*account.SelectedExtKey, error) { func (b *StatusBackend) getVerifiedWalletAccount(password string) (*account.SelectedExtKey, error) {
selectedAccount, err := b.accountManager.SelectedAccount() selectedWalletAccount, err := b.accountManager.SelectedWalletAccount()
if err != nil { if err != nil {
b.log.Error("failed to get a selected account", "err", err) b.log.Error("failed to get a selected account", "err", err)
return nil, err return nil, err
} }
config := b.StatusNode().Config() config := b.StatusNode().Config()
_, err = b.accountManager.VerifyAccountPassword(config.KeyStoreDir, selectedAccount.Address.String(), password) _, err = b.accountManager.VerifyAccountPassword(config.KeyStoreDir, selectedWalletAccount.Address.String(), password)
if err != nil { if err != nil {
b.log.Error("failed to verify account", "account", selectedAccount.Address.String(), "error", err) b.log.Error("failed to verify account", "account", selectedWalletAccount.Address.String(), "error", err)
return nil, err return nil, err
} }
return selectedAccount, nil return selectedWalletAccount, nil
} }
// registerHandlers attaches Status callback handlers to running node // registerHandlers attaches Status callback handlers to running node
@ -403,15 +402,16 @@ func (b *StatusBackend) Logout() error {
// reSelectAccount selects previously selected account, often, after node restart. // reSelectAccount selects previously selected account, often, after node restart.
func (b *StatusBackend) reSelectAccount() error { func (b *StatusBackend) reSelectAccount() error {
selectedAccount, err := b.AccountManager().SelectedAccount() selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
if selectedAccount == nil || err == account.ErrNoAccountSelected { if selectedChatAccount == nil || err == account.ErrNoAccountSelected {
return nil return nil
} }
whisperService, err := b.statusNode.WhisperService() whisperService, err := b.statusNode.WhisperService()
switch err { switch err {
case node.ErrServiceUnknown: // Whisper was never registered case node.ErrServiceUnknown: // Whisper was never registered
case nil: case nil:
if err := whisperService.SelectKeyPair(selectedAccount.AccountKey.PrivateKey); err != nil { if err := whisperService.SelectKeyPair(selectedChatAccount.AccountKey.PrivateKey); err != nil {
return ErrWhisperIdentityInjectionFailure return ErrWhisperIdentityInjectionFailure
} }
default: default:
@ -432,7 +432,7 @@ func (b *StatusBackend) SelectAccount(address, password string) error {
if err != nil { if err != nil {
return err return err
} }
acc, err := b.accountManager.SelectedAccount() chatAccount, err := b.accountManager.SelectedChatAccount()
if err != nil { if err != nil {
return err return err
} }
@ -441,7 +441,7 @@ func (b *StatusBackend) SelectAccount(address, password string) error {
switch err { switch err {
case node.ErrServiceUnknown: // Whisper was never registered case node.ErrServiceUnknown: // Whisper was never registered
case nil: case nil:
if err := whisperService.SelectKeyPair(acc.AccountKey.PrivateKey); err != nil { if err := whisperService.SelectKeyPair(chatAccount.AccountKey.PrivateKey); err != nil {
return ErrWhisperIdentityInjectionFailure return ErrWhisperIdentityInjectionFailure
} }
default: default:
@ -483,7 +483,7 @@ func appendIf(condition bool, services []gethnode.ServiceConstructor, service ge
// CreateContactCode create or return the latest contact code // CreateContactCode create or return the latest contact code
func (b *StatusBackend) CreateContactCode() (string, error) { func (b *StatusBackend) CreateContactCode() (string, error) {
selectedAccount, err := b.AccountManager().SelectedAccount() selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
if err != nil { if err != nil {
return "", err return "", err
} }
@ -493,7 +493,7 @@ func (b *StatusBackend) CreateContactCode() (string, error) {
return "", err return "", err
} }
bundle, err := st.GetBundle(selectedAccount.AccountKey.PrivateKey) bundle, err := st.GetBundle(selectedChatAccount.AccountKey.PrivateKey)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -503,7 +503,7 @@ func (b *StatusBackend) CreateContactCode() (string, error) {
// ProcessContactCode process and adds the someone else's bundle // ProcessContactCode process and adds the someone else's bundle
func (b *StatusBackend) ProcessContactCode(contactCode string) error { func (b *StatusBackend) ProcessContactCode(contactCode string) error {
selectedAccount, err := b.AccountManager().SelectedAccount() selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
if err != nil { if err != nil {
return err return err
} }
@ -519,7 +519,7 @@ func (b *StatusBackend) ProcessContactCode(contactCode string) error {
return err return err
} }
if _, err := st.ProcessPublicBundle(selectedAccount.AccountKey.PrivateKey, bundle); err != nil { if _, err := st.ProcessPublicBundle(selectedChatAccount.AccountKey.PrivateKey, bundle); err != nil {
b.log.Error("error adding bundle", "err", err) b.log.Error("error adding bundle", "err", err)
return err return err
} }
@ -544,17 +544,17 @@ func (b *StatusBackend) ExtractGroupMembershipSignatures(signaturePairs [][2]str
// SignGroupMembership signs a piece of data containing membership information // SignGroupMembership signs a piece of data containing membership information
func (b *StatusBackend) SignGroupMembership(content string) (string, error) { func (b *StatusBackend) SignGroupMembership(content string) (string, error) {
selectedAccount, err := b.AccountManager().SelectedAccount() selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
if err != nil { if err != nil {
return "", err return "", err
} }
return crypto.Sign(content, selectedAccount.AccountKey.PrivateKey) return crypto.Sign(content, selectedChatAccount.AccountKey.PrivateKey)
} }
// EnableInstallation enables an installation for multi-device sync. // EnableInstallation enables an installation for multi-device sync.
func (b *StatusBackend) EnableInstallation(installationID string) error { func (b *StatusBackend) EnableInstallation(installationID string) error {
selectedAccount, err := b.AccountManager().SelectedAccount() selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
if err != nil { if err != nil {
return err return err
} }
@ -564,7 +564,7 @@ func (b *StatusBackend) EnableInstallation(installationID string) error {
return err return err
} }
if err := st.EnableInstallation(&selectedAccount.AccountKey.PrivateKey.PublicKey, installationID); err != nil { if err := st.EnableInstallation(&selectedChatAccount.AccountKey.PrivateKey.PublicKey, installationID); err != nil {
b.log.Error("error enabling installation", "err", err) b.log.Error("error enabling installation", "err", err)
return err return err
} }
@ -574,7 +574,7 @@ func (b *StatusBackend) EnableInstallation(installationID string) error {
// DisableInstallation disables an installation for multi-device sync. // DisableInstallation disables an installation for multi-device sync.
func (b *StatusBackend) DisableInstallation(installationID string) error { func (b *StatusBackend) DisableInstallation(installationID string) error {
selectedAccount, err := b.AccountManager().SelectedAccount() selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
if err != nil { if err != nil {
return err return err
} }
@ -584,7 +584,7 @@ func (b *StatusBackend) DisableInstallation(installationID string) error {
return err return err
} }
if err := st.DisableInstallation(&selectedAccount.AccountKey.PrivateKey.PublicKey, installationID); err != nil { if err := st.DisableInstallation(&selectedChatAccount.AccountKey.PrivateKey.PublicKey, installationID); err != nil {
b.log.Error("error disabling installation", "err", err) b.log.Error("error disabling installation", "err", err)
return err return err
} }

View File

@ -207,7 +207,7 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() {
s.NoError(err) s.NoError(err)
// make sure that no account is selected by default // make sure that no account is selected by default
selectedAccount, err := s.Backend.AccountManager().SelectedAccount() selectedAccount, err := s.Backend.AccountManager().SelectedWalletAccount()
s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be") s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be")
s.Nil(selectedAccount) s.Nil(selectedAccount)
@ -225,7 +225,7 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() {
s.NoError(s.Backend.StopNode()) s.NoError(s.Backend.StopNode())
// make sure that account is still selected // make sure that account is still selected
selectedAccount, err = s.Backend.AccountManager().SelectedAccount() selectedAccount, err = s.Backend.AccountManager().SelectedWalletAccount()
s.NoError(err) s.NoError(err)
s.NotNil(selectedAccount) s.NotNil(selectedAccount)
s.Equal(selectedAccount.Address.Hex(), address2, "incorrect address selected") s.Equal(selectedAccount.Address.Hex(), address2, "incorrect address selected")
@ -234,7 +234,7 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() {
s.Require().NoError(s.Backend.StartNode(&preservedNodeConfig)) s.Require().NoError(s.Backend.StartNode(&preservedNodeConfig))
// re-check selected account (account2 MUST be selected) // re-check selected account (account2 MUST be selected)
selectedAccount, err = s.Backend.AccountManager().SelectedAccount() selectedAccount, err = s.Backend.AccountManager().SelectedWalletAccount()
s.NoError(err) s.NoError(err)
s.NotNil(selectedAccount) s.NotNil(selectedAccount)
s.Equal(selectedAccount.Address.Hex(), address2, "incorrect address selected") s.Equal(selectedAccount.Address.Hex(), address2, "incorrect address selected")
@ -247,7 +247,7 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() {
s.NoError(s.Backend.Logout()) s.NoError(s.Backend.Logout())
s.RestartTestNode() s.RestartTestNode()
selectedAccount, err = s.Backend.AccountManager().SelectedAccount() selectedAccount, err = s.Backend.AccountManager().SelectedWalletAccount()
s.EqualError(account.ErrNoAccountSelected, err.Error()) s.EqualError(account.ErrNoAccountSelected, err.Error())
s.Nil(selectedAccount) s.Nil(selectedAccount)
} }

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"testing" "testing"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/status-go/account" "github.com/status-im/status-go/account"
e2e "github.com/status-im/status-go/t/e2e" e2e "github.com/status-im/status-go/t/e2e"
@ -141,30 +142,44 @@ func (s *WhisperTestSuite) TestSelectedAccountOnRestart() {
// create test accounts // create test accounts
address1, pubKey1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) address1, pubKey1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
s.NoError(err) s.NoError(err)
address2, pubKey2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) address2, pubKey2, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account2.Password)
s.NoError(err) s.NoError(err)
// make sure that identity is not (yet injected) // make sure that identity is not (yet injected)
s.False(whisperService.HasKeyPair(pubKey1), "identity already present in whisper") s.False(whisperService.HasKeyPair(pubKey1), "identity already present in whisper")
// make sure that no account is selected by default // make sure that no account is selected by default
selectedAccount, err := s.Backend.AccountManager().SelectedAccount() selectedWalletAccount, err := s.Backend.AccountManager().SelectedWalletAccount()
s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be") s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be")
s.Nil(selectedAccount) s.Nil(selectedWalletAccount)
// select account // make sure that no chat account is selected by default
selectedChatAccount, err := s.Backend.AccountManager().SelectedChatAccount()
s.EqualError(account.ErrNoAccountSelected, err.Error(), "account selected, but should not be")
s.Nil(selectedChatAccount)
// select account with wrong password
err = s.Backend.SelectAccount(address1, "wrongPassword") err = s.Backend.SelectAccount(address1, "wrongPassword")
expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase") expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase")
s.EqualError(expectedErr, err.Error()) s.EqualError(expectedErr, err.Error())
// select account with right password
s.NoError(s.Backend.SelectAccount(address1, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(address1, TestConfig.Account1.Password))
s.True(whisperService.HasKeyPair(pubKey1), "identity not injected into whisper") selectedChatAccount1, err := s.Backend.AccountManager().SelectedChatAccount()
s.NoError(err)
selectedChatPubKey1 := hexutil.Encode(crypto.FromECDSAPub(&selectedChatAccount1.AccountKey.PrivateKey.PublicKey))
s.Equal(selectedChatPubKey1, pubKey1)
s.True(whisperService.HasKeyPair(selectedChatPubKey1), "identity not injected into whisper")
// select another account, make sure that previous account is wiped out from Whisper cache // select another account, make sure that previous account is wiped out from Whisper cache
s.False(whisperService.HasKeyPair(pubKey2), "identity already present in whisper") s.False(whisperService.HasKeyPair(pubKey2), "identity already present in whisper")
s.NoError(s.Backend.SelectAccount(address2, TestConfig.Account1.Password)) s.NoError(s.Backend.SelectAccount(address2, TestConfig.Account2.Password))
s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") selectedChatAccount2, err := s.Backend.AccountManager().SelectedChatAccount()
s.False(whisperService.HasKeyPair(pubKey1), "identity should be removed, but it is still present in whisper") s.NoError(err)
selectedChatPubKey2 := hexutil.Encode(crypto.FromECDSAPub(&selectedChatAccount2.AccountKey.PrivateKey.PublicKey))
s.Equal(selectedChatPubKey2, pubKey2)
s.True(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into whisper")
s.False(whisperService.HasKeyPair(selectedChatPubKey1), "identity should be removed, but it is still present in whisper")
// stop node (and all of its sub-protocols) // stop node (and all of its sub-protocols)
nodeConfig := s.Backend.StatusNode().Config() nodeConfig := s.Backend.StatusNode().Config()
@ -176,32 +191,59 @@ func (s *WhisperTestSuite) TestSelectedAccountOnRestart() {
s.Require().NoError(s.Backend.StartNode(&preservedNodeConfig)) s.Require().NoError(s.Backend.StartNode(&preservedNodeConfig))
// re-check selected account (account2 MUST be selected) // re-check selected account (account2 MUST be selected)
selectedAccount, err = s.Backend.AccountManager().SelectedAccount() selectedWalletAccount, err = s.Backend.AccountManager().SelectedWalletAccount()
s.NoError(err) s.NoError(err)
s.NotNil(selectedAccount) s.NotNil(selectedWalletAccount)
s.Equal(selectedAccount.Address.Hex(), address2, "incorrect address selected") s.Equal(selectedWalletAccount.Address.Hex(), address2, "incorrect address selected")
// make sure that Whisper gets identity re-injected // make sure that Whisper gets identity re-injected
whisperService = s.WhisperService() whisperService = s.WhisperService()
s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") s.True(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into whisper")
s.False(whisperService.HasKeyPair(pubKey1), "identity should not be present, but it is still present in whisper") s.False(whisperService.HasKeyPair(selectedChatPubKey1), "identity should not be present, but it is still present in whisper")
// now restart node using RestartNode() method, and make sure that account is still available // now restart node using RestartNode() method, and make sure that account is still available
s.RestartTestNode() s.RestartTestNode()
defer s.StopTestBackend() defer s.StopTestBackend()
whisperService = s.WhisperService() whisperService = s.WhisperService()
s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") s.True(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into whisper")
s.False(whisperService.HasKeyPair(pubKey1), "identity should not be present, but it is still present in whisper") s.False(whisperService.HasKeyPair(selectedChatPubKey1), "identity should not be present, but it is still present in whisper")
// now logout, and make sure that on restart no account is selected (i.e. logout works properly) // now logout, and make sure that on restart no account is selected (i.e. logout works properly)
s.NoError(s.Backend.Logout()) s.NoError(s.Backend.Logout())
s.RestartTestNode() s.RestartTestNode()
whisperService = s.WhisperService() whisperService = s.WhisperService()
s.False(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") s.False(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into whisper")
s.False(whisperService.HasKeyPair(pubKey1), "identity should not be present, but it is still present in whisper") s.False(whisperService.HasKeyPair(selectedChatPubKey1), "identity should not be present, but it is still present in whisper")
selectedAccount, err = s.Backend.AccountManager().SelectedAccount() selectedWalletAccount, err = s.Backend.AccountManager().SelectedWalletAccount()
s.EqualError(account.ErrNoAccountSelected, err.Error()) s.EqualError(account.ErrNoAccountSelected, err.Error())
s.Nil(selectedAccount) s.Nil(selectedWalletAccount)
selectedChatAccount, err = s.Backend.AccountManager().SelectedChatAccount()
s.EqualError(account.ErrNoAccountSelected, err.Error())
s.Nil(selectedChatAccount)
}
func (s *WhisperTestSuite) TestSelectedChatKeyIsUsedInWhisper() {
s.StartTestBackend()
defer s.StopTestBackend()
whisperService, err := s.Backend.StatusNode().WhisperService()
s.NoError(err)
// create an account
address, _, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password)
s.NoError(err)
// select account
s.NoError(s.Backend.SelectAccount(address, TestConfig.Account1.Password))
// Get the chat account
selectedChatAccount, err := s.Backend.AccountManager().SelectedChatAccount()
s.NoError(err)
// chat key should be injected in whisper
selectedChatPubKey := hexutil.Encode(crypto.FromECDSAPub(&selectedChatAccount.AccountKey.PrivateKey.PublicKey))
s.True(whisperService.HasKeyPair(selectedChatPubKey), "identity not injected in whisper")
} }