From 5d62a9eef4a6676d62a9a51cdadea596d3d9a658 Mon Sep 17 00:00:00 2001 From: frank Date: Thu, 1 Jun 2023 20:57:05 +0800 Subject: [PATCH] Fix/mobile issue 16043 (#3560) * update color hash/id on login * bump version * fix test * fix conflict with LoginAccount --- VERSION | 2 +- api/backend_test.go | 17 ++++- api/geth_backend.go | 103 ++++++++++++++++++++++++++--- multiaccounts/accounts/database.go | 10 +++ 4 files changed, 120 insertions(+), 12 deletions(-) diff --git a/VERSION b/VERSION index e0588cede..4e4efce63 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.154.1 +0.154.2 diff --git a/api/backend_test.go b/api/backend_test.go index 157ca76df..76e999988 100644 --- a/api/backend_test.go +++ b/api/backend_test.go @@ -676,7 +676,11 @@ func TestLoginWithKey(t *testing.T) { settings.KeyUID = keyUID settings.Address = crypto.PubkeyToAddress(walletKey.PublicKey) - require.NoError(t, b.SaveAccountAndStartNodeWithKey(main, "test-pass", settings, conf, []*accounts.Account{{Address: address, KeyUID: keyUID, Wallet: true}}, keyhex)) + chatPubKey := crypto.FromECDSAPub(&chatKey.PublicKey) + require.NoError(t, b.SaveAccountAndStartNodeWithKey(main, "test-pass", settings, conf, + []*accounts.Account{ + {Address: address, KeyUID: keyUID, Wallet: true}, + {Address: crypto.PubkeyToAddress(chatKey.PublicKey), KeyUID: keyUID, Chat: true, PublicKey: chatPubKey}}, keyhex)) require.NoError(t, b.Logout()) require.NoError(t, b.StopNode()) @@ -692,6 +696,11 @@ func TestLoginWithKey(t *testing.T) { extkey, err := b.accountManager.SelectedChatAccount() require.NoError(t, err) require.Equal(t, crypto.PubkeyToAddress(chatKey.PublicKey), extkey.Address) + + activeAccount, err := b.GetActiveAccount() + require.NoError(t, err) + require.NotNil(t, activeAccount.ColorHash) + require.NotZero(t, activeAccount.ColorID) } func TestVerifyDatabasePassword(t *testing.T) { @@ -722,7 +731,11 @@ func TestVerifyDatabasePassword(t *testing.T) { settings.KeyUID = keyUID settings.Address = crypto.PubkeyToAddress(walletKey.PublicKey) - require.NoError(t, b.SaveAccountAndStartNodeWithKey(main, "test-pass", settings, conf, []*accounts.Account{{Address: address, KeyUID: keyUID, Wallet: true}}, keyhex)) + chatPubKey := crypto.FromECDSAPub(&chatKey.PublicKey) + + require.NoError(t, b.SaveAccountAndStartNodeWithKey(main, "test-pass", settings, conf, []*accounts.Account{ + {Address: address, KeyUID: keyUID, Wallet: true}, + {Address: crypto.PubkeyToAddress(chatKey.PublicKey), KeyUID: keyUID, Chat: true, PublicKey: chatPubKey}}, keyhex)) require.NoError(t, b.Logout()) require.NoError(t, b.StopNode()) diff --git a/api/geth_backend.go b/api/geth_backend.go index 064b99507..b30301784 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -201,6 +201,24 @@ func (b *GethStatusBackend) GetAccounts() ([]multiaccounts.Account, error) { return b.multiaccountsDB.GetAccounts() } +func (b *GethStatusBackend) getAccountByKeyUID(keyUID string) (*multiaccounts.Account, error) { + b.mu.Lock() + defer b.mu.Unlock() + if b.multiaccountsDB == nil { + return nil, errors.New("accounts db wasn't initialized") + } + as, err := b.multiaccountsDB.GetAccounts() + if err != nil { + return nil, err + } + for _, acc := range as { + if acc.KeyUID == keyUID { + return &acc, nil + } + } + return nil, fmt.Errorf("account with keyUID %s not found", keyUID) +} + func (b *GethStatusBackend) SaveAccount(account multiaccounts.Account) error { b.mu.Lock() defer b.mu.Unlock() @@ -350,11 +368,21 @@ func (b *GethStatusBackend) startNodeWithKey(acc multiaccounts.Account, password return err } - b.account = &acc accountsDB, err := accounts.NewDB(b.appDB) if err != nil { return err } + + if acc.ColorHash == nil || acc.ColorID == 0 { + multiAccount, err := b.updateAccountColorHashAndColorID(acc.KeyUID, accountsDB) + if err != nil { + return err + } + acc = *multiAccount + } + + b.account = &acc + walletAddr, err := accountsDB.GetWalletAddress() if err != nil { return err @@ -416,6 +444,30 @@ func (b *GethStatusBackend) OverwriteNodeConfigValues(conf *params.NodeConfig, n return conf, nil } +func (b *GethStatusBackend) updateAccountColorHashAndColorID(keyUID string, accountsDB *accounts.Database) (*multiaccounts.Account, error) { + multiAccount, err := b.getAccountByKeyUID(keyUID) + if err != nil { + return nil, err + } + if multiAccount.ColorHash == nil || multiAccount.ColorID == 0 { + keypair, err := accountsDB.GetKeypairByKeyUID(keyUID) + if err != nil { + return nil, err + } + publicKey := keypair.GetChatPublicKey() + if publicKey == nil { + return nil, errors.New("chat public key not found") + } + if err = enrichMultiAccountByPublicKey(multiAccount, publicKey); err != nil { + return nil, err + } + if err = b.multiaccountsDB.UpdateAccount(*multiAccount); err != nil { + return nil, err + } + } + return multiAccount, nil +} + func (b *GethStatusBackend) overrideNetworks(conf *params.NodeConfig, request *requests.Login) { conf.Networks = setRPCs(defaultNetworks, &request.WalletSecretsConfig) } @@ -463,11 +515,17 @@ func (b *GethStatusBackend) loginAccount(request *requests.Login) error { return err } - b.account = &acc accountsDB, err := accounts.NewDB(b.appDB) if err != nil { return err } + + multiAccount, err := b.updateAccountColorHashAndColorID(acc.KeyUID, accountsDB) + if err != nil { + return err + } + b.account = multiAccount + chatAddr, err := accountsDB.GetChatAddress() if err != nil { return err @@ -523,11 +581,21 @@ func (b *GethStatusBackend) startNodeWithAccount(acc multiaccounts.Account, pass return err } - b.account = &acc accountsDB, err := accounts.NewDB(b.appDB) if err != nil { return err } + + if acc.ColorHash == nil || acc.ColorID == 0 { + multiAccount, err := b.updateAccountColorHashAndColorID(acc.KeyUID, accountsDB) + if err != nil { + return err + } + acc = *multiAccount + } + + b.account = &acc + chatAddr, err := accountsDB.GetChatAddress() if err != nil { return err @@ -1078,22 +1146,22 @@ func (b *GethStatusBackend) VerifyDatabasePassword(keyUID string, password strin return nil } -func enrichMultiaccountInfo(account *multiaccounts.Account, subaccs []*accounts.Account) error { +func enrichMultiAccountBySubAccounts(account *multiaccounts.Account, subaccs []*accounts.Account) error { if account.ColorHash != nil && account.ColorID != 0 { return nil } for i, acc := range subaccs { subaccs[i].KeyUID = account.KeyUID - if acc.Chat { - colorHash, err := colorhash.GenerateFor(string(acc.PublicKey.Bytes())) + pk := string(acc.PublicKey.Bytes()) + colorHash, err := colorhash.GenerateFor(pk) if err != nil { return err } account.ColorHash = colorHash - colorID, err := identityUtils.ToColorID(string(acc.PublicKey.Bytes())) + colorID, err := identityUtils.ToColorID(pk) if err != nil { return err } @@ -1106,8 +1174,25 @@ func enrichMultiaccountInfo(account *multiaccounts.Account, subaccs []*accounts. return nil } +func enrichMultiAccountByPublicKey(account *multiaccounts.Account, publicKey types.HexBytes) error { + pk := string(publicKey.Bytes()) + colorHash, err := colorhash.GenerateFor(pk) + if err != nil { + return err + } + account.ColorHash = colorHash + + colorID, err := identityUtils.ToColorID(pk) + if err != nil { + return err + } + account.ColorID = colorID + + return nil +} + func (b *GethStatusBackend) SaveAccountAndStartNodeWithKey(account multiaccounts.Account, password string, settings settings.Settings, nodecfg *params.NodeConfig, subaccs []*accounts.Account, keyHex string) error { - err := enrichMultiaccountInfo(&account, subaccs) + err := enrichMultiAccountBySubAccounts(&account, subaccs) if err != nil { return err } @@ -1138,7 +1223,7 @@ func (b *GethStatusBackend) StartNodeWithAccountAndInitialConfig( ) error { b.log.Info("node config", "config", nodecfg) - err := enrichMultiaccountInfo(&account, subaccs) + err := enrichMultiAccountBySubAccounts(&account, subaccs) if err != nil { return err } diff --git a/multiaccounts/accounts/database.go b/multiaccounts/accounts/database.go index 697d43bf3..5f7afd9f0 100644 --- a/multiaccounts/accounts/database.go +++ b/multiaccounts/accounts/database.go @@ -197,6 +197,16 @@ func (a *Keypair) CopyKeypair() *Keypair { return kp } +func (a *Keypair) GetChatPublicKey() types.HexBytes { + for _, acc := range a.Accounts { + if acc.Chat { + return acc.PublicKey + } + } + + return nil +} + // Database sql wrapper for operations with browser objects. type Database struct { *settings.Database