diff --git a/account/accounts.go b/account/accounts.go index e83bc8b8f..1ee931139 100644 --- a/account/accounts.go +++ b/account/accounts.go @@ -61,8 +61,8 @@ func (m *Manager) AccountsGenerator() *generator.Generator { // BIP44-compatible keys are generated: CKD#1 is stored as account key, CKD#2 stored as sub-account root // Public key of CKD#1 is returned, with CKD#2 securely encoded into account key file (to be used for // sub-account derivations) -func (m *Manager) CreateAccount(password string) (generator.IdentifiedAccountInfo, Info, string, error) { - var mkInfo generator.IdentifiedAccountInfo +func (m *Manager) CreateAccount(password string) (generator.GeneratedAccountInfo, Info, string, error) { + var mkInfo generator.GeneratedAccountInfo info := Info{} // generate mnemonic phrase @@ -82,7 +82,7 @@ func (m *Manager) CreateAccount(password string) (generator.IdentifiedAccountInf return mkInfo, info, "", fmt.Errorf("can not create master extended key: %v", err) } - mkInfo = generator.IdentifiedAccountInfoFromExtKey(extKey) + mkInfo = generator.GeneratedAccountInfoFromExtKey(mnemonic, extKey) // import created key into account keystore info.WalletAddress, info.WalletPubKey, err = m.importExtendedKey(extkeys.KeyPurposeWallet, extKey, password) diff --git a/account/generator/account.go b/account/generator/account.go index b121b7890..c1d1166a5 100644 --- a/account/generator/account.go +++ b/account/generator/account.go @@ -3,10 +3,12 @@ package generator import ( "crypto/ecdsa" "crypto/sha256" + "time" "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/extkeys" + "github.com/status-im/status-go/multiaccounts" ) type account struct { @@ -80,11 +82,18 @@ type GeneratedAndDerivedAccountInfo struct { Derived map[string]AccountInfo `json:"derived"` } -func IdentifiedAccountInfoFromExtKey(extKey *extkeys.ExtendedKey) IdentifiedAccountInfo { +func GeneratedAccountInfoFromExtKey(mnemonic string, extKey *extkeys.ExtendedKey) GeneratedAccountInfo { acc := account{ privateKey: extKey.ToECDSA(), extendedKey: extKey, } - return acc.toIdentifiedAccountInfo("") + return acc.toGeneratedAccountInfo("", mnemonic) +} + +func (ga *GeneratedAccountInfo) ToMultiAccount() *multiaccounts.Account { + return &multiaccounts.Account{ + Timestamp: time.Now().Unix(), + KeyUID: ga.KeyUID, + } } diff --git a/account/utils.go b/account/utils.go index a8310dbe4..83f9a3130 100644 --- a/account/utils.go +++ b/account/utils.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/multiaccounts" ) // errors @@ -15,10 +16,11 @@ var ( ) type LoginParams struct { - ChatAddress types.Address `json:"chatAddress"` - Password string `json:"password"` - MainAccount types.Address `json:"mainAccount"` - WatchAddresses []types.Address `json:"watchAddresses"` + ChatAddress types.Address `json:"chatAddress"` + Password string `json:"password"` + MainAccount types.Address `json:"mainAccount"` + WatchAddresses []types.Address `json:"watchAddresses"` + MultiAccount *multiaccounts.Account `json:"multiAccount"` } type ErrZeroAddress struct { diff --git a/api/backend_test.go b/api/backend_test.go index 933cd7b95..070416e4d 100644 --- a/api/backend_test.go +++ b/api/backend_test.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/status-im/status-go/account/generator" "io/ioutil" "math/rand" "os" @@ -181,15 +182,20 @@ func TestBackendAccountsConcurrently(t *testing.T) { var wgCreateAccounts sync.WaitGroup count := 3 - addressCh := make(chan [3]string, count) // use buffered channel to avoid blocking + type AccountData struct { + MasterAccount generator.GeneratedAccountInfo + AccountInfo account.Info + Password string + } + addressCh := make(chan AccountData, count) // use buffered channel to avoid blocking // create new accounts concurrently for i := 0; i < count; i++ { wgCreateAccounts.Add(1) go func(pass string) { - _, accountInfo, _, err := backend.AccountManager().CreateAccount(pass) + MKInfo, accountInfo, _, err := backend.AccountManager().CreateAccount(pass) assert.NoError(t, err) - addressCh <- [...]string{accountInfo.WalletAddress, accountInfo.ChatAddress, pass} + addressCh <- AccountData{MKInfo, accountInfo, pass} wgCreateAccounts.Done() }("password-00" + fmt.Sprint(i)) } @@ -200,17 +206,18 @@ func TestBackendAccountsConcurrently(t *testing.T) { // select, reselect or logout concurrently var wg sync.WaitGroup - for tuple := range addressCh { + for accountData := range addressCh { wg.Add(1) - go func(tuple [3]string) { + go func(accountData AccountData) { loginParams := account.LoginParams{ - MainAccount: types.HexToAddress(tuple[0]), - ChatAddress: types.HexToAddress(tuple[1]), - Password: tuple[2], + MainAccount: types.HexToAddress(accountData.AccountInfo.WalletAddress), + ChatAddress: types.HexToAddress(accountData.AccountInfo.ChatAddress), + Password: accountData.Password, + MultiAccount: accountData.MasterAccount.ToMultiAccount(), } assert.NoError(t, backend.SelectAccount(loginParams)) wg.Done() - }(tuple) + }(accountData) wg.Add(1) go func() { @@ -235,6 +242,8 @@ func TestBackendInjectChatAccount(t *testing.T) { require.NoError(t, backend.StopNode()) }() + backend.account = &multiaccounts.Account{KeyUID: "0xdeadbeef"} + chatPrivKey, err := gethcrypto.GenerateKey() require.NoError(t, err) encryptionPrivKey, err := gethcrypto.GenerateKey() @@ -446,6 +455,8 @@ func TestSignHash(t *testing.T) { require.NoError(t, backend.StopNode()) }() + backend.account = &multiaccounts.Account{KeyUID: "0xdeadbeef"} + var testCases = []struct { name string chatPrivKeyHex string diff --git a/api/geth_backend.go b/api/geth_backend.go index c8c624072..9f5be6352 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -1101,6 +1101,10 @@ func (b *GethStatusBackend) SelectAccount(loginParams account.LoginParams) error return err } + if loginParams.MultiAccount != nil { + b.account = loginParams.MultiAccount + } + if err := b.injectAccountsIntoServices(); err != nil { return err } diff --git a/services/status/service.go b/services/status/service.go index 0b15caf85..aed81eba2 100644 --- a/services/status/service.go +++ b/services/status/service.go @@ -24,7 +24,7 @@ type WhisperService interface { type AccountManager interface { AddressToDecryptedAccount(string, string) (types.Account, *types.Key, error) SelectAccount(account.LoginParams) error - CreateAccount(password string) (mkInfo generator.IdentifiedAccountInfo, accountInfo account.Info, mnemonic string, err error) + CreateAccount(password string) (mkInfo generator.GeneratedAccountInfo, accountInfo account.Info, mnemonic string, err error) } // Service represents our own implementation of status status operations.