diff --git a/account/accounts.go b/account/accounts.go index abc450d57..d5989261b 100644 --- a/account/accounts.go +++ b/account/accounts.go @@ -35,8 +35,9 @@ type GethServiceProvider interface { type Manager struct { geth GethServiceProvider - mu sync.RWMutex - selectedAccount *SelectedExtKey // account that was processed during the last call to SelectAccount() + mu sync.RWMutex + 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. @@ -69,7 +70,7 @@ func (m *Manager) CreateAccount(password string) (address, pubKey, mnemonic stri } // 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 { return "", "", "", err } @@ -89,8 +90,8 @@ func (m *Manager) CreateChildAccount(parentAddress, password string) (address, p return "", "", err } - if parentAddress == "" && m.selectedAccount != nil { // derive from selected account by default - parentAddress = m.selectedAccount.Address.Hex() + if parentAddress == "" && m.selectedWalletAccount != nil { // derive from selected account by default + parentAddress = m.selectedWalletAccount.Address.Hex() } if parentAddress == "" { @@ -124,14 +125,14 @@ func (m *Manager) CreateChildAccount(parentAddress, password string) (address, p accountKey.SubAccountIndex++ // 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 { return } // update in-memory selected account - if m.selectedAccount != nil { - m.selectedAccount.AccountKey = accountKey + if m.selectedWalletAccount != nil { + m.selectedWalletAccount.AccountKey = accountKey } 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 - address, pubKey, err = m.importExtendedKey(extKey, password) + address, pubKey, err = m.importExtendedKey(extkeys.KeyPurposeWallet, extKey, password) if err != nil { return } @@ -240,7 +241,16 @@ func (m *Manager) SelectAccount(address, password string) error { if err != nil { 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, AccountKey: accountKey, SubAccounts: subAccounts, @@ -249,35 +259,47 @@ func (m *Manager) SelectAccount(address, password string) error { return nil } -// SelectedAccount returns currently selected account -func (m *Manager) SelectedAccount() (*SelectedExtKey, error) { +// SelectedWalletAccount returns currently selected wallet account +func (m *Manager) SelectedWalletAccount() (*SelectedExtKey, error) { m.mu.RLock() defer m.mu.RUnlock() - if m.selectedAccount == nil { + if m.selectedWalletAccount == nil { 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() { m.mu.Lock() 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. // 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() if err != nil { return "", "", err } // imports extended key, create key file (if necessary) - account, err := keyStore.ImportExtendedKey(extKey, password) + account, err := keyStore.ImportExtendedKeyForPurpose(keyPurpose, extKey, password) if err != nil { 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 } - m.refreshSelectedAccount() + m.refreshSelectedWalletAccount() filtered := make([]gethcommon.Address, 0) for _, account := range addresses { // main account - if m.selectedAccount.Address.Hex() == account.Hex() { + if m.selectedWalletAccount.Address.Hex() == account.Hex() { filtered = append(filtered, account) } else { // sub accounts - for _, subAccount := range m.selectedAccount.SubAccounts { + for _, subAccount := range m.selectedWalletAccount.SubAccounts { if subAccount.Address.Hex() == account.Hex() { filtered = append(filtered, account) } @@ -335,13 +357,13 @@ func (m *Manager) Accounts() ([]gethcommon.Address, error) { return filtered, nil } -// refreshSelectedAccount re-populates list of sub-accounts of the currently selected account (if any) -func (m *Manager) refreshSelectedAccount() { - if m.selectedAccount == nil { +// refreshSelectedWalletAccount re-populates list of sub-accounts of the currently selected account (if any) +func (m *Manager) refreshSelectedWalletAccount() { + if m.selectedWalletAccount == nil { return } - accountKey := m.selectedAccount.AccountKey + accountKey := m.selectedWalletAccount.AccountKey if accountKey == nil { return } @@ -351,9 +373,9 @@ func (m *Manager) refreshSelectedAccount() { if err != nil { return } - m.selectedAccount = &SelectedExtKey{ - Address: m.selectedAccount.Address, - AccountKey: m.selectedAccount.AccountKey, + m.selectedWalletAccount = &SelectedExtKey{ + Address: m.selectedWalletAccount.Address, + AccountKey: m.selectedWalletAccount.AccountKey, SubAccounts: subAccounts, } } diff --git a/account/accounts_test.go b/account/accounts_test.go index 581949778..11eab7b70 100644 --- a/account/accounts_test.go +++ b/account/accounts_test.go @@ -254,6 +254,13 @@ func (s *ManagerTestSuite) TestSelectAccount() { s.gethServiceProvider.EXPECT().AccountKeyStore().Return(testCase.accountKeyStoreReturn...).AnyTimes() err := s.accManager.SelectAccount(testCase.address, testCase.password) 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() { // First, test the negative case where an account is not selected // and an address is not provided. - s.accManager.selectedAccount = nil + s.accManager.selectedWalletAccount = nil s.T().Run("fail_noAccount", func(t *testing.T) { s.gethServiceProvider.EXPECT().AccountKeyStore().Return(s.keyStore, nil).AnyTimes() _, _, err := s.accManager.CreateChildAccount("", s.password) @@ -329,7 +336,7 @@ func (s *ManagerTestSuite) TestCreateChildAccount() { func (s *ManagerTestSuite) TestLogout() { s.accManager.Logout() - s.Nil(s.accManager.selectedAccount) + s.Nil(s.accManager.selectedWalletAccount) } // TestAccounts tests cases for (*Manager).Accounts. @@ -351,7 +358,7 @@ func (s *ManagerTestSuite) TestAccounts() { s.Equal(errAccManager, err) // Selected account is nil but doesn't fail - s.accManager.selectedAccount = nil + s.accManager.selectedWalletAccount = nil s.gethServiceProvider.EXPECT().AccountManager().Return(s.gethAccManager, nil) accs, err = s.accManager.Accounts() s.NoError(err) diff --git a/api/backend.go b/api/backend.go index d93b26274..df5a57287 100644 --- a/api/backend.go +++ b/api/backend.go @@ -12,7 +12,6 @@ import ( "github.com/ethereum/go-ethereum/log" gethnode "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/status-im/status-go/account" "github.com/status-im/status-go/node" "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. 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 { 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 // to personalAPI for message signature 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 { 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. 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 { return hexutil.Bytes{}, err } @@ -292,19 +291,19 @@ func (b *StatusBackend) SignTypedData(typed typeddata.TypedData, password string return hexutil.Bytes(sig), err } -func (b *StatusBackend) getVerifiedAccount(password string) (*account.SelectedExtKey, error) { - selectedAccount, err := b.accountManager.SelectedAccount() +func (b *StatusBackend) getVerifiedWalletAccount(password string) (*account.SelectedExtKey, error) { + selectedWalletAccount, err := b.accountManager.SelectedWalletAccount() if err != nil { b.log.Error("failed to get a selected account", "err", err) return nil, err } 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 { - 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 selectedAccount, nil + return selectedWalletAccount, nil } // 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. func (b *StatusBackend) reSelectAccount() error { - selectedAccount, err := b.AccountManager().SelectedAccount() - if selectedAccount == nil || err == account.ErrNoAccountSelected { + selectedChatAccount, err := b.AccountManager().SelectedChatAccount() + if selectedChatAccount == nil || err == account.ErrNoAccountSelected { return nil } + whisperService, err := b.statusNode.WhisperService() switch err { case node.ErrServiceUnknown: // Whisper was never registered case nil: - if err := whisperService.SelectKeyPair(selectedAccount.AccountKey.PrivateKey); err != nil { + if err := whisperService.SelectKeyPair(selectedChatAccount.AccountKey.PrivateKey); err != nil { return ErrWhisperIdentityInjectionFailure } default: @@ -432,7 +432,7 @@ func (b *StatusBackend) SelectAccount(address, password string) error { if err != nil { return err } - acc, err := b.accountManager.SelectedAccount() + chatAccount, err := b.accountManager.SelectedChatAccount() if err != nil { return err } @@ -441,7 +441,7 @@ func (b *StatusBackend) SelectAccount(address, password string) error { switch err { case node.ErrServiceUnknown: // Whisper was never registered case nil: - if err := whisperService.SelectKeyPair(acc.AccountKey.PrivateKey); err != nil { + if err := whisperService.SelectKeyPair(chatAccount.AccountKey.PrivateKey); err != nil { return ErrWhisperIdentityInjectionFailure } default: @@ -483,7 +483,7 @@ func appendIf(condition bool, services []gethnode.ServiceConstructor, service ge // CreateContactCode create or return the latest contact code func (b *StatusBackend) CreateContactCode() (string, error) { - selectedAccount, err := b.AccountManager().SelectedAccount() + selectedChatAccount, err := b.AccountManager().SelectedChatAccount() if err != nil { return "", err } @@ -493,7 +493,7 @@ func (b *StatusBackend) CreateContactCode() (string, error) { return "", err } - bundle, err := st.GetBundle(selectedAccount.AccountKey.PrivateKey) + bundle, err := st.GetBundle(selectedChatAccount.AccountKey.PrivateKey) if err != nil { return "", err } @@ -503,7 +503,7 @@ func (b *StatusBackend) CreateContactCode() (string, error) { // ProcessContactCode process and adds the someone else's bundle func (b *StatusBackend) ProcessContactCode(contactCode string) error { - selectedAccount, err := b.AccountManager().SelectedAccount() + selectedChatAccount, err := b.AccountManager().SelectedChatAccount() if err != nil { return err } @@ -519,7 +519,7 @@ func (b *StatusBackend) ProcessContactCode(contactCode string) error { 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) return err } @@ -544,17 +544,17 @@ func (b *StatusBackend) ExtractGroupMembershipSignatures(signaturePairs [][2]str // SignGroupMembership signs a piece of data containing membership information func (b *StatusBackend) SignGroupMembership(content string) (string, error) { - selectedAccount, err := b.AccountManager().SelectedAccount() + selectedChatAccount, err := b.AccountManager().SelectedChatAccount() if err != nil { return "", err } - return crypto.Sign(content, selectedAccount.AccountKey.PrivateKey) + return crypto.Sign(content, selectedChatAccount.AccountKey.PrivateKey) } // EnableInstallation enables an installation for multi-device sync. func (b *StatusBackend) EnableInstallation(installationID string) error { - selectedAccount, err := b.AccountManager().SelectedAccount() + selectedChatAccount, err := b.AccountManager().SelectedChatAccount() if err != nil { return err } @@ -564,7 +564,7 @@ func (b *StatusBackend) EnableInstallation(installationID string) error { 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) return err } @@ -574,7 +574,7 @@ func (b *StatusBackend) EnableInstallation(installationID string) error { // DisableInstallation disables an installation for multi-device sync. func (b *StatusBackend) DisableInstallation(installationID string) error { - selectedAccount, err := b.AccountManager().SelectedAccount() + selectedChatAccount, err := b.AccountManager().SelectedChatAccount() if err != nil { return err } @@ -584,7 +584,7 @@ func (b *StatusBackend) DisableInstallation(installationID string) error { 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) return err } diff --git a/t/e2e/accounts/accounts_test.go b/t/e2e/accounts/accounts_test.go index 8d7f824e8..5530562a1 100644 --- a/t/e2e/accounts/accounts_test.go +++ b/t/e2e/accounts/accounts_test.go @@ -207,7 +207,7 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() { s.NoError(err) // 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.Nil(selectedAccount) @@ -225,7 +225,7 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() { s.NoError(s.Backend.StopNode()) // make sure that account is still selected - selectedAccount, err = s.Backend.AccountManager().SelectedAccount() + selectedAccount, err = s.Backend.AccountManager().SelectedWalletAccount() s.NoError(err) s.NotNil(selectedAccount) s.Equal(selectedAccount.Address.Hex(), address2, "incorrect address selected") @@ -234,7 +234,7 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() { s.Require().NoError(s.Backend.StartNode(&preservedNodeConfig)) // re-check selected account (account2 MUST be selected) - selectedAccount, err = s.Backend.AccountManager().SelectedAccount() + selectedAccount, err = s.Backend.AccountManager().SelectedWalletAccount() s.NoError(err) s.NotNil(selectedAccount) s.Equal(selectedAccount.Address.Hex(), address2, "incorrect address selected") @@ -247,7 +247,7 @@ func (s *AccountsTestSuite) TestSelectedAccountOnRestart() { s.NoError(s.Backend.Logout()) s.RestartTestNode() - selectedAccount, err = s.Backend.AccountManager().SelectedAccount() + selectedAccount, err = s.Backend.AccountManager().SelectedWalletAccount() s.EqualError(account.ErrNoAccountSelected, err.Error()) s.Nil(selectedAccount) } diff --git a/t/e2e/whisper/whisper_test.go b/t/e2e/whisper/whisper_test.go index 81179720e..52dafdd38 100644 --- a/t/e2e/whisper/whisper_test.go +++ b/t/e2e/whisper/whisper_test.go @@ -5,6 +5,7 @@ import ( "errors" "testing" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/status-im/status-go/account" e2e "github.com/status-im/status-go/t/e2e" @@ -141,30 +142,44 @@ func (s *WhisperTestSuite) TestSelectedAccountOnRestart() { // create test accounts address1, pubKey1, _, err := s.Backend.AccountManager().CreateAccount(TestConfig.Account1.Password) 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) // make sure that identity is not (yet injected) s.False(whisperService.HasKeyPair(pubKey1), "identity already present in whisper") // 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.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") expectedErr := errors.New("cannot retrieve a valid key for a given account: could not decrypt key with given passphrase") s.EqualError(expectedErr, err.Error()) + // select account with right 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 s.False(whisperService.HasKeyPair(pubKey2), "identity already present in whisper") - s.NoError(s.Backend.SelectAccount(address2, TestConfig.Account1.Password)) - s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") - s.False(whisperService.HasKeyPair(pubKey1), "identity should be removed, but it is still present in whisper") + s.NoError(s.Backend.SelectAccount(address2, TestConfig.Account2.Password)) + selectedChatAccount2, err := s.Backend.AccountManager().SelectedChatAccount() + 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) nodeConfig := s.Backend.StatusNode().Config() @@ -176,32 +191,59 @@ func (s *WhisperTestSuite) TestSelectedAccountOnRestart() { s.Require().NoError(s.Backend.StartNode(&preservedNodeConfig)) // re-check selected account (account2 MUST be selected) - selectedAccount, err = s.Backend.AccountManager().SelectedAccount() + selectedWalletAccount, err = s.Backend.AccountManager().SelectedWalletAccount() s.NoError(err) - s.NotNil(selectedAccount) - s.Equal(selectedAccount.Address.Hex(), address2, "incorrect address selected") + s.NotNil(selectedWalletAccount) + s.Equal(selectedWalletAccount.Address.Hex(), address2, "incorrect address selected") // make sure that Whisper gets identity re-injected whisperService = s.WhisperService() - s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") - s.False(whisperService.HasKeyPair(pubKey1), "identity should not be present, but it is still present in whisper") + s.True(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into 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 s.RestartTestNode() defer s.StopTestBackend() whisperService = s.WhisperService() - s.True(whisperService.HasKeyPair(pubKey2), "identity not injected into whisper") - s.False(whisperService.HasKeyPair(pubKey1), "identity should not be present, but it is still present in whisper") + s.True(whisperService.HasKeyPair(selectedChatPubKey2), "identity not injected into 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) s.NoError(s.Backend.Logout()) s.RestartTestNode() whisperService = s.WhisperService() - s.False(whisperService.HasKeyPair(pubKey2), "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(selectedChatPubKey2), "identity not injected into 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.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") }