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:
parent
54022561f5
commit
06d4a99c09
|
@ -35,8 +35,9 @@ type GethServiceProvider interface {
|
||||||
type Manager struct {
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue