From 61527f8c7870331bc3c6b61f3adb1c68111e9188 Mon Sep 17 00:00:00 2001 From: Sale Djenic Date: Wed, 28 Jun 2023 21:45:36 +0200 Subject: [PATCH] chore: synchronization improvements applied to keypairs/accounts This is the first step of improvements over keypairs/keycards/accounts. - `SyncKeypairFull` protobuf removed - `SyncKeypair` protobuf is used for syncing all but the watch only accounts - `SyncAccount` is used only for syncing watch only accounts - related keycards are synced together with a keypair - on any keypair change (either it's just a keypair name or any change made over an account which belongs to that keypair) entire keypair is synced including related keycards - on any watch only account related change, that account is synced with all its details --- VERSION | 2 +- account/accounts.go | 1 + multiaccounts/accounts/database.go | 279 ++++++--- multiaccounts/accounts/database_test.go | 41 +- multiaccounts/accounts/keycard_database.go | 107 ++-- multiaccounts/accounts/testutils.go | 2 +- ...nities_messenger_token_permissions_test.go | 4 + protocol/messenger.go | 19 +- protocol/messenger_backup.go | 16 +- protocol/messenger_backup_handler.go | 23 +- protocol/messenger_backup_test.go | 5 +- protocol/messenger_config.go | 1 - protocol/messenger_handler.go | 202 ++++--- protocol/messenger_response.go | 15 +- .../messenger_sync_keycards_state_test.go | 532 +++++++++-------- protocol/messenger_sync_raw_messages.go | 13 +- protocol/messenger_sync_wallets_test.go | 40 +- protocol/messenger_wallet.go | 251 ++++++-- .../application_metadata_message.pb.go | 145 +++-- .../application_metadata_message.proto | 7 +- protocol/protobuf/pairing.pb.go | 543 +++++++++--------- protocol/protobuf/pairing.proto | 12 +- protocol/v1/status_message.go | 2 - protocol/wakusync/response.go | 3 - services/accounts/accounts.go | 55 +- services/ext/signal.go | 4 - services/web3provider/api_test.go | 2 +- signal/events_sync_from_waku.go | 7 - 28 files changed, 1279 insertions(+), 1054 deletions(-) diff --git a/VERSION b/VERSION index 94a94ed34..c959a3bc5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.161.0 +0.161.1 \ No newline at end of file diff --git a/account/accounts.go b/account/accounts.go index eda99f83e..cfb593f84 100644 --- a/account/accounts.go +++ b/account/accounts.go @@ -67,6 +67,7 @@ type Manager interface { GetVerifiedWalletAccount(db *accounts.Database, address, password string) (*SelectedExtKey, error) Sign(rpcParams SignParams, verifiedAccount *SelectedExtKey) (result types.HexBytes, err error) CanRecover(rpcParams RecoverParams, revealedAddress types.Address) (bool, error) + DeleteAccount(address types.Address) error } // DefaultManager represents default account manager implementation diff --git a/multiaccounts/accounts/database.go b/multiaccounts/accounts/database.go index 230345388..3a8f9bbfb 100644 --- a/multiaccounts/accounts/database.go +++ b/multiaccounts/accounts/database.go @@ -18,6 +18,7 @@ import ( ) const ( + statusChatPath = "m/43'/60'/1581'/0'/0" statusWalletRootPath = "m/44'/60'/0'/0/" zeroAddress = "0x0000000000000000000000000000000000000000" SyncedFromBackup = "backup" // means a account is coming from backed up data @@ -25,6 +26,7 @@ const ( ) var ( + errDbPassedParameterIsNil = errors.New("accounts: passed parameter is nil") errDbTransactionIsNil = errors.New("accounts: database transaction is nil") ErrDbKeypairNotFound = errors.New("accounts: keypair is not found") ErrDbAccountNotFound = errors.New("accounts: account is not found") @@ -40,7 +42,9 @@ type Keypair struct { LastUsedDerivationIndex uint64 `json:"last-used-derivation-index,omitempty"` SyncedFrom string `json:"synced-from,omitempty"` // keeps an info which device this keypair is added from can be one of two values defined in constants or device name (custom) Clock uint64 `json:"clock,omitempty"` - Accounts []*Account `json:"accounts"` + Accounts []*Account `json:"accounts,omitempty"` + Keycards []*Keycard `json:"keycards,omitempty"` + Removed bool `json:"removed,omitempty"` } type Account struct { @@ -156,6 +160,8 @@ func (a *Keypair) MarshalJSON() ([]byte, error) { SyncedFrom string `json:"synced-from"` Clock uint64 `json:"clock"` Accounts []*Account `json:"accounts"` + Keycards []*Keycard `json:"keycards"` + Removed bool `json:"removed"` }{ KeyUID: a.KeyUID, Name: a.Name, @@ -165,6 +171,8 @@ func (a *Keypair) MarshalJSON() ([]byte, error) { SyncedFrom: a.SyncedFrom, Clock: a.Clock, Accounts: a.Accounts, + Keycards: a.Keycards, + Removed: a.Removed, } return json.Marshal(item) @@ -180,6 +188,8 @@ func (a *Keypair) CopyKeypair() *Keypair { LastUsedDerivationIndex: a.LastUsedDerivationIndex, SyncedFrom: a.SyncedFrom, Accounts: make([]*Account, len(a.Accounts)), + Keycards: make([]*Keycard, len(a.Keycards)), + Removed: a.Removed, } for i, acc := range a.Accounts { @@ -203,6 +213,17 @@ func (a *Keypair) CopyKeypair() *Keypair { } } + for i, kc := range a.Keycards { + kp.Keycards[i] = &Keycard{ + KeycardUID: kc.KeycardUID, + KeycardName: kc.KeycardName, + KeycardLocked: kc.KeycardLocked, + AccountsAddresses: kc.AccountsAddresses, + KeyUID: kc.KeyUID, + LastUpdateClock: kc.LastUpdateClock, + } + } + return kp } @@ -248,7 +269,7 @@ func (db *Database) Close() error { return db.db.Close() } -func getAccountTypeForKeypairType(kpType KeypairType) AccountType { +func GetAccountTypeForKeypairType(kpType KeypairType) AccountType { switch kpType { case KeypairTypeProfile: return AccountTypeGenerated @@ -368,7 +389,7 @@ func (db *Database) processKeypairs(rows *sql.Rows) ([]*Keypair, error) { acc.PublicKey = make(types.HexBytes, lth) copy(acc.PublicKey, pubkey) } - acc.Type = getAccountTypeForKeypairType(kp.Type) + acc.Type = GetAccountTypeForKeypairType(kp.Type) if _, ok := keypairMap[kp.KeyUID]; !ok { keypairMap[kp.KeyUID] = kp @@ -396,6 +417,21 @@ func (db *Database) getKeypairs(tx *sql.Tx, keyUID string) ([]*Keypair, error) { err error where string ) + if tx == nil { + tx, err = db.db.Begin() + defer func() { + if err == nil { + err = tx.Commit() + return + } + _ = tx.Rollback() + }() + + if err != nil { + return nil, err + } + } + if keyUID != "" { where = "WHERE k.key_uid = ?" } @@ -427,35 +463,38 @@ func (db *Database) getKeypairs(tx *sql.Tx, keyUID string) ([]*Keypair, error) { ORDER BY ka.position`, where) - if tx == nil { - if where != "" { - rows, err = db.db.Query(query, keyUID) - } else { - rows, err = db.db.Query(query) - } - if err != nil { - return nil, err - } - } else { - stmt, err := tx.Prepare(query) - if err != nil { - return nil, err - } - defer stmt.Close() + stmt, err := tx.Prepare(query) + if err != nil { + return nil, err + } + defer stmt.Close() - if where != "" { - rows, err = stmt.Query(keyUID) - } else { - rows, err = stmt.Query() - } - if err != nil { - return nil, err - } + if where != "" { + rows, err = stmt.Query(keyUID) + } else { + rows, err = stmt.Query() + } + if err != nil { + return nil, err } defer rows.Close() - return db.processKeypairs(rows) + keypairs, err := db.processKeypairs(rows) + if err != nil { + return nil, err + } + + for _, kp := range keypairs { + keycards, err := db.getAllRows(tx, true) + if err != nil { + return nil, err + } + + kp.Keycards = keycards + } + + return keypairs, nil } func (db *Database) getKeypairByKeyUID(tx *sql.Tx, keyUID string) (*Keypair, error) { @@ -624,7 +663,7 @@ func (db *Database) GetWatchOnlyAccounts() (res []*Account, err error) { return } -func (db *Database) IsAnyAccountPartalyOrFullyOperableForKeyUID(keyUID string) (bool, error) { +func (db *Database) IsAnyAccountPartiallyOrFullyOperableForKeyUID(keyUID string) (bool, error) { kp, err := db.getKeypairByKeyUID(nil, keyUID) if err != nil { return false, err @@ -642,7 +681,7 @@ func (db *Database) DeleteKeypair(keyUID string) error { return db.deleteKeypair(nil, keyUID) } -func (db *Database) DeleteAccount(address types.Address) error { +func (db *Database) DeleteAccount(address types.Address, clock uint64) error { tx, err := db.db.Begin() defer func() { if err == nil { @@ -683,38 +722,72 @@ func (db *Database) DeleteAccount(address types.Address) error { defer delete.Close() _, err = delete.Exec(address) + if err != nil { + return err + } + + // Update keypair clock if any but the watch only account was deleted. + if kp != nil { + err = db.updateKeypairClock(tx, acc.KeyUID, clock) + return err + } + + return nil +} + +func updateKeypairLastUsedIndex(tx *sql.Tx, keyUID string, index uint64, clock uint64, updateKeypairClock bool) error { + if tx == nil { + return errDbTransactionIsNil + } + var ( + err error + setClock string + ) + if updateKeypairClock { + setClock = ", clock = ?" + } + + query := fmt.Sprintf( // nolint: gosec + ` + UPDATE + keypairs + SET + last_used_derivation_index = ? + %s + WHERE + key_uid = ?`, setClock) + + if setClock != "" { + _, err = tx.Exec(query, index, clock, keyUID) + } else { + _, err = tx.Exec(query, index, keyUID) + } return err } -func updateKeypairLastUsedIndex(tx *sql.Tx, keyUID string, index uint64, clock uint64) error { +func (db *Database) updateKeypairClock(tx *sql.Tx, keyUID string, clock uint64) error { if tx == nil { return errDbTransactionIsNil } + _, err := tx.Exec(` UPDATE keypairs SET - last_used_derivation_index = ?, clock = ? WHERE key_uid = ?`, - index, clock, keyUID) + clock, keyUID) return err } -func (db *Database) saveOrUpdateAccounts(tx *sql.Tx, accounts []*Account) (err error) { +func (db *Database) saveOrUpdateAccounts(tx *sql.Tx, accounts []*Account, updateKeypairClock bool) (err error) { if tx == nil { return errDbTransactionIsNil } - var maxPosition uint64 - err = tx.QueryRow("SELECT MAX(position) FROM keypairs_accounts").Scan(&maxPosition) - if err != nil { - maxPosition = 0 - } - for _, acc := range accounts { var relatedKeypair *Keypair // only watch only accounts have an empty `KeyUID` field @@ -736,19 +809,12 @@ func (db *Database) saveOrUpdateAccounts(tx *sql.Tx, accounts []*Account) (err e return err } - if !exists { - maxPosition++ - _, err = tx.Exec(` - INSERT OR IGNORE INTO - keypairs_accounts (address, key_uid, pubkey, path, wallet, chat, position, created_at, updated_at) - VALUES - (?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now')); - `, acc.Address, keyUID, acc.PublicKey, acc.Path, acc.Wallet, acc.Chat, maxPosition) - if err != nil { - return err - } - } _, err = tx.Exec(` + INSERT OR IGNORE INTO + keypairs_accounts (address, key_uid, pubkey, path, wallet, chat, created_at, updated_at) + VALUES + (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now')); + UPDATE keypairs_accounts SET @@ -757,15 +823,27 @@ func (db *Database) saveOrUpdateAccounts(tx *sql.Tx, accounts []*Account) (err e emoji = ?, hidden = ?, operable = ?, - clock = ? + clock = ?, + position = ?, + updated_at = datetime('now') WHERE address = ?; - `, acc.Name, acc.ColorID, acc.Emoji, acc.Hidden, acc.Operable, acc.Clock, acc.Address) + `, + acc.Address, keyUID, acc.PublicKey, acc.Path, acc.Wallet, acc.Chat, + acc.Name, acc.ColorID, acc.Emoji, acc.Hidden, acc.Operable, acc.Clock, acc.Position, acc.Address) if err != nil { return err } + // Update keypair clock if any but the watch only account has changed. + if relatedKeypair != nil && updateKeypairClock { + err = db.updateKeypairClock(tx, acc.KeyUID, acc.Clock) + if err != nil { + return err + } + } + if strings.HasPrefix(acc.Path, statusWalletRootPath) { accIndex, err := strconv.ParseUint(acc.Path[len(statusWalletRootPath):], 0, 64) if err != nil { @@ -781,16 +859,19 @@ func (db *Database) saveOrUpdateAccounts(tx *sql.Tx, accounts []*Account) (err e return false } - expectedNewKeypairIndex := relatedKeypair.LastUsedDerivationIndex - for { - expectedNewKeypairIndex++ - if !accountsContainPath(relatedKeypair.Accounts, statusWalletRootPath+strconv.FormatUint(expectedNewKeypairIndex, 10)) { - break + expectedNewKeypairIndex := uint64(0) + if relatedKeypair != nil { + expectedNewKeypairIndex = relatedKeypair.LastUsedDerivationIndex + for { + expectedNewKeypairIndex++ + if !accountsContainPath(relatedKeypair.Accounts, statusWalletRootPath+strconv.FormatUint(expectedNewKeypairIndex, 10)) { + break + } } } if accIndex == expectedNewKeypairIndex { - err = updateKeypairLastUsedIndex(tx, acc.KeyUID, accIndex, acc.Clock) + err = updateKeypairLastUsedIndex(tx, acc.KeyUID, accIndex, acc.Clock, updateKeypairClock) if err != nil { return err } @@ -801,7 +882,7 @@ func (db *Database) saveOrUpdateAccounts(tx *sql.Tx, accounts []*Account) (err e return nil } -func (db *Database) SaveOrUpdateAccounts(accounts []*Account) error { +func (db *Database) SaveOrUpdateAccounts(accounts []*Account, updateKeypairClock bool) error { if len(accounts) == 0 { return errors.New("no provided accounts to save/update") } @@ -817,11 +898,15 @@ func (db *Database) SaveOrUpdateAccounts(accounts []*Account) error { } _ = tx.Rollback() }() - err = db.saveOrUpdateAccounts(tx, accounts) + err = db.saveOrUpdateAccounts(tx, accounts, updateKeypairClock) return err } func (db *Database) SaveOrUpdateKeypair(keypair *Keypair) error { + if keypair == nil { + return errDbPassedParameterIsNil + } + tx, err := db.db.Begin() if err != nil { return err @@ -870,10 +955,10 @@ func (db *Database) SaveOrUpdateKeypair(keypair *Keypair) error { if err != nil { return err } - return db.saveOrUpdateAccounts(tx, keypair.Accounts) + return db.saveOrUpdateAccounts(tx, keypair.Accounts, false) } -func (db *Database) UpdateKeypairName(keyUID string, name string, clock uint64) error { +func (db *Database) UpdateKeypairName(keyUID string, name string, clock uint64, updateChatAccountName bool) error { tx, err := db.db.Begin() if err != nil { return err @@ -900,8 +985,26 @@ func (db *Database) UpdateKeypairName(keyUID string, name string, clock uint64) WHERE key_uid = ?; `, name, clock, keyUID) + if err != nil { + return err + } - return err + if updateChatAccountName { + _, err = tx.Exec(` + UPDATE + keypairs_accounts + SET + name = ?, + clock = ? + WHERE + key_uid = ? + AND + path = ?; + `, name, clock, keyUID, statusChatPath) + return err + } + + return nil } func (db *Database) GetWalletAddress() (rst types.Address, err error) { @@ -976,8 +1079,8 @@ func (db *Database) GetNodeConfig() (*params.NodeConfig, error) { return nodecfg.GetNodeConfigFromDB(db.db) } -// this doesn't update clock -func (db *Database) UpdateAccountToFullyOperable(keyUID string, address types.Address) (err error) { +// This function should not update the clock, cause it marks accounts locally. +func (db *Database) SetAccountOperability(address types.Address, operable AccountOperable) (err error) { tx, err := db.db.Begin() defer func() { if err == nil { @@ -996,24 +1099,30 @@ func (db *Database) UpdateAccountToFullyOperable(keyUID string, address types.Ad return err } - _, err = tx.Exec(`UPDATE keypairs_accounts SET operable = ? WHERE address = ?`, AccountFullyOperable, address) + _, err = tx.Exec(`UPDATE keypairs_accounts SET operable = ? WHERE address = ?`, operable, address) return err } +func (db *Database) GetPositionForNextNewAccount() (int64, error) { + var pos sql.NullInt64 + err := db.db.QueryRow("SELECT MAX(position) FROM keypairs_accounts").Scan(&pos) + if err != nil { + return 0, err + } + if pos.Valid { + return pos.Int64 + 1, nil + } + return 0, nil +} + // The UpdateAccountPosition function rearranges accounts based on the new position assigned to a given address. // Please note that this function does not ensure a sequential order -func (db *Database) UpdateAccountPosition(address types.Address, newPosition int64) (err error) { - var maxPosition int64 - var minPosition int64 - err = db.db.QueryRow("SELECT MAX(position), MIN(position) FROM keypairs_accounts").Scan(&maxPosition, &minPosition) - if err != nil { - return err - } - var currentPosition int64 - err = db.db.QueryRow("SELECT position FROM keypairs_accounts where address = ?", address).Scan(¤tPosition) - if err != nil { - return err - } +func (db *Database) UpdateAccountPosition(address types.Address, newPosition int64, clock uint64) (err error) { + var ( + maxPosition int64 + minPosition int64 + currentPosition int64 + ) tx, err := db.db.Begin() defer func() { if err == nil { @@ -1023,9 +1132,15 @@ func (db *Database) UpdateAccountPosition(address types.Address, newPosition int _ = tx.Rollback() }() + err = tx.QueryRow("SELECT MAX(position), MIN(position) FROM keypairs_accounts").Scan(&maxPosition, &minPosition) if err != nil { return err } + acc, err := db.getAccountByAddress(tx, address) + if err != nil { + return err + } + currentPosition = acc.Position if newPosition == maxPosition { newPosition++ @@ -1047,5 +1162,11 @@ func (db *Database) UpdateAccountPosition(address types.Address, newPosition int return err } + // Update keypair clock if any but the watch only account was deleted. + if acc.KeyUID != "" { + err = db.updateKeypairClock(tx, acc.KeyUID, clock) + return err + } + return nil } diff --git a/multiaccounts/accounts/database_test.go b/multiaccounts/accounts/database_test.go index 549e278ae..f2a80dd57 100644 --- a/multiaccounts/accounts/database_test.go +++ b/multiaccounts/accounts/database_test.go @@ -36,7 +36,7 @@ func TestGetAddresses(t *testing.T) { {Address: types.Address{0x01}, Chat: true, Wallet: true}, {Address: types.Address{0x02}}, } - require.NoError(t, db.SaveOrUpdateAccounts(accounts)) + require.NoError(t, db.SaveOrUpdateAccounts(accounts, false)) addresses, err := db.GetAddresses() require.NoError(t, err) require.Equal(t, []types.Address{{0x01}, {0x02}}, addresses) @@ -46,16 +46,16 @@ func TestUpdateAccountPosition(t *testing.T) { db, stop := setupTestDB(t) defer stop() accounts := []*Account{ - {Address: types.Address{0x01}, Chat: true, Wallet: true}, - {Address: types.Address{0x02}}, + {Address: types.Address{0x01}, Position: 1}, + {Address: types.Address{0x02}, Position: 2}, } - require.NoError(t, db.SaveOrUpdateAccounts(accounts)) + require.NoError(t, db.SaveOrUpdateAccounts(accounts, false)) accountsRes, err := db.GetAccounts() require.NoError(t, err) require.Equal(t, accountsRes[0].Position, int64(1)) require.Equal(t, accountsRes[1].Position, int64(2)) - err = db.UpdateAccountPosition(accounts[1].Address, 1) + err = db.UpdateAccountPosition(accounts[1].Address, 1, 0) require.NoError(t, err) accountsRes, err = db.GetAccounts() @@ -70,7 +70,7 @@ func TestGetWalletAddress(t *testing.T) { address := types.Address{0x01} _, err := db.GetWalletAddress() require.Equal(t, err, sql.ErrNoRows) - require.NoError(t, db.SaveOrUpdateAccounts([]*Account{{Address: address, Wallet: true}})) + require.NoError(t, db.SaveOrUpdateAccounts([]*Account{{Address: address, Wallet: true}}, false)) wallet, err := db.GetWalletAddress() require.NoError(t, err) require.Equal(t, address, wallet) @@ -82,7 +82,7 @@ func TestGetChatAddress(t *testing.T) { address := types.Address{0x01} _, err := db.GetChatAddress() require.Equal(t, err, sql.ErrNoRows) - require.NoError(t, db.SaveOrUpdateAccounts([]*Account{{Address: address, Chat: true}})) + require.NoError(t, db.SaveOrUpdateAccounts([]*Account{{Address: address, Chat: true}}, false)) chat, err := db.GetChatAddress() require.NoError(t, err) require.Equal(t, address, chat) @@ -95,7 +95,7 @@ func TestAddressExists(t *testing.T) { accounts := []*Account{ {Address: types.Address{0x01}, Chat: true, Wallet: true}, } - require.NoError(t, db.SaveOrUpdateAccounts(accounts)) + require.NoError(t, db.SaveOrUpdateAccounts(accounts, false)) exists, err := db.AddressExists(accounts[0].Address) require.NoError(t, err) @@ -133,7 +133,7 @@ func TestWatchOnlyAccounts(t *testing.T) { require.Equal(t, 0, len(dbAccounts)) // save watch only accounts - err = db.SaveOrUpdateAccounts(woAccounts) + err = db.SaveOrUpdateAccounts(woAccounts, false) require.NoError(t, err) _, err = db.GetKeypairByKeyUID(woAccounts[0].KeyUID) require.Error(t, err) @@ -144,7 +144,7 @@ func TestWatchOnlyAccounts(t *testing.T) { require.Equal(t, woAccounts[0].Address, dbAccounts[0].Address) // try to save the same watch only account again - err = db.SaveOrUpdateAccounts(woAccounts[:1]) + err = db.SaveOrUpdateAccounts(woAccounts[:1], false) require.NoError(t, err) dbAccounts, err = db.GetAccounts() require.NoError(t, err) @@ -161,7 +161,7 @@ func TestWatchOnlyAccounts(t *testing.T) { ColorID: common.CustomizationColorPrimary, Emoji: "emoji-1", } - err = db.SaveOrUpdateAccounts([]*Account{wo4}) + err = db.SaveOrUpdateAccounts([]*Account{wo4}, false) require.NoError(t, err) dbAccounts, err = db.GetAccounts() require.NoError(t, err) @@ -174,7 +174,7 @@ func TestWatchOnlyAccounts(t *testing.T) { wo4.Name = wo4.Name + "updated" wo4.ColorID = common.CustomizationColorCamel wo4.Emoji = wo4.Emoji + "updated" - err = db.SaveOrUpdateAccounts([]*Account{wo4}) + err = db.SaveOrUpdateAccounts([]*Account{wo4}, false) require.NoError(t, err) dbAccounts, err = db.GetAccounts() require.NoError(t, err) @@ -189,7 +189,7 @@ func TestWatchOnlyAccounts(t *testing.T) { require.True(t, err == ErrDbKeypairNotFound) // try to delete watch only account - err = db.DeleteAccount(wo4.Address) + err = db.DeleteAccount(wo4.Address, 0) require.NoError(t, err) dbAccounts, err = db.GetAccounts() require.NoError(t, err) @@ -220,7 +220,8 @@ func TestUpdateKeypairName(t *testing.T) { // update keypair name kp.Name = kp.Name + "updated" - err = db.UpdateKeypairName(kp.KeyUID, kp.Name, kp.Clock) + kp.Accounts[0].Name = kp.Name + err = db.UpdateKeypairName(kp.KeyUID, kp.Name, kp.Clock, true) require.NoError(t, err) // check keypair @@ -288,7 +289,7 @@ func TestKeypairs(t *testing.T) { accToUpdate := kp.Accounts[ind] // try to save the same account again - err = db.SaveOrUpdateAccounts([]*Account{accToUpdate}) + err = db.SaveOrUpdateAccounts([]*Account{accToUpdate}, false) require.NoError(t, err) dbKp, err = db.GetKeypairByKeyUID(kp.KeyUID) require.NoError(t, err) @@ -303,7 +304,7 @@ func TestKeypairs(t *testing.T) { accToUpdate.ColorID = common.CustomizationColorBrown accToUpdate.Emoji = accToUpdate.Emoji + "updated" - err = db.SaveOrUpdateAccounts([]*Account{accToUpdate}) + err = db.SaveOrUpdateAccounts([]*Account{accToUpdate}, false) require.NoError(t, err) dbKp, err = db.GetKeypairByKeyUID(kp.KeyUID) require.NoError(t, err) @@ -335,7 +336,7 @@ func TestKeypairs(t *testing.T) { accToAdd.PublicKey = types.Hex2Bytes("0x000000008") accToAdd.Name = "Generated Acc 8" - err = db.SaveOrUpdateAccounts([]*Account{accToAdd}) + err = db.SaveOrUpdateAccounts([]*Account{accToAdd}, false) require.NoError(t, err) dbKp, err = db.GetKeypairByKeyUID(kp.KeyUID) require.NoError(t, err) @@ -364,7 +365,7 @@ func TestKeypairs(t *testing.T) { expectedLastUsedDerivationIndex = 1 } - err = db.SaveOrUpdateAccounts([]*Account{accToAdd}) + err = db.SaveOrUpdateAccounts([]*Account{accToAdd}, false) require.NoError(t, err) dbKp, err = db.GetKeypairByKeyUID(kp.KeyUID) require.NoError(t, err) @@ -378,7 +379,7 @@ func TestKeypairs(t *testing.T) { require.Equal(t, accToAdd.Address, dbAcc.Address) // delete account - err = db.DeleteAccount(accToAdd.Address) + err = db.DeleteAccount(accToAdd.Address, 0) require.NoError(t, err) dbAccounts, err = db.GetAccounts() require.NoError(t, err) @@ -388,7 +389,7 @@ func TestKeypairs(t *testing.T) { require.True(t, err == ErrDbAccountNotFound) for _, acc := range dbAccounts { - err = db.DeleteAccount(acc.Address) + err = db.DeleteAccount(acc.Address, 0) require.NoError(t, err) } diff --git a/multiaccounts/accounts/keycard_database.go b/multiaccounts/accounts/keycard_database.go index 0533fabf1..fc1305ad3 100644 --- a/multiaccounts/accounts/keycard_database.go +++ b/multiaccounts/accounts/keycard_database.go @@ -120,7 +120,60 @@ func (kp *Keycards) processResult(rows *sql.Rows, groupByKeycard bool) ([]*Keyca return keycards, nil } -func (kp *Keycards) getAllRows(groupByKeycard bool) ([]*Keycard, error) { +func (kp *Keycards) getAllRows(tx *sql.Tx, groupByKeycard bool) ([]*Keycard, error) { + var ( + rows *sql.Rows + err error + ) + query := // nolint: gosec + ` + SELECT + k.keycard_uid, + k.keycard_name, + k.keycard_locked, + ka.account_address, + k.key_uid, + k.last_update_clock + FROM + keycards AS k + LEFT JOIN + keycards_accounts AS ka + ON + k.keycard_uid = ka.keycard_uid + ORDER BY + key_uid` + + if tx == nil { + rows, err = kp.db.Query(query) + if err != nil { + return nil, err + } + } else { + stmt, err := tx.Prepare(query) + if err != nil { + return nil, err + } + defer stmt.Close() + + rows, err = stmt.Query() + if err != nil { + return nil, err + } + } + + defer rows.Close() + return kp.processResult(rows, groupByKeycard) +} + +func (kp *Keycards) GetAllKnownKeycards() ([]*Keycard, error) { + return kp.getAllRows(nil, true) +} + +func (kp *Keycards) GetAllKnownKeycardsGroupedByKeyUID() ([]*Keycard, error) { + return kp.getAllRows(nil, false) +} + +func (kp *Keycards) GetKeycardByKeyUID(keyUID string) ([]*Keycard, error) { rows, err := kp.db.Query(` SELECT k.keycard_uid, @@ -130,44 +183,10 @@ func (kp *Keycards) getAllRows(groupByKeycard bool) ([]*Keycard, error) { k.key_uid, k.last_update_clock FROM - keycards AS k - LEFT JOIN - keycards_accounts AS ka - ON - k.keycard_uid = ka.keycard_uid - ORDER BY - key_uid - `) - if err != nil { - return nil, err - } - - defer rows.Close() - return kp.processResult(rows, groupByKeycard) -} - -func (kp *Keycards) GetAllKnownKeycards() ([]*Keycard, error) { - return kp.getAllRows(true) -} - -func (kp *Keycards) GetAllKnownKeycardsGroupedByKeyUID() ([]*Keycard, error) { - return kp.getAllRows(false) -} - -func (kp *Keycards) GetKeycardByKeyUID(keyUID string) ([]*Keycard, error) { - rows, err := kp.db.Query(` - SELECT - k.keycard_uid, - k.keycard_name, - k.keycard_locked, - ka.account_address, - k.key_uid, - k.last_update_clock - FROM - keycards AS k - LEFT JOIN - keycards_accounts AS ka - ON + keycards AS k + LEFT JOIN + keycards_accounts AS ka + ON k.keycard_uid = ka.keycard_uid WHERE k.key_uid = ? @@ -205,11 +224,11 @@ func (kp *Keycards) setLastUpdateClock(tx *sql.Tx, kcUID string, clock uint64) ( } _, err = tx.Exec(` - UPDATE - keycards - SET - last_update_clock = ? - WHERE + UPDATE + keycards + SET + last_update_clock = ? + WHERE keycard_uid = ?`, clock, kcUID) diff --git a/multiaccounts/accounts/testutils.go b/multiaccounts/accounts/testutils.go index ab38c1933..ca01f1f34 100644 --- a/multiaccounts/accounts/testutils.go +++ b/multiaccounts/accounts/testutils.go @@ -11,7 +11,7 @@ func MockTestAccounts(t *testing.T, db *sql.DB, accounts []*Account) { d, err := NewDB(db) require.NoError(t, err) - err = d.SaveOrUpdateAccounts(accounts) + err = d.SaveOrUpdateAccounts(accounts, false) require.NoError(t, err) res, err := d.GetAccounts() require.NoError(t, err) diff --git a/protocol/communities_messenger_token_permissions_test.go b/protocol/communities_messenger_token_permissions_test.go index d34f8cb91..8c5bc6214 100644 --- a/protocol/communities_messenger_token_permissions_test.go +++ b/protocol/communities_messenger_token_permissions_test.go @@ -55,6 +55,10 @@ func (m *AccountManagerMock) Sign(rpcParams account.SignParams, verifiedAccount return types.HexBytes{}, nil } +func (m *AccountManagerMock) DeleteAccount(address types.Address) error { + return nil +} + type TokenManagerMock struct { Balances *map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big } diff --git a/protocol/messenger.go b/protocol/messenger.go index 62179d316..4b4453334 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -2509,7 +2509,7 @@ func (m *Messenger) SyncDevices(ctx context.Context, ensName, photoPath string, if syncedFromLocalPairing { kp.SyncedFrom = accounts.SyncedFromLocalPairing } - err = m.syncKeypair(kp, true, rawMessageHandler) + err = m.syncKeypair(kp, rawMessageHandler) if err != nil { return err } @@ -4269,21 +4269,6 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte allMessagesProcessed = false continue } - case protobuf.SyncKeypairFull: - if !common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) { - logger.Warn("not coming from us, ignoring") - continue - } - - p := msg.ParsedMessage.Interface().(protobuf.SyncKeypairFull) - m.outputToCSV(msg.TransportMessage.Timestamp, msg.ID, senderID, filter.Topic, filter.ChatID, msg.Type, p) - logger.Debug("Handling SyncKeypairFull", zap.Any("message", p)) - err = m.HandleSyncKeypairFull(messageState, p) - if err != nil { - logger.Warn("failed to handle SyncKeypairFull", zap.Error(err)) - allMessagesProcessed = false - continue - } case protobuf.SyncAccount: if !common.IsPubKeyEqual(messageState.CurrentMessageState.PublicKey, &m.identity.PublicKey) { logger.Warn("not coming from us, ignoring") @@ -4293,7 +4278,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte p := msg.ParsedMessage.Interface().(protobuf.SyncAccount) m.outputToCSV(msg.TransportMessage.Timestamp, msg.ID, senderID, filter.Topic, filter.ChatID, msg.Type, p) logger.Debug("Handling SyncAccount", zap.Any("message", p)) - err = m.HandleSyncWalletAccount(messageState, p, "") + err = m.HandleSyncWatchOnlyAccount(messageState, p) if err != nil { logger.Warn("failed to handle SyncAccount", zap.Error(err)) allMessagesProcessed = false diff --git a/protocol/messenger_backup.go b/protocol/messenger_backup.go index 66c7b319f..76d7e52bb 100644 --- a/protocol/messenger_backup.go +++ b/protocol/messenger_backup.go @@ -96,7 +96,7 @@ func (m *Messenger) BackupData(ctx context.Context) (uint64, error) { return 0, errors[0] } - fullKeypairsToBackup, err := m.backupKeypairs() + keypairsToBackup, err := m.backupKeypairs() if err != nil { return 0, err } @@ -125,9 +125,9 @@ func (m *Messenger) BackupData(ctx context.Context) (uint64, error) { DataNumber: uint32(0), TotalNumber: uint32(len(settings)), }, - FullKeypairDetails: &protobuf.FetchingBackedUpDataDetails{ + KeypairDetails: &protobuf.FetchingBackedUpDataDetails{ DataNumber: uint32(0), - TotalNumber: uint32(len(fullKeypairsToBackup)), + TotalNumber: uint32(len(keypairsToBackup)), }, WatchOnlyAccountDetails: &protobuf.FetchingBackedUpDataDetails{ DataNumber: uint32(0), @@ -181,10 +181,10 @@ func (m *Messenger) BackupData(ctx context.Context) (uint64, error) { } // Update keypairs messages encode and dispatch - for i, d := range fullKeypairsToBackup { + for i, d := range keypairsToBackup { pb := backupDetailsOnly() - pb.FullKeypairDetails.DataNumber = uint32(i + 1) - pb.FullKeypair = d.FullKeypair + pb.KeypairDetails.DataNumber = uint32(i + 1) + pb.Keypair = d.Keypair err = m.encodeAndDispatchBackupMessage(ctx, pb, chat.ID) if err != nil { return 0, err @@ -430,13 +430,13 @@ func (m *Messenger) backupKeypairs() ([]*protobuf.Backup, error) { for _, kp := range keypairs { kp.SyncedFrom = accounts.SyncedFromBackup - fullKeypair, err := m.prepareSyncKeypairFullMessage(kp) + keypair, err := m.prepareSyncKeypairMessage(kp) if err != nil { return nil, err } backupMessage := &protobuf.Backup{ - FullKeypair: fullKeypair, + Keypair: keypair, } backupMessages = append(backupMessages, backupMessage) diff --git a/protocol/messenger_backup_handler.go b/protocol/messenger_backup_handler.go index 5d5a39359..9ea20100a 100644 --- a/protocol/messenger_backup_handler.go +++ b/protocol/messenger_backup_handler.go @@ -3,7 +3,6 @@ package protocol import ( "database/sql" - "github.com/status-im/status-go/multiaccounts/accounts" ensservice "github.com/status-im/status-go/services/ens" "github.com/status-im/status-go/protocol/identity" @@ -50,7 +49,7 @@ func (m *Messenger) HandleBackup(state *ReceivedMessageState, message protobuf.B errors = append(errors, err) } - err = m.handleFullKeypair(message.FullKeypair) + err = m.handleKeypair(message.Keypair) if err != nil { errors = append(errors, err) } @@ -70,7 +69,7 @@ func (m *Messenger) HandleBackup(state *ReceivedMessageState, message protobuf.B response.AddFetchingBackedUpDataDetails(SyncWakuSectionKeyContacts, message.ContactsDetails) response.AddFetchingBackedUpDataDetails(SyncWakuSectionKeyCommunities, message.CommunitiesDetails) response.AddFetchingBackedUpDataDetails(SyncWakuSectionKeySettings, message.SettingsDetails) - response.AddFetchingBackedUpDataDetails(SyncWakuSectionKeyKeypairs, message.FullKeypairDetails) + response.AddFetchingBackedUpDataDetails(SyncWakuSectionKeyKeypairs, message.KeypairDetails) response.AddFetchingBackedUpDataDetails(SyncWakuSectionKeyWatchOnlyAccounts, message.WatchOnlyAccountDetails) m.config.messengerSignalsHandler.SendWakuFetchingBackupProgress(&response) @@ -197,13 +196,16 @@ func (m *Messenger) handleBackedUpSettings(message *protobuf.SyncSetting) error return nil } -func (m *Messenger) handleFullKeypair(message *protobuf.SyncKeypairFull) error { +func (m *Messenger) handleKeypair(message *protobuf.SyncKeypair) error { if message == nil { return nil } - keypair, keycards, err := m.handleSyncKeypairFull(message) + keypair, err := m.handleSyncKeypair(message) if err != nil { + if err == ErrTryingToStoreOldKeypair { + return nil + } return err } @@ -213,12 +215,6 @@ func (m *Messenger) handleFullKeypair(message *protobuf.SyncKeypairFull) error { } m.config.messengerSignalsHandler.SendWakuBackedUpKeypair(&kpResponse) - - kcResponse := wakusync.WakuBackedUpDataResponse{ - Keycards: keycards, - } - - m.config.messengerSignalsHandler.SendWakuBackedUpKeycards(&kcResponse) } return nil @@ -229,8 +225,11 @@ func (m *Messenger) handleWatchOnlyAccount(message *protobuf.SyncAccount) error return nil } - acc, err := m.handleSyncWalletAccount(message, accounts.SyncedFromBackup) + acc, err := m.handleSyncWatchOnlyAccount(message) if err != nil { + if err == ErrTryingToStoreOldWalletAccount { + return nil + } return err } diff --git a/protocol/messenger_backup_test.go b/protocol/messenger_backup_test.go index 2b84f7a04..e282f9017 100644 --- a/protocol/messenger_backup_test.go +++ b/protocol/messenger_backup_test.go @@ -757,9 +757,6 @@ func (s *MessengerBackupSuite) TestBackupKeypairs() { s.Require().Equal(accounts.SyncedFromBackup, dbProfileKp2.SyncedFrom) for _, acc := range profileKp.Accounts { - if acc.Chat { - continue - } s.Require().True(contains(dbProfileKp2.Accounts, acc, accounts.SameAccounts)) } @@ -849,7 +846,7 @@ func (s *MessengerBackupSuite) TestBackupWatchOnlyAccounts() { bob1 := s.m woAccounts := accounts.GetWatchOnlyAccountsForTest() - err := bob1.settings.SaveOrUpdateAccounts(woAccounts) + err := bob1.settings.SaveOrUpdateAccounts(woAccounts, false) s.Require().NoError(err) dbWoAccounts1, err := bob1.settings.GetWatchOnlyAccounts() s.Require().NoError(err) diff --git a/protocol/messenger_config.go b/protocol/messenger_config.go index a60afe7e2..4246e7c77 100644 --- a/protocol/messenger_config.go +++ b/protocol/messenger_config.go @@ -58,7 +58,6 @@ type MessengerSignalsHandler interface { SendWakuBackedUpProfile(response *wakusync.WakuBackedUpDataResponse) SendWakuBackedUpSettings(response *wakusync.WakuBackedUpDataResponse) SendWakuBackedUpKeypair(response *wakusync.WakuBackedUpDataResponse) - SendWakuBackedUpKeycards(response *wakusync.WakuBackedUpDataResponse) SendWakuBackedUpWatchOnlyAccount(response *wakusync.WakuBackedUpDataResponse) } diff --git a/protocol/messenger_handler.go b/protocol/messenger_handler.go index cd088b009..44820003f 100644 --- a/protocol/messenger_handler.go +++ b/protocol/messenger_handler.go @@ -42,9 +42,10 @@ const ( var ( ErrMessageNotAllowed = errors.New("message from a non-contact") ErrMessageForWrongChatType = errors.New("message for the wrong chat type") - ErrNotWalletAccount = errors.New("an account is not a wallet account") + ErrNotWatchOnlyAccount = errors.New("an account is not a watch only account") ErrWalletAccountNotSupportedForMobileApp = errors.New("handling account is not supported for mobile app") ErrTryingToStoreOldWalletAccount = errors.New("trying to store an old wallet account") + ErrTryingToStoreOldKeypair = errors.New("trying to store an old keypair") ErrSomeFieldsMissingForWalletAccount = errors.New("some fields are missing for wallet account") ErrTryingToRemoveUnexistingWalletAccount = errors.New("trying to remove an unexisting wallet account") ErrUnknownKeypairForWalletAccount = errors.New("keypair is not known for the wallet account") @@ -2979,11 +2980,13 @@ func (m *Messenger) updateUnviewedCounts(chat *Chat, mentionedOrReplied bool) { chat.UnviewedMentionsCount++ } } -func mapSyncAccountToAccount(message *protobuf.SyncAccount, accountOperability accounts.AccountOperable) *accounts.Account { + +func mapSyncAccountToAccount(message *protobuf.SyncAccount, accountOperability accounts.AccountOperable, accType accounts.AccountType) *accounts.Account { return &accounts.Account{ Address: types.BytesToAddress(message.Address), KeyUID: message.KeyUid, PublicKey: types.HexBytes(message.PublicKey), + Type: accType, Path: message.Path, Name: message.Name, ColorID: multiaccountscommon.CustomizationColor(message.ColorId), @@ -2993,24 +2996,40 @@ func mapSyncAccountToAccount(message *protobuf.SyncAccount, accountOperability a Hidden: message.Hidden, Clock: message.Clock, Operable: accountOperability, + Removed: message.Removed, + Position: message.Position, } } -func (m *Messenger) resolveAccountOperability(keyUID string, defaultWalletAccount bool, accountReceivedFromRecovering bool) (accounts.AccountOperable, error) { - knownKeycardsForKeyUID, err := m.settings.GetKeycardByKeyUID(keyUID) - if err != nil { - if err == accounts.ErrDbKeypairNotFound { - return accounts.AccountNonOperable, nil - } - return accounts.AccountNonOperable, err +func (m *Messenger) resolveAccountOperability(syncAcc *protobuf.SyncAccount, syncKpMigratedToKeycard bool, accountReceivedFromLocalPairing bool) (accounts.AccountOperable, error) { + accountsOperability := accounts.AccountNonOperable + dbAccount, err := m.settings.GetAccountByAddress(types.BytesToAddress(syncAcc.Address)) + if err != nil && err != accounts.ErrDbAccountNotFound { + return accountsOperability, err + } + if dbAccount != nil { + return dbAccount.Operable, nil } - keypairMigratedToKeycard := len(knownKeycardsForKeyUID) > 0 - accountsOperability := accounts.AccountNonOperable - if keypairMigratedToKeycard || accountReceivedFromRecovering || defaultWalletAccount { + if !syncKpMigratedToKeycard { + // We're here when we receive a keypair from the paired device which is either: + // 1. regular keypair or + // 2. was just converted from keycard to a regular keypair. + dbKeycardsForKeyUID, err := m.settings.GetKeycardByKeyUID(syncAcc.KeyUid) + if err != nil && err != accounts.ErrDbKeypairNotFound { + return accounts.AccountNonOperable, err + } + + if len(dbKeycardsForKeyUID) > 0 { + // We're here in 2. case from above and in this case we need to mark all accounts for this keypair non operable + return accounts.AccountNonOperable, nil + } + } + + if syncKpMigratedToKeycard || accountReceivedFromLocalPairing || syncAcc.Chat || syncAcc.Wallet { accountsOperability = accounts.AccountFullyOperable } else { - partiallyOrFullyOperable, err := m.settings.IsAnyAccountPartalyOrFullyOperableForKeyUID(keyUID) + partiallyOrFullyOperable, err := m.settings.IsAnyAccountPartiallyOrFullyOperableForKeyUID(syncAcc.KeyUid) if err != nil { if err == accounts.ErrDbKeypairNotFound { return accounts.AccountNonOperable, nil @@ -3025,30 +3044,13 @@ func (m *Messenger) resolveAccountOperability(keyUID string, defaultWalletAccoun return accountsOperability, nil } -func (m *Messenger) handleSyncWalletAccount(message *protobuf.SyncAccount, syncedFrom string) (*accounts.Account, error) { - if message.Chat { - return nil, ErrNotWalletAccount +func (m *Messenger) handleSyncWatchOnlyAccount(message *protobuf.SyncAccount) (*accounts.Account, error) { + if message.KeyUid != "" { + return nil, ErrNotWatchOnlyAccount } accountOperability := accounts.AccountFullyOperable - // The only account without `KeyUid` is watch only account and it doesn't belong to any keypair. - if message.KeyUid != "" { - _, err := m.settings.GetKeypairByKeyUID(message.KeyUid) - if err != nil { - if err == accounts.ErrDbKeypairNotFound { - return nil, ErrUnknownKeypairForWalletAccount - } - return nil, err - } - - accountReceivedFromRecovering := syncedFrom == accounts.SyncedFromLocalPairing - accountOperability, err = m.resolveAccountOperability(message.KeyUid, message.Wallet, accountReceivedFromRecovering) - if err != nil { - return nil, err - } - } - accAddress := types.BytesToAddress(message.Address) dbAccount, err := m.settings.GetAccountByAddress(accAddress) if err != nil && err != accounts.ErrDbAccountNotFound { @@ -3061,7 +3063,7 @@ func (m *Messenger) handleSyncWalletAccount(message *protobuf.SyncAccount, synce } if message.Removed { - err = m.settings.DeleteAccount(accAddress) + err = m.settings.DeleteAccount(accAddress, message.Clock) dbAccount.Removed = true return dbAccount, err } @@ -3071,9 +3073,9 @@ func (m *Messenger) handleSyncWalletAccount(message *protobuf.SyncAccount, synce } } - acc := mapSyncAccountToAccount(message, accountOperability) + acc := mapSyncAccountToAccount(message, accountOperability, accounts.AccountTypeWatch) - err = m.settings.SaveOrUpdateAccounts([]*accounts.Account{acc}) + err = m.settings.SaveOrUpdateAccounts([]*accounts.Account{acc}, false) if err != nil { return nil, err } @@ -3098,95 +3100,98 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts. LastUsedDerivationIndex: message.LastUsedDerivationIndex, SyncedFrom: message.SyncedFrom, Clock: message.Clock, + Removed: message.Removed, } - saveOrUpdate := dbKeypair == nil + accountReceivedFromLocalPairing := message.SyncedFrom == accounts.SyncedFromLocalPairing if dbKeypair != nil { - saveOrUpdate = dbKeypair.Clock < kp.Clock + if dbKeypair.Clock >= kp.Clock { + return nil, ErrTryingToStoreOldKeypair + } // in case of keypair update, we need to keep `synced_from` field as it was when keypair was introduced to this device for the first time kp.SyncedFrom = dbKeypair.SyncedFrom - } - - if saveOrUpdate { - accountReceivedFromRecovering := message.SyncedFrom == accounts.SyncedFromLocalPairing - if dbKeypair != nil && message.SyncedFrom == accounts.SyncedFromBackup { - // in case of recovering from backed up messages we need to delete messages which are already in db (eg. stored py previously received backed up message) - for _, dbAcc := range dbKeypair.Accounts { - found := false - for _, sAcc := range message.Accounts { - sAccAddress := types.BytesToAddress(sAcc.Address) - if dbAcc.Address == sAccAddress { - found = true - break - } - } - if found { - err = m.settings.DeleteAccount(dbAcc.Address) - if err != nil { - return nil, err - } - } - } - } - - for _, sAcc := range message.Accounts { - accountOperability, err := m.resolveAccountOperability(sAcc.KeyUid, sAcc.Wallet, accountReceivedFromRecovering) - if err != nil { - return nil, err - } - acc := mapSyncAccountToAccount(sAcc, accountOperability) - kp.Accounts = append(kp.Accounts, acc) - } - err = m.settings.SaveOrUpdateKeypair(kp) - if err != nil { - return nil, err + } else { + if kp.Removed { + return nil, nil } } for _, sAcc := range message.Accounts { - acc, err := m.handleSyncWalletAccount(sAcc, message.SyncedFrom) + syncKpMigratedToKeycard := len(message.Keycards) > 0 + accountOperability, err := m.resolveAccountOperability(sAcc, syncKpMigratedToKeycard, accountReceivedFromLocalPairing) if err != nil { - if err == ErrNotWalletAccount || - err == ErrTryingToStoreOldWalletAccount || - err == ErrTryingToRemoveUnexistingWalletAccount { - continue - } return nil, err } + acc := mapSyncAccountToAccount(sAcc, accountOperability, accounts.GetAccountTypeForKeypairType(kp.Type)) kp.Accounts = append(kp.Accounts, acc) } - return kp, nil -} + if kp.Removed { + // delete all keystore files + for _, dbAcc := range dbKeypair.Accounts { + err = m.deleteKeystoreFileForAddress(dbAcc.Address) + if err != nil { + return nil, err + } + } + } else if !accountReceivedFromLocalPairing && dbKeypair != nil { + for _, dbAcc := range dbKeypair.Accounts { + found := false + for _, acc := range kp.Accounts { + if dbAcc.Address == acc.Address { + found = true + break + } + } + if !found { + err = m.deleteKeystoreFileForAddress(dbAcc.Address) + if err != nil { + return nil, err + } + } + } + } -func (m *Messenger) handleSyncKeypairFull(message *protobuf.SyncKeypairFull) (kp *accounts.Keypair, keycards []*accounts.Keycard, err error) { - kp, err = m.handleSyncKeypair(message.Keypair) + err = m.settings.DeleteKeypair(message.KeyUid) + if err != nil && err != accounts.ErrDbKeypairNotFound { + return nil, err + } + + // if entire keypair was removed, there is no point to continue + if kp.Removed { + return kp, nil + } + + err = m.settings.SaveOrUpdateKeypair(kp) if err != nil { - return nil, nil, err + return nil, err } for _, sKc := range message.Keycards { kc := accounts.Keycard{} kc.FromSyncKeycard(sKc) - keycards = append(keycards, &kc) + kp.Keycards = append(kp.Keycards, &kc) } - err = m.settings.ApplyKeycardsForKeypairWithKeyUID(kp.KeyUID, keycards) + err = m.settings.ApplyKeycardsForKeypairWithKeyUID(kp.KeyUID, kp.Keycards) if err != nil { - return kp, keycards, err + return nil, err } - return + return kp, nil } -func (m *Messenger) HandleSyncWalletAccount(state *ReceivedMessageState, message protobuf.SyncAccount, syncedFrom string) error { - acc, err := m.handleSyncWalletAccount(&message, syncedFrom) +func (m *Messenger) HandleSyncWatchOnlyAccount(state *ReceivedMessageState, message protobuf.SyncAccount) error { + acc, err := m.handleSyncWatchOnlyAccount(&message) if err != nil { + if err == ErrTryingToStoreOldWalletAccount { + return nil + } return err } - state.Response.Accounts = append(state.Response.Accounts, acc) + state.Response.WatchOnlyAccounts = append(state.Response.WatchOnlyAccounts, acc) return nil } @@ -3194,6 +3199,9 @@ func (m *Messenger) HandleSyncWalletAccount(state *ReceivedMessageState, message func (m *Messenger) HandleSyncKeypair(state *ReceivedMessageState, message protobuf.SyncKeypair) error { kp, err := m.handleSyncKeypair(&message) if err != nil { + if err == ErrTryingToStoreOldKeypair { + return nil + } return err } @@ -3202,18 +3210,6 @@ func (m *Messenger) HandleSyncKeypair(state *ReceivedMessageState, message proto return nil } -func (m *Messenger) HandleSyncKeypairFull(state *ReceivedMessageState, message protobuf.SyncKeypairFull) error { - keypair, keycards, err := m.handleSyncKeypairFull(&message) - if err != nil { - return err - } - - state.Response.Keypairs = append(state.Response.Keypairs, keypair) - state.Response.Keycards = append(state.Response.Keycards, keycards...) - - return nil -} - func (m *Messenger) HandleSyncContactRequestDecision(state *ReceivedMessageState, message protobuf.SyncContactRequestDecision) error { var err error var response *MessengerResponse diff --git a/protocol/messenger_response.go b/protocol/messenger_response.go index 9d3814a38..da8699b11 100644 --- a/protocol/messenger_response.go +++ b/protocol/messenger_response.go @@ -45,7 +45,7 @@ type MessengerResponse struct { Bookmarks []*browsers.Bookmark Settings []*settings.SyncSettingField IdentityImages []images.IdentityImage - Accounts []*accounts.Account + WatchOnlyAccounts []*accounts.Account Keypairs []*accounts.Keypair DiscordCategories []*discord.Category DiscordChannels []*discord.Channel @@ -74,7 +74,6 @@ type MessengerResponse struct { trustStatus map[string]verification.TrustStatus emojiReactions map[string]*EmojiReaction savedAddresses map[string]*wallet.SavedAddress - Keycards []*accounts.Keycard keycardActions []*accounts.KeycardAction SocialLinksInfo *identity.SocialLinksInfo ensUsernameDetails []*ensservice.UsernameDetail @@ -109,7 +108,7 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { StatusUpdates []UserStatus `json:"statusUpdates,omitempty"` Settings []*settings.SyncSettingField `json:"settings,omitempty"` IdentityImages []images.IdentityImage `json:"identityImages,omitempty"` - Accounts []*accounts.Account `json:"accounts,omitempty"` + WatchOnlyAccounts []*accounts.Account `json:"watchOnlyAccounts,omitempty"` Keypairs []*accounts.Keypair `json:"keypairs,omitempty"` DiscordCategories []*discord.Category `json:"discordCategories,omitempty"` DiscordChannels []*discord.Channel `json:"discordChannels,omitempty"` @@ -117,7 +116,6 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { DiscordMessages []*protobuf.DiscordMessage `json:"discordMessages,omitempty"` DiscordMessageAttachments []*protobuf.DiscordMessageAttachment `json:"discordMessageAtachments,omitempty"` SavedAddresses []*wallet.SavedAddress `json:"savedAddresses,omitempty"` - Keycards []*accounts.Keycard `json:"keycards,omitempty"` KeycardActions []*accounts.KeycardAction `json:"keycardActions,omitempty"` SocialLinksInfo *identity.SocialLinksInfo `json:"socialLinksInfo,omitempty"` EnsUsernameDetails []*ensservice.UsernameDetail `json:"ensUsernameDetails,omitempty"` @@ -132,7 +130,7 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { CurrentStatus: r.currentStatus, Settings: r.Settings, IdentityImages: r.IdentityImages, - Accounts: r.Accounts, + WatchOnlyAccounts: r.WatchOnlyAccounts, Keypairs: r.Keypairs, Messages: r.Messages(), @@ -153,7 +151,6 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { DiscordCategories: r.DiscordCategories, DiscordChannels: r.DiscordChannels, DiscordOldestMessageTimestamp: r.DiscordOldestMessageTimestamp, - Keycards: r.Keycards, KeycardActions: r.KeycardActions(), SocialLinksInfo: r.SocialLinksInfo, EnsUsernameDetails: r.EnsUsernameDetails(), @@ -273,7 +270,7 @@ func (r *MessengerResponse) IsEmpty() bool { len(r.removedMessages)+ len(r.Mailservers)+ len(r.IdentityImages)+ - len(r.Accounts)+ + len(r.WatchOnlyAccounts)+ len(r.Keypairs)+ len(r.notifications)+ len(r.statusUpdates)+ @@ -282,7 +279,6 @@ func (r *MessengerResponse) IsEmpty() bool { len(r.verificationRequests)+ len(r.RequestsToJoinCommunity)+ len(r.savedAddresses)+ - len(r.Keycards)+ len(r.keycardActions) == 0 && len(r.ensUsernameDetails) == 0 && r.currentStatus == nil && @@ -322,9 +318,8 @@ func (r *MessengerResponse) Merge(response *MessengerResponse) error { r.AddBookmarks(response.GetBookmarks()) r.CommunityChanges = append(r.CommunityChanges, response.CommunityChanges...) r.BackupHandled = response.BackupHandled - r.Accounts = append(r.Accounts, response.Accounts...) + r.WatchOnlyAccounts = append(r.WatchOnlyAccounts, response.WatchOnlyAccounts...) r.Keypairs = append(r.Keypairs, response.Keypairs...) - r.Keycards = append(r.Keycards, response.Keycards...) r.SocialLinksInfo = response.SocialLinksInfo return nil diff --git a/protocol/messenger_sync_keycards_state_test.go b/protocol/messenger_sync_keycards_state_test.go index 7f1637a9f..ac01b20d6 100644 --- a/protocol/messenger_sync_keycards_state_test.go +++ b/protocol/messenger_sync_keycards_state_test.go @@ -116,296 +116,338 @@ func (s *MessengerSyncKeycardsStateSuite) newMessenger(shh types.Waku) *Messenge return messenger } -func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasNoKeycards() { - senderDb := s.main.settings - dbOnReceiver := s.other.settings +// TODO: commented tests below will be handled in the seocnd step of planned improvements - keycard1 := accounts.GetProfileKeycardForTest() +// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasNoKeycards() { +// senderDb := s.main.settings +// dbOnReceiver := s.other.settings - keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// keycard1 := accounts.GetProfileKeycardForTest() - keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest() - keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C" - keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy" - keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1 +// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() - keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest() +// keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C" +// keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy" +// keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1 - // Add keycards on sender - addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest() - // Trigger's a sync between devices - err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) - s.Require().NoError(err) +// // Add keycards on sender +// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - // Wait for the response - _, err = WaitOnMessengerResponse( - s.other, - func(r *MessengerResponse) bool { - return len(r.Keypairs) == 3 && len(r.Keycards) == 4 - }, - "expected to receive keycards", - ) - s.Require().NoError(err) +// // Trigger's a sync between devices +// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) +// s.Require().NoError(err) - syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() - s.Require().NoError(err) - s.Require().Equal(4, len(syncedKeycards)) - s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards)) - s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) - s.Require().True(contains(syncedKeycards, keycard2Copy, accounts.SameKeycards)) - s.Require().True(contains(syncedKeycards, keycard3, accounts.SameKeycards)) -} +// // Wait for the response +// _, err = WaitOnMessengerResponse( +// s.other, +// func(r *MessengerResponse) bool { +// success := len(r.Keypairs) == 3 +// for _, kp := range r.Keypairs { +// if kp.KeyUID == keycard1.KeyUID { +// success = success && len(kp.Keycards) == 1 +// } else if kp.KeyUID == keycard2.KeyUID { +// success = success && len(kp.Keycards) == 2 +// } else if kp.KeyUID == keycard3.KeyUID { +// success = success && len(kp.Keycards) == 1 +// } +// } +// return success +// }, +// "expected to receive keycards", +// ) +// s.Require().NoError(err) -func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasKeycardsOlderThanSender() { - senderDb := s.main.settings - dbOnReceiver := s.other.settings +// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() +// s.Require().NoError(err) +// s.Require().Equal(4, len(syncedKeycards)) +// s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards)) +// s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) +// s.Require().True(contains(syncedKeycards, keycard2Copy, accounts.SameKeycards)) +// s.Require().True(contains(syncedKeycards, keycard3, accounts.SameKeycards)) +// } - keycard1 := accounts.GetProfileKeycardForTest() +// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasKeycardsOlderThanSender() { +// senderDb := s.main.settings +// dbOnReceiver := s.other.settings - keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// keycard1 := accounts.GetProfileKeycardForTest() - // Add keycards on sender - addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() - // Add keycards on receiver - partially - keycardR1 := accounts.GetProfileKeycardForTest() - keycardR1.KeycardName = "CardNameToBeChanged-0" - keycardR1.AccountsAddresses = keycardR1.AccountsAddresses[2:3] - keycardR1.LastUpdateClock = keycardR1.LastUpdateClock - 1 +// // Add keycards on sender +// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - keycardR2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() - keycardR2.KeycardName = "CardNameToBeChanged-1" - keycardR2.LastUpdateClock = keycardR2.LastUpdateClock - 1 +// // Add keycards on receiver - partially +// keycardR1 := accounts.GetProfileKeycardForTest() +// keycardR1.KeycardName = "CardNameToBeChanged-0" +// keycardR1.AccountsAddresses = keycardR1.AccountsAddresses[2:3] +// keycardR1.LastUpdateClock = keycardR1.LastUpdateClock - 1 - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR1) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR2) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// keycardR2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// keycardR2.KeycardName = "CardNameToBeChanged-1" +// keycardR2.LastUpdateClock = keycardR2.LastUpdateClock - 1 - // Trigger's a sync between devices - err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) - s.Require().NoError(err) +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR1) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR2) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - // Wait for the response - _, err = WaitOnMessengerResponse( - s.other, - func(r *MessengerResponse) bool { - return len(r.Keypairs) == 3 && len(r.Keycards) == 2 - }, - "expected to receive keycards", - ) - s.Require().NoError(err) +// // Trigger's a sync between devices +// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) +// s.Require().NoError(err) - syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() - s.Require().NoError(err) - s.Require().Equal(2, len(syncedKeycards)) - s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards)) - s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) -} +// // Wait for the response +// _, err = WaitOnMessengerResponse( +// s.other, +// func(r *MessengerResponse) bool { +// success := len(r.Keypairs) == 3 +// for _, kp := range r.Keypairs { +// if kp.KeyUID == keycardR1.KeyUID { +// success = success && len(kp.Keycards) == 1 +// } else if kp.KeyUID == keycardR2.KeyUID { +// success = success && len(kp.Keycards) == 1 +// } +// } +// return success +// }, +// "expected to receive keycards", +// ) +// s.Require().NoError(err) -func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasKeycardsNewerThanSender() { - senderDb := s.main.settings - dbOnReceiver := s.other.settings +// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() +// s.Require().NoError(err) +// s.Require().Equal(2, len(syncedKeycards)) +// s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards)) +// s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) +// } - keycard1 := accounts.GetProfileKeycardForTest() +// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasKeycardsNewerThanSender() { +// senderDb := s.main.settings +// dbOnReceiver := s.other.settings - keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// keycard1 := accounts.GetProfileKeycardForTest() - // Add keycards on sender - addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() - // Add keycards on receiver - partially - keycardR1 := accounts.GetProfileKeycardForTest() - keycardR1.KeycardName = "CardNameToBeChanged-0" - keycardR1.AccountsAddresses = keycardR1.AccountsAddresses[2:3] - keycardR1.LastUpdateClock = keycardR1.LastUpdateClock + 1 +// // Add keycards on sender +// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - keycardR2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() - keycardR2.KeycardName = "CardNameToBeChanged-1" - keycardR2.LastUpdateClock = keycardR2.LastUpdateClock + 1 +// // Add keycards on receiver - partially +// keycardR1 := accounts.GetProfileKeycardForTest() +// keycardR1.KeycardName = "CardNameToBeChanged-0" +// keycardR1.AccountsAddresses = keycardR1.AccountsAddresses[2:3] +// keycardR1.LastUpdateClock = keycardR1.LastUpdateClock + 1 - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR1) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR2) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// keycardR2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// keycardR2.KeycardName = "CardNameToBeChanged-1" +// keycardR2.LastUpdateClock = keycardR2.LastUpdateClock + 1 - // Trigger's a sync between devices - err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) - s.Require().NoError(err) +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR1) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycardR2) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - // Wait for the response - _, err = WaitOnMessengerResponse( - s.other, - func(r *MessengerResponse) bool { - return len(r.Keypairs) == 3 && len(r.Keycards) == 2 - }, - "expected to receive keycards", - ) - s.Require().NoError(err) +// // Trigger's a sync between devices +// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) +// s.Require().NoError(err) - syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() - s.Require().NoError(err) - s.Require().Equal(2, len(syncedKeycards)) - s.Require().True(contains(syncedKeycards, keycardR1, accounts.SameKeycards)) - s.Require().True(contains(syncedKeycards, keycardR2, accounts.SameKeycards)) -} +// // Wait for the response +// _, err = WaitOnMessengerResponse( +// s.other, +// func(r *MessengerResponse) bool { +// success := len(r.Keypairs) == 3 +// for _, kp := range r.Keypairs { +// if kp.KeyUID == keycardR1.KeyUID { +// success = success && len(kp.Keycards) == 1 +// } else if kp.KeyUID == keycardR2.KeyUID { +// success = success && len(kp.Keycards) == 1 +// } +// } +// return success +// }, +// "expected to receive keycards", +// ) +// s.Require().NoError(err) -func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfKeycardsWereDeletedOnSenderSide() { - senderDb := s.main.settings - dbOnReceiver := s.other.settings +// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() +// s.Require().NoError(err) +// s.Require().Equal(2, len(syncedKeycards)) +// s.Require().True(contains(syncedKeycards, keycardR1, accounts.SameKeycards)) +// s.Require().True(contains(syncedKeycards, keycardR2, accounts.SameKeycards)) +// } - // Add keycards on sender - keycard1 := accounts.GetProfileKeycardForTest() +// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfKeycardsWereDeletedOnSenderSide() { +// senderDb := s.main.settings +// dbOnReceiver := s.other.settings - keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// // Add keycards on sender +// keycard1 := accounts.GetProfileKeycardForTest() - keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest() - keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C" - keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy" - keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1 +// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() - keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest() +// keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C" +// keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy" +// keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1 - // Add keycards on sender - addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest() - // Add keycards on receiver - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// // Add keycards on sender +// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - // Trigger's a sync between devices - err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) - s.Require().NoError(err) +// // Add keycards on receiver +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - // Wait for the response - _, err = WaitOnMessengerResponse( - s.other, - func(r *MessengerResponse) bool { - return len(r.Keypairs) == 3 && len(r.Keycards) == 2 - }, - "expected to receive keycards", - ) - s.Require().NoError(err) +// // Trigger's a sync between devices +// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) +// s.Require().NoError(err) - syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() - s.Require().NoError(err) - s.Require().Equal(2, len(syncedKeycards)) - s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards)) - s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) -} +// // Wait for the response +// _, err = WaitOnMessengerResponse( +// s.other, +// func(r *MessengerResponse) bool { +// success := len(r.Keypairs) == 3 +// for _, kp := range r.Keypairs { +// if kp.KeyUID == keycard1.KeyUID { +// success = success && len(kp.Keycards) == 1 +// } else if kp.KeyUID == keycard2.KeyUID { +// success = success && len(kp.Keycards) == 1 +// } +// } +// return success +// }, +// "expected to receive keycards", +// ) +// s.Require().NoError(err) -func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverAndSenderHasNoKeycardsInCommon() { - senderDb := s.main.settings - dbOnReceiver := s.other.settings +// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() +// s.Require().NoError(err) +// s.Require().Equal(2, len(syncedKeycards)) +// s.Require().True(contains(syncedKeycards, keycard1, accounts.SameKeycards)) +// s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) +// } - // Add keycards on sender - keycard1 := accounts.GetProfileKeycardForTest() +// func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverAndSenderHasNoKeycardsInCommon() { +// senderDb := s.main.settings +// dbOnReceiver := s.other.settings - keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// // Add keycards on sender +// keycard1 := accounts.GetProfileKeycardForTest() - keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest() - keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C" - keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy" - keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1 +// keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest() - keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest() +// keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest() +// keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C" +// keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy" +// keycard2Copy.LastUpdateClock = keycard2Copy.LastUpdateClock + 1 - // Add keycards on sender - addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest() - // Add keycards on receiver - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) - addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3) - s.Require().NoError(err) - s.Require().Equal(true, addedKc) - s.Require().Equal(false, addedAccs) +// // Add keycards on sender +// addedKc, addedAccs, err := senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = senderDb.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard2Copy) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - // Trigger's a sync between devices - err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) - s.Require().NoError(err) +// // Add keycards on receiver +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard1) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) +// addedKc, addedAccs, err = dbOnReceiver.AddKeycardOrAddAccountsIfKeycardIsAdded(*keycard3) +// s.Require().NoError(err) +// s.Require().Equal(true, addedKc) +// s.Require().Equal(false, addedAccs) - // Wait for the response - _, err = WaitOnMessengerResponse( - s.other, - func(r *MessengerResponse) bool { - return len(r.Keypairs) == 3 && len(r.Keycards) == 2 - }, - "expected to receive keycards", - ) - s.Require().NoError(err) +// // Trigger's a sync between devices +// err = s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil) +// s.Require().NoError(err) - syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() - s.Require().NoError(err) - s.Require().Equal(2, len(syncedKeycards)) - s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) - s.Require().True(contains(syncedKeycards, keycard2Copy, accounts.SameKeycards)) -} +// // Wait for the response +// _, err = WaitOnMessengerResponse( +// s.other, +// func(r *MessengerResponse) bool { +// success := len(r.Keypairs) == 3 +// for _, kp := range r.Keypairs { +// if kp.KeyUID == keycard2.KeyUID { +// success = success && len(kp.Keycards) == 2 +// } +// } +// return success +// }, +// "expected to receive keycards", +// ) +// s.Require().NoError(err) + +// syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() +// s.Require().NoError(err) +// s.Require().Equal(2, len(syncedKeycards)) +// s.Require().True(contains(syncedKeycards, keycard2, accounts.SameKeycards)) +// s.Require().True(contains(syncedKeycards, keycard2Copy, accounts.SameKeycards)) +// } diff --git a/protocol/messenger_sync_raw_messages.go b/protocol/messenger_sync_raw_messages.go index a8112cf1e..4685454d8 100644 --- a/protocol/messenger_sync_raw_messages.go +++ b/protocol/messenger_sync_raw_messages.go @@ -7,7 +7,6 @@ import ( "github.com/golang/protobuf/proto" "go.uber.org/zap" - "github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/encryption/multidevice" "github.com/status-im/status-go/protocol/protobuf" @@ -199,20 +198,20 @@ func (m *Messenger) HandleSyncRawMessages(rawMessages []*protobuf.RawMessage) er if err != nil { return err } - err = m.HandleSyncWalletAccount(state, message, accounts.SyncedFromLocalPairing) + err = m.HandleSyncWatchOnlyAccount(state, message) if err != nil { - m.logger.Error("failed to HandleSyncWalletAccount when HandleSyncRawMessages", zap.Error(err)) + m.logger.Error("failed to HandleSyncWatchOnlyAccount when HandleSyncRawMessages", zap.Error(err)) continue } - case protobuf.ApplicationMetadataMessage_SYNC_FULL_KEYPAIR: - var message protobuf.SyncKeypairFull + case protobuf.ApplicationMetadataMessage_SYNC_KEYPAIR: + var message protobuf.SyncKeypair err := proto.Unmarshal(rawMessage.GetPayload(), &message) if err != nil { return err } - err = m.HandleSyncKeypairFull(state, message) + err = m.HandleSyncKeypair(state, message) if err != nil { - m.logger.Error("failed to HandleSyncKeypairFull when HandleSyncRawMessages", zap.Error(err)) + m.logger.Error("failed to HandleSyncKeypair when HandleSyncRawMessages", zap.Error(err)) continue } case protobuf.ApplicationMetadataMessage_SYNC_SAVED_ADDRESS: diff --git a/protocol/messenger_sync_wallets_test.go b/protocol/messenger_sync_wallets_test.go index 0642a09e7..4772c8251 100644 --- a/protocol/messenger_sync_wallets_test.go +++ b/protocol/messenger_sync_wallets_test.go @@ -109,6 +109,11 @@ func (s *MessengerSyncWalletSuite) TestProfileKeypairNameChange() { func (s *MessengerSyncWalletSuite) TestSyncWallets() { profileKp := accounts.GetProfileKeypairForTest(true, true, true) + // set clocks for accounts + profileKp.Clock = uint64(len(profileKp.Accounts) - 1) + for i, acc := range profileKp.Accounts { + acc.Clock = uint64(i) + } // Create a main account on alice err := s.m.settings.SaveOrUpdateKeypair(profileKp) @@ -183,7 +188,7 @@ func (s *MessengerSyncWalletSuite) TestSyncWallets() { // Store watch only accounts on alice's device woAccounts := accounts.GetWatchOnlyAccountsForTest() - err = s.m.settings.SaveOrUpdateAccounts(woAccounts) + err = s.m.settings.SaveOrUpdateAccounts(woAccounts, false) s.Require().NoError(err) dbWoAccounts1, err := s.m.settings.GetWatchOnlyAccounts() s.Require().NoError(err) @@ -205,16 +210,37 @@ func (s *MessengerSyncWalletSuite) TestSyncWallets() { } if len(response.Keypairs) != 3 || // 3 keypairs (profile, seed, priv key) - len(response.Accounts) != len(woAccounts) { + len(response.WatchOnlyAccounts) != len(woAccounts) { return errors.New("no sync wallet account received") } return nil }) s.Require().NoError(err) - dbProfileKp2, err = s.m.settings.GetKeypairByKeyUID(profileKp.KeyUID) + dbProfileKp2, err = alicesOtherDevice.settings.GetKeypairByKeyUID(profileKp.KeyUID) s.Require().NoError(err) - s.Require().True(accounts.SameKeypairsWithDifferentSyncedFrom(profileKp, dbProfileKp2, true, "", accounts.AccountFullyOperable)) + s.Require().True(profileKp.KeyUID == dbProfileKp2.KeyUID && + profileKp.Name == dbProfileKp2.Name && + profileKp.Type == dbProfileKp2.Type && + profileKp.DerivedFrom == dbProfileKp2.DerivedFrom && + profileKp.LastUsedDerivationIndex == dbProfileKp2.LastUsedDerivationIndex && + profileKp.Clock == dbProfileKp2.Clock && + len(profileKp.Accounts) == len(dbProfileKp2.Accounts)) + // chat and default wallet account should be fully operable, other accounts partially operable + for i := range profileKp.Accounts { + match := false + expectedOperableValue := accounts.AccountPartiallyOperable + if profileKp.Accounts[i].Chat || profileKp.Accounts[i].Wallet { + expectedOperableValue = accounts.AccountFullyOperable + } + for j := range dbProfileKp2.Accounts { + if accounts.SameAccountsWithDifferentOperable(profileKp.Accounts[i], dbProfileKp2.Accounts[j], expectedOperableValue) { + match = true + break + } + } + s.Require().True(match) + } dbSeedPhraseKp2, err := alicesOtherDevice.settings.GetKeypairByKeyUID(seedPhraseKp.KeyUID) s.Require().NoError(err) @@ -252,7 +278,7 @@ func (s *MessengerSyncWalletSuite) TestSyncWallets() { } if len(response.Keypairs) != 1 { - return errors.New("no sync wallet account received") + return errors.New("no sync keypairs received") } return nil }) @@ -280,8 +306,8 @@ func (s *MessengerSyncWalletSuite) TestSyncWallets() { return err } - if len(response.Accounts) != len(accountsToUpdate) { - return errors.New("no sync wallet account received") + if len(response.Keypairs) != 2 { + return errors.New("no sync keypairs received") } return nil }) diff --git a/protocol/messenger_wallet.go b/protocol/messenger_wallet.go index 0281f488b..875b9ac86 100644 --- a/protocol/messenger_wallet.go +++ b/protocol/messenger_wallet.go @@ -9,6 +9,7 @@ import ( "go.uber.org/zap" ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/status-im/status-go/account" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/protocol/common" @@ -83,17 +84,59 @@ func (m *Messenger) UpdateKeypairName(keyUID string, name string) error { return ErrCannotChangeKeypairName } clock, _ := m.getLastClockWithRelatedChat() - err := m.settings.UpdateKeypairName(keyUID, name, clock) + err := m.settings.UpdateKeypairName(keyUID, name, clock, keyUID == m.account.KeyUID) if err != nil { return err } - dbKeypair, err := m.settings.GetKeypairByKeyUID(m.account.KeyUID) + return m.resolveAndSyncKeypairOrJustWalletAccount(keyUID, types.Address{}, clock, m.dispatchMessage) +} + +func (m *Messenger) UpdateAccountPosition(address types.Address, position int64) error { + acc, err := m.settings.GetAccountByAddress(address) if err != nil { return err } - return m.syncKeypair(dbKeypair, false, m.dispatchMessage) + clock, _ := m.getLastClockWithRelatedChat() + acc.Clock = clock + + err = m.settings.UpdateAccountPosition(address, position, clock) + if err != nil { + return err + } + + return m.resolveAndSyncKeypairOrJustWalletAccount(acc.KeyUID, acc.Address, acc.Clock, m.dispatchMessage) +} + +func (m *Messenger) resolveAndSetAccountPropsMaintainedByBackend(acc *accounts.Account) error { + // Account position is fully maintained by the backend, no need client to set it explicitly. + // To support DragAndDrop feature for accounts there is exposed `UpdateAccountPosition` which + // moves an account to the passed position. + // + // Account operability is fully maintained by the backend, for new accounts created on this device + // it is always set to fully operable, while for accounts received by syncing process or fetched from waku + // is set by logic placed in `resolveAccountOperability` function. + // + // TODO: making not or partially operable accounts fully operable will be added later, but for sure it will + // be handled by the backend only, no need client to set it explicitly. + + dbAccount, err := m.settings.GetAccountByAddress(acc.Address) + if err != nil && err != accounts.ErrDbAccountNotFound { + return err + } + if dbAccount != nil { + acc.Position = dbAccount.Position + acc.Operable = dbAccount.Operable + } else { + pos, err := m.settings.GetPositionForNextNewAccount() + if err != nil { + return err + } + acc.Position = pos + acc.Operable = accounts.AccountFullyOperable + } + return nil } func (m *Messenger) SaveOrUpdateKeypair(keypair *accounts.Keypair) error { @@ -106,56 +149,121 @@ func (m *Messenger) SaveOrUpdateKeypair(keypair *accounts.Keypair) error { for _, acc := range keypair.Accounts { acc.Clock = clock + err := m.resolveAndSetAccountPropsMaintainedByBackend(acc) + if err != nil { + return err + } } err := m.settings.SaveOrUpdateKeypair(keypair) if err != nil { return err } - return m.syncKeypair(keypair, false, m.dispatchMessage) + + return m.resolveAndSyncKeypairOrJustWalletAccount(keypair.KeyUID, types.Address{}, keypair.Clock, m.dispatchMessage) } func (m *Messenger) SaveOrUpdateAccount(acc *accounts.Account) error { clock, _ := m.getLastClockWithRelatedChat() acc.Clock = clock - err := m.settings.SaveOrUpdateAccounts([]*accounts.Account{acc}) + err := m.resolveAndSetAccountPropsMaintainedByBackend(acc) if err != nil { return err } - return m.syncWalletAccount(acc, m.dispatchMessage) + + err = m.settings.SaveOrUpdateAccounts([]*accounts.Account{acc}, true) + if err != nil { + return err + } + + return m.resolveAndSyncKeypairOrJustWalletAccount(acc.KeyUID, acc.Address, acc.Clock, m.dispatchMessage) +} + +func (m *Messenger) deleteKeystoreFileForAddress(address types.Address) error { + acc, err := m.settings.GetAccountByAddress(address) + if err != nil { + return err + } + + if acc.Operable == accounts.AccountNonOperable || acc.Operable == accounts.AccountPartiallyOperable { + return nil + } + + if acc.Type != accounts.AccountTypeWatch { + kp, err := m.settings.GetKeypairByKeyUID(acc.KeyUID) + if err != nil { + return err + } + + lastAcccountOfKeypairWithTheSameKey := len(kp.Accounts) == 1 + + knownKeycardsForKeyUID, err := m.settings.GetKeycardByKeyUID(acc.KeyUID) + if err != nil { + return err + } + + if len(knownKeycardsForKeyUID) == 0 { + err = m.accountsManager.DeleteAccount(address) + var e *account.ErrCannotLocateKeyFile + if err != nil && !errors.As(err, &e) { + return err + } + + if acc.Type != accounts.AccountTypeKey { + if lastAcccountOfKeypairWithTheSameKey { + err = m.accountsManager.DeleteAccount(types.Address(ethcommon.HexToAddress(kp.DerivedFrom))) + var e *account.ErrCannotLocateKeyFile + if err != nil && !errors.As(err, &e) { + return err + } + } + } + } else { + if lastAcccountOfKeypairWithTheSameKey { + knownKeycards, err := m.settings.GetAllKnownKeycards() + if err != nil { + return err + } + + for _, kc := range knownKeycards { + if kc.KeyUID == acc.KeyUID { + clock := uint64(time.Now().Unix()) + err = m.RemoveMigratedAccountsForKeycard(context.Background(), kc.KeycardUID, kc.AccountsAddresses, clock) + if err != nil { + return err + } + } + } + } + } + } + + return nil } func (m *Messenger) DeleteAccount(address types.Address) error { + err := m.deleteKeystoreFileForAddress(address) + if err != nil { + return err + } acc, err := m.settings.GetAccountByAddress(address) if err != nil { return err } - err = m.settings.DeleteAccount(address) + clock, _ := m.getLastClockWithRelatedChat() + + err = m.settings.DeleteAccount(address, clock) if err != nil { return err } - clock, chat := m.getLastClockWithRelatedChat() - acc.Clock = clock - acc.Removed = true - - err = m.syncWalletAccount(acc, m.dispatchMessage) - if err != nil { - return err - } - - chat.LastClockValue = clock - return m.saveChat(chat) + return m.resolveAndSyncKeypairOrJustWalletAccount(acc.KeyUID, acc.Address, clock, m.dispatchMessage) } func (m *Messenger) prepareSyncAccountMessage(acc *accounts.Account) *protobuf.SyncAccount { - if acc.Chat { - return nil - } - return &protobuf.SyncAccount{ Clock: acc.Clock, Address: acc.Address.Bytes(), @@ -169,6 +277,7 @@ func (m *Messenger) prepareSyncAccountMessage(acc *accounts.Account) *protobuf.S Chat: acc.Chat, Hidden: acc.Hidden, Removed: acc.Removed, + Position: acc.Position, } } @@ -194,6 +303,7 @@ func (m *Messenger) prepareSyncKeypairMessage(kp *accounts.Keypair) (*protobuf.S DerivedFrom: kp.DerivedFrom, LastUsedDerivationIndex: kp.LastUsedDerivationIndex, SyncedFrom: kp.SyncedFrom, + Removed: kp.Removed, } if kp.SyncedFrom == "" { @@ -213,24 +323,13 @@ func (m *Messenger) prepareSyncKeypairMessage(kp *accounts.Keypair) (*protobuf.S message.Accounts = append(message.Accounts, sAcc) } - return message, nil -} - -func (m *Messenger) prepareSyncKeypairFullMessage(kp *accounts.Keypair) (*protobuf.SyncKeypairFull, error) { - syncKpMsg, err := m.prepareSyncKeypairMessage(kp) - if err != nil { - return nil, err - } - syncKcMsgs, err := m.prepareSyncKeycardsMessage(kp.KeyUID) if err != nil { return nil, err } + message.Keycards = syncKcMsgs - return &protobuf.SyncKeypairFull{ - Keypair: syncKpMsg, - Keycards: syncKcMsgs, - }, nil + return message, nil } func (m *Messenger) syncWalletAccount(acc *accounts.Account, rawMessageHandler RawMessageHandler) error { @@ -261,7 +360,7 @@ func (m *Messenger) syncWalletAccount(acc *accounts.Account, rawMessageHandler R return err } -func (m *Messenger) syncKeypair(keypair *accounts.Keypair, fullKeypairSync bool, rawMessageHandler RawMessageHandler) (err error) { +func (m *Messenger) syncKeypair(keypair *accounts.Keypair, rawMessageHandler RawMessageHandler) (err error) { if !m.hasPairedDevices() { return nil } @@ -273,32 +372,70 @@ func (m *Messenger) syncKeypair(keypair *accounts.Keypair, fullKeypairSync bool, rawMessage := common.RawMessage{ LocalChatID: chat.ID, ResendAutomatically: true, + MessageType: protobuf.ApplicationMetadataMessage_SYNC_KEYPAIR, } - if fullKeypairSync { - message, err := m.prepareSyncKeypairFullMessage(keypair) - if err != nil { - return err - } + message, err := m.prepareSyncKeypairMessage(keypair) + if err != nil { + return err + } - rawMessage.MessageType = protobuf.ApplicationMetadataMessage_SYNC_FULL_KEYPAIR - rawMessage.Payload, err = proto.Marshal(message) - if err != nil { - return err - } - } else { - message, err := m.prepareSyncKeypairMessage(keypair) - if err != nil { - return err - } - - rawMessage.MessageType = protobuf.ApplicationMetadataMessage_SYNC_KEYPAIR - rawMessage.Payload, err = proto.Marshal(message) - if err != nil { - return err - } + rawMessage.Payload, err = proto.Marshal(message) + if err != nil { + return err } _, err = rawMessageHandler(ctx, rawMessage) return err } + +// This function resolves which protobuf message needs to be sent. +// +// If `KeyUID` is empty (means it's a watch only account) we send `protobuf.SyncAccount` message +// otherwise means the account belong to a keypai, hence we send `protobuf.SyncKeypair` message +func (m *Messenger) resolveAndSyncKeypairOrJustWalletAccount(keyUID string, address types.Address, clock uint64, rawMessageHandler RawMessageHandler) error { + if !m.hasPairedDevices() { + return nil + } + + if keyUID == "" { + dbAccount, err := m.settings.GetAccountByAddress(address) + if err != nil && err != accounts.ErrDbAccountNotFound { + return err + } + if dbAccount == nil { + dbAccount = &accounts.Account{ + Address: address, + Clock: clock, + Removed: true, + } + } + err = m.syncWalletAccount(dbAccount, rawMessageHandler) + if err != nil { + return err + } + } else { + dbKeypair, err := m.settings.GetKeypairByKeyUID(keyUID) + if err != nil && err != accounts.ErrDbKeypairNotFound { + return err + } + + if dbKeypair == nil { + // In case entire keypair was removed (happens if user removes the last account for a keypair). + dbKeypair = &accounts.Keypair{ + KeyUID: keyUID, + Clock: clock, + Removed: true, + } + } + + err = m.syncKeypair(dbKeypair, rawMessageHandler) + if err != nil { + return err + } + } + + _, chat := m.getLastClockWithRelatedChat() + chat.LastClockValue = clock + return m.saveChat(chat) +} diff --git a/protocol/protobuf/application_metadata_message.pb.go b/protocol/protobuf/application_metadata_message.pb.go index 1bbc3481f..d61b6e92d 100644 --- a/protocol/protobuf/application_metadata_message.pb.go +++ b/protocol/protobuf/application_metadata_message.pb.go @@ -88,10 +88,9 @@ const ( ApplicationMetadataMessage_SYNC_KEYCARD_ACTION ApplicationMetadataMessage_Type = 63 ApplicationMetadataMessage_SYNC_SOCIAL_LINKS ApplicationMetadataMessage_Type = 64 ApplicationMetadataMessage_SYNC_ENS_USERNAME_DETAIL ApplicationMetadataMessage_Type = 65 - ApplicationMetadataMessage_SYNC_FULL_KEYPAIR ApplicationMetadataMessage_Type = 66 - ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION ApplicationMetadataMessage_Type = 67 - ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE ApplicationMetadataMessage_Type = 68 - ApplicationMetadataMessage_COMMUNITY_ADMIN_MESSAGE ApplicationMetadataMessage_Type = 69 + ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION ApplicationMetadataMessage_Type = 66 + ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE ApplicationMetadataMessage_Type = 67 + ApplicationMetadataMessage_COMMUNITY_ADMIN_MESSAGE ApplicationMetadataMessage_Type = 68 ) var ApplicationMetadataMessage_Type_name = map[int32]string{ @@ -160,10 +159,9 @@ var ApplicationMetadataMessage_Type_name = map[int32]string{ 63: "SYNC_KEYCARD_ACTION", 64: "SYNC_SOCIAL_LINKS", 65: "SYNC_ENS_USERNAME_DETAIL", - 66: "SYNC_FULL_KEYPAIR", - 67: "SYNC_ACTIVITY_CENTER_NOTIFICATION", - 68: "SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE", - 69: "COMMUNITY_ADMIN_MESSAGE", + 66: "SYNC_ACTIVITY_CENTER_NOTIFICATION", + 67: "SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE", + 68: "COMMUNITY_ADMIN_MESSAGE", } var ApplicationMetadataMessage_Type_value = map[string]int32{ @@ -232,10 +230,9 @@ var ApplicationMetadataMessage_Type_value = map[string]int32{ "SYNC_KEYCARD_ACTION": 63, "SYNC_SOCIAL_LINKS": 64, "SYNC_ENS_USERNAME_DETAIL": 65, - "SYNC_FULL_KEYPAIR": 66, - "SYNC_ACTIVITY_CENTER_NOTIFICATION": 67, - "SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE": 68, - "COMMUNITY_ADMIN_MESSAGE": 69, + "SYNC_ACTIVITY_CENTER_NOTIFICATION": 66, + "SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE": 67, + "COMMUNITY_ADMIN_MESSAGE": 68, } func (x ApplicationMetadataMessage_Type) String() string { @@ -314,67 +311,67 @@ func init() { } var fileDescriptor_ad09a6406fcf24c7 = []byte{ - // 985 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x6d, 0x73, 0x13, 0x37, - 0x10, 0x6e, 0x20, 0x4d, 0x40, 0x79, 0x53, 0x44, 0x5e, 0x9c, 0x77, 0xc7, 0x40, 0x08, 0xd0, 0x9a, - 0x16, 0xda, 0x4e, 0x5b, 0x4a, 0x5b, 0x59, 0xda, 0xd8, 0xc2, 0x77, 0xd2, 0x21, 0xe9, 0xdc, 0x71, - 0xbf, 0x68, 0x4c, 0x71, 0x99, 0xcc, 0x00, 0xf1, 0x10, 0xe7, 0x43, 0x7e, 0x5a, 0x7f, 0x45, 0xff, - 0x52, 0x47, 0xf7, 0xea, 0x24, 0x97, 0xe6, 0x53, 0xe2, 0xdd, 0x67, 0x77, 0xb5, 0xcf, 0x3e, 0xbb, - 0x87, 0x1a, 0x83, 0xd1, 0xe8, 0xc3, 0xf1, 0x5f, 0x83, 0xf1, 0xf1, 0xc9, 0x27, 0xf7, 0x71, 0x38, - 0x1e, 0xbc, 0x1b, 0x8c, 0x07, 0xee, 0xe3, 0xf0, 0xf4, 0x74, 0xf0, 0x7e, 0xd8, 0x1c, 0x7d, 0x3e, - 0x19, 0x9f, 0x90, 0x3b, 0xc9, 0x9f, 0xb7, 0x67, 0x7f, 0x37, 0xfe, 0xc5, 0x68, 0x93, 0x96, 0x01, + // 977 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x6b, 0x73, 0x13, 0x37, + 0x14, 0x6d, 0x20, 0x4d, 0x40, 0x79, 0x29, 0x22, 0x0f, 0xe7, 0xed, 0x18, 0x08, 0x01, 0x5a, 0xd3, + 0x42, 0xdb, 0x69, 0x4b, 0x69, 0x2b, 0x4b, 0x37, 0xb6, 0xf0, 0xae, 0xb4, 0x48, 0x5a, 0x77, 0xdc, + 0x2f, 0x1a, 0x53, 0x5c, 0x26, 0x33, 0x40, 0x3c, 0xc4, 0xf9, 0x90, 0xbf, 0xd3, 0x5f, 0xd1, 0x9f, + 0xd7, 0xd1, 0x3e, 0x9d, 0x64, 0xd3, 0x7c, 0x4a, 0x7c, 0xef, 0xd1, 0x95, 0xee, 0xb9, 0xe7, 0x9e, + 0x45, 0x8d, 0xc1, 0x68, 0xf4, 0xe1, 0xf8, 0xaf, 0xc1, 0xf8, 0xf8, 0xe4, 0x93, 0xfb, 0x38, 0x1c, + 0x0f, 0xde, 0x0d, 0xc6, 0x03, 0xf7, 0x71, 0x78, 0x7a, 0x3a, 0x78, 0x3f, 0x6c, 0x8e, 0x3e, 0x9f, + 0x8c, 0x4f, 0xc8, 0x9d, 0xe4, 0xcf, 0xdb, 0xb3, 0xbf, 0x1b, 0xff, 0x62, 0xb4, 0x49, 0xcb, 0x03, 0x61, 0x86, 0x0f, 0x53, 0x38, 0xd9, 0x46, 0x77, 0x4f, 0x8f, 0xdf, 0x7f, 0x1a, 0x8c, 0xcf, 0x3e, - 0x0f, 0x6b, 0x53, 0xf5, 0xa9, 0xc3, 0x79, 0x5d, 0x1a, 0x48, 0x0d, 0xcd, 0x8e, 0x06, 0xe7, 0x1f, - 0x4e, 0x06, 0xef, 0x6a, 0xb7, 0x12, 0x5f, 0xfe, 0x93, 0xbc, 0x42, 0xd3, 0xe3, 0xf3, 0xd1, 0xb0, - 0x76, 0xbb, 0x3e, 0x75, 0xb8, 0xf8, 0xfc, 0x71, 0x33, 0xaf, 0xd7, 0xbc, 0xbe, 0x56, 0xd3, 0x9e, - 0x8f, 0x86, 0x3a, 0x09, 0x6b, 0xfc, 0xb3, 0x84, 0xa6, 0xfd, 0x4f, 0x32, 0x87, 0x66, 0x63, 0xd9, - 0x95, 0xea, 0x0f, 0x89, 0xbf, 0x20, 0x18, 0xcd, 0xb3, 0x0e, 0xb5, 0x2e, 0x04, 0x63, 0x68, 0x1b, - 0xf0, 0x14, 0x21, 0x68, 0x91, 0x29, 0x69, 0x29, 0xb3, 0x2e, 0x8e, 0x38, 0xb5, 0x80, 0x6f, 0x91, - 0x1d, 0xb4, 0x11, 0x42, 0xd8, 0x02, 0x6d, 0x3a, 0x22, 0xca, 0xcc, 0x45, 0xc8, 0x6d, 0xb2, 0x8a, - 0x96, 0x23, 0x2a, 0xb4, 0x13, 0xd2, 0x58, 0x1a, 0x04, 0xd4, 0x0a, 0x25, 0xf1, 0xb4, 0x37, 0x9b, - 0xbe, 0x64, 0x17, 0xcd, 0x5f, 0x92, 0xfb, 0x68, 0x4f, 0xc3, 0x9b, 0x18, 0x8c, 0x75, 0x94, 0x73, - 0x0d, 0xc6, 0xb8, 0x23, 0xa5, 0x9d, 0xd5, 0x54, 0x1a, 0xca, 0x12, 0xd0, 0x0c, 0x79, 0x82, 0x0e, - 0x28, 0x63, 0x10, 0x59, 0x77, 0x13, 0x76, 0x96, 0x3c, 0x45, 0x8f, 0x38, 0xb0, 0x40, 0x48, 0xb8, - 0x11, 0x7c, 0x87, 0xac, 0xa3, 0x7b, 0x39, 0x68, 0xd2, 0x71, 0x97, 0xac, 0x20, 0x6c, 0x40, 0xf2, - 0x0b, 0x56, 0x44, 0xf6, 0xd0, 0xd6, 0xe5, 0xdc, 0x93, 0x80, 0x39, 0x4f, 0xcd, 0x95, 0x26, 0x5d, - 0x46, 0x20, 0x9e, 0xaf, 0x76, 0x53, 0xc6, 0x54, 0x2c, 0x2d, 0x5e, 0x20, 0xfb, 0x68, 0xe7, 0xaa, - 0x3b, 0x8a, 0x5b, 0x81, 0x60, 0xce, 0xcf, 0x05, 0x2f, 0x92, 0x5d, 0xb4, 0x99, 0xcf, 0x83, 0x29, - 0x0e, 0x8e, 0xf2, 0x1e, 0x68, 0x2b, 0x0c, 0x84, 0x20, 0x2d, 0x5e, 0x22, 0x0d, 0xb4, 0x1b, 0xc5, - 0xa6, 0xe3, 0xa4, 0xb2, 0xe2, 0x48, 0xb0, 0x34, 0x85, 0x86, 0xb6, 0x30, 0x56, 0xa7, 0x94, 0x63, - 0xcf, 0xd0, 0xff, 0x63, 0x9c, 0x06, 0x13, 0x29, 0x69, 0x00, 0x2f, 0x93, 0x2d, 0xb4, 0x7e, 0x15, - 0xfc, 0x26, 0x06, 0xdd, 0xc7, 0x84, 0x3c, 0x40, 0xf5, 0x6b, 0x9c, 0x65, 0x8a, 0x7b, 0xbe, 0xeb, - 0xaa, 0x7a, 0x09, 0x7f, 0x78, 0xc5, 0xb7, 0x54, 0xe5, 0xce, 0xc2, 0x57, 0xbd, 0x04, 0x21, 0x54, - 0xaf, 0x85, 0xd3, 0x90, 0xf1, 0xbc, 0x46, 0x36, 0xd0, 0x6a, 0x5b, 0xab, 0x38, 0x4a, 0x68, 0x71, - 0x42, 0xf6, 0x84, 0x4d, 0xbb, 0x5b, 0x27, 0xcb, 0x68, 0x21, 0x35, 0x72, 0x90, 0x56, 0xd8, 0x3e, - 0xae, 0x79, 0x34, 0x53, 0x61, 0x18, 0x4b, 0x61, 0xfb, 0x8e, 0x83, 0x61, 0x5a, 0x44, 0x09, 0x7a, - 0x83, 0xd4, 0xd0, 0x4a, 0xe9, 0x9a, 0xc8, 0xb3, 0xe9, 0x5f, 0x5d, 0x7a, 0x8a, 0x69, 0x2b, 0xf7, - 0x5a, 0x09, 0x89, 0xb7, 0xc8, 0x12, 0x9a, 0x8b, 0x84, 0x2c, 0x64, 0xbf, 0xed, 0x77, 0x07, 0xb8, - 0x28, 0x77, 0x67, 0xc7, 0xbf, 0xc4, 0x58, 0x6a, 0x63, 0x93, 0xaf, 0xce, 0xae, 0xef, 0x85, 0x43, - 0x00, 0x13, 0xfb, 0xb2, 0xe7, 0x45, 0x55, 0xa5, 0x99, 0xac, 0x34, 0xae, 0x93, 0x4d, 0xb4, 0x46, - 0xa5, 0x92, 0xfd, 0x50, 0xc5, 0xc6, 0x85, 0x60, 0xb5, 0x60, 0xae, 0x45, 0x2d, 0xeb, 0xe0, 0xfd, - 0x62, 0xab, 0x92, 0x96, 0x35, 0x84, 0xaa, 0x07, 0x1c, 0x37, 0xfc, 0xd4, 0x4a, 0x73, 0x56, 0xca, - 0x78, 0x02, 0x39, 0xbe, 0x4f, 0x10, 0x9a, 0x69, 0x51, 0xd6, 0x8d, 0x23, 0xfc, 0xa0, 0x50, 0xa4, - 0x67, 0xb6, 0xe7, 0x3b, 0x65, 0x20, 0x2d, 0xe8, 0x14, 0xfa, 0xb0, 0x50, 0xe4, 0x65, 0x77, 0xba, - 0x8d, 0xc0, 0xf1, 0x81, 0x57, 0x5c, 0x25, 0x84, 0x0b, 0x13, 0x0a, 0x63, 0x80, 0xe3, 0x47, 0x09, - 0x13, 0x1e, 0xd3, 0x52, 0xaa, 0x1b, 0x52, 0xdd, 0xc5, 0x87, 0x64, 0x0d, 0x91, 0xf4, 0x85, 0x01, - 0x50, 0xed, 0x3a, 0xc2, 0x58, 0xa5, 0xfb, 0xf8, 0xb1, 0xa7, 0x31, 0xb1, 0x1b, 0xb0, 0x56, 0xc8, - 0x36, 0x7e, 0x42, 0xea, 0x68, 0xbb, 0x1c, 0x04, 0xd5, 0xac, 0x23, 0x7a, 0xe0, 0x42, 0xda, 0x96, - 0x60, 0x03, 0x21, 0xbb, 0xf8, 0xa9, 0x1f, 0x62, 0x12, 0x13, 0x69, 0x75, 0x24, 0x02, 0x70, 0x91, - 0x60, 0x36, 0xd6, 0x80, 0xbf, 0x2a, 0xb2, 0xe5, 0x3b, 0xf6, 0x75, 0x42, 0x66, 0x7a, 0x4a, 0xf2, - 0x3d, 0xca, 0x95, 0xd8, 0xf4, 0xac, 0x69, 0xb0, 0x3a, 0x5d, 0xae, 0x8b, 0xce, 0x67, 0xe4, 0x00, - 0x35, 0xae, 0xd5, 0x43, 0x29, 0xd7, 0x6f, 0x4a, 0xea, 0x0b, 0x70, 0xd6, 0x8a, 0xc1, 0xdf, 0xfa, - 0x5e, 0xf2, 0xd0, 0xbc, 0x42, 0x0f, 0x74, 0x21, 0x7b, 0xfc, 0xdc, 0xab, 0xe1, 0xd2, 0xfb, 0x2e, - 0x00, 0x5e, 0xf8, 0x14, 0xf9, 0x0d, 0xaa, 0x44, 0x7c, 0x57, 0x68, 0xc2, 0xea, 0xd8, 0x58, 0xe0, - 0x2e, 0x36, 0xa0, 0xf1, 0xf7, 0xc5, 0xa8, 0x27, 0xd1, 0x45, 0x7f, 0x3f, 0x14, 0xa3, 0xbe, 0xd4, - 0xb9, 0xe3, 0xc0, 0x84, 0xf1, 0x89, 0x7f, 0x4c, 0x8f, 0x4f, 0x05, 0x05, 0x01, 0xd0, 0x1e, 0xe0, - 0x9f, 0xbc, 0x3f, 0x49, 0x91, 0x49, 0xdc, 0x9f, 0xdb, 0xb0, 0x54, 0xfa, 0xcf, 0xc5, 0xcc, 0x0d, - 0xed, 0x01, 0xcf, 0xaf, 0x32, 0x7e, 0xe9, 0xcf, 0x48, 0x99, 0x97, 0x51, 0xc9, 0x20, 0xb8, 0xb2, - 0x71, 0xbf, 0x78, 0x66, 0x32, 0x5f, 0x65, 0xdf, 0xaf, 0x8a, 0x61, 0x77, 0xa1, 0xef, 0x3f, 0x40, - 0xf8, 0x57, 0x7f, 0xde, 0x73, 0x0b, 0xa3, 0x9a, 0xbb, 0xec, 0x7e, 0xfc, 0x56, 0x50, 0x64, 0x14, - 0x13, 0x34, 0x70, 0x5e, 0x47, 0x06, 0xff, 0x4e, 0xb6, 0x51, 0x2d, 0x31, 0x83, 0x34, 0x09, 0x6b, - 0x92, 0x86, 0xe0, 0x38, 0x58, 0x2a, 0x02, 0x4c, 0x8b, 0xa0, 0xa3, 0x38, 0x08, 0x8a, 0x22, 0x2d, - 0xf2, 0x10, 0xed, 0x57, 0x2e, 0xc0, 0xe4, 0x3d, 0xc3, 0xcc, 0x5f, 0xdd, 0x1b, 0x61, 0xce, 0xdf, - 0x0b, 0xc0, 0xdc, 0x8b, 0x68, 0x42, 0xf3, 0x3c, 0x9c, 0xb8, 0x34, 0xd0, 0x5a, 0xf8, 0x73, 0xae, - 0xf9, 0xec, 0x65, 0xfe, 0xc1, 0x7f, 0x3b, 0x93, 0xfc, 0xf7, 0xe2, 0xbf, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xe0, 0x3a, 0xd3, 0x3a, 0x97, 0x08, 0x00, 0x00, + 0x0f, 0x6b, 0x53, 0xf5, 0xa9, 0xc3, 0x79, 0x5d, 0x06, 0x48, 0x0d, 0xcd, 0x8e, 0x06, 0xe7, 0x1f, + 0x4e, 0x06, 0xef, 0x6a, 0xb7, 0x92, 0x5c, 0xfe, 0x93, 0xbc, 0x42, 0xd3, 0xe3, 0xf3, 0xd1, 0xb0, + 0x76, 0xbb, 0x3e, 0x75, 0xb8, 0xf8, 0xfc, 0x71, 0x33, 0xbf, 0xaf, 0x79, 0xfd, 0x5d, 0x4d, 0x7b, + 0x3e, 0x1a, 0xea, 0xe4, 0x58, 0xe3, 0x9f, 0x25, 0x34, 0xed, 0x7f, 0x92, 0x39, 0x34, 0x1b, 0xcb, + 0xae, 0x54, 0x7f, 0x48, 0xfc, 0x05, 0xc1, 0x68, 0x9e, 0x75, 0xa8, 0x75, 0x21, 0x18, 0x43, 0xdb, + 0x80, 0xa7, 0x08, 0x41, 0x8b, 0x4c, 0x49, 0x4b, 0x99, 0x75, 0x71, 0xc4, 0xa9, 0x05, 0x7c, 0x8b, + 0xec, 0xa0, 0x8d, 0x10, 0xc2, 0x16, 0x68, 0xd3, 0x11, 0x51, 0x16, 0x2e, 0x8e, 0xdc, 0x26, 0xab, + 0x68, 0x39, 0xa2, 0x42, 0x3b, 0x21, 0x8d, 0xa5, 0x41, 0x40, 0xad, 0x50, 0x12, 0x4f, 0xfb, 0xb0, + 0xe9, 0x4b, 0x76, 0x31, 0xfc, 0x25, 0xb9, 0x8f, 0xf6, 0x34, 0xbc, 0x89, 0xc1, 0x58, 0x47, 0x39, + 0xd7, 0x60, 0x8c, 0x3b, 0x52, 0xda, 0x59, 0x4d, 0xa5, 0xa1, 0x2c, 0x01, 0xcd, 0x90, 0x27, 0xe8, + 0x80, 0x32, 0x06, 0x91, 0x75, 0x37, 0x61, 0x67, 0xc9, 0x53, 0xf4, 0x88, 0x03, 0x0b, 0x84, 0x84, + 0x1b, 0xc1, 0x77, 0xc8, 0x3a, 0xba, 0x97, 0x83, 0x26, 0x13, 0x77, 0xc9, 0x0a, 0xc2, 0x06, 0x24, + 0xbf, 0x10, 0x45, 0x64, 0x0f, 0x6d, 0x5d, 0xae, 0x3d, 0x09, 0x98, 0xf3, 0xd4, 0x5c, 0x69, 0xd2, + 0x65, 0x04, 0xe2, 0xf9, 0xea, 0x34, 0x65, 0x4c, 0xc5, 0xd2, 0xe2, 0x05, 0xb2, 0x8f, 0x76, 0xae, + 0xa6, 0xa3, 0xb8, 0x15, 0x08, 0xe6, 0xfc, 0x5c, 0xf0, 0x22, 0xd9, 0x45, 0x9b, 0xf9, 0x3c, 0x98, + 0xe2, 0xe0, 0x28, 0xef, 0x81, 0xb6, 0xc2, 0x40, 0x08, 0xd2, 0xe2, 0x25, 0xd2, 0x40, 0xbb, 0x51, + 0x6c, 0x3a, 0x4e, 0x2a, 0x2b, 0x8e, 0x04, 0x4b, 0x4b, 0x68, 0x68, 0x0b, 0x63, 0x75, 0x4a, 0x39, + 0xf6, 0x0c, 0xfd, 0x3f, 0xc6, 0x69, 0x30, 0x91, 0x92, 0x06, 0xf0, 0x32, 0xd9, 0x42, 0xeb, 0x57, + 0xc1, 0x6f, 0x62, 0xd0, 0x7d, 0x4c, 0xc8, 0x03, 0x54, 0xbf, 0x26, 0x59, 0x96, 0xb8, 0xe7, 0xbb, + 0xae, 0xba, 0x2f, 0xe1, 0x0f, 0xaf, 0xf8, 0x96, 0xaa, 0xd2, 0xd9, 0xf1, 0x55, 0x2f, 0x41, 0x08, + 0xd5, 0x6b, 0xe1, 0x34, 0x64, 0x3c, 0xaf, 0x91, 0x0d, 0xb4, 0xda, 0xd6, 0x2a, 0x8e, 0x12, 0x5a, + 0x9c, 0x90, 0x3d, 0x61, 0xd3, 0xee, 0xd6, 0xc9, 0x32, 0x5a, 0x48, 0x83, 0x1c, 0xa4, 0x15, 0xb6, + 0x8f, 0x6b, 0x1e, 0xcd, 0x54, 0x18, 0xc6, 0x52, 0xd8, 0xbe, 0xe3, 0x60, 0x98, 0x16, 0x51, 0x82, + 0xde, 0x20, 0x35, 0xb4, 0x52, 0xa6, 0x26, 0xea, 0x6c, 0xfa, 0x57, 0x97, 0x99, 0x62, 0xda, 0xca, + 0xbd, 0x56, 0x42, 0xe2, 0x2d, 0xb2, 0x84, 0xe6, 0x22, 0x21, 0x0b, 0xd9, 0x6f, 0xfb, 0xdd, 0x01, + 0x2e, 0xca, 0xdd, 0xd9, 0xf1, 0x2f, 0x31, 0x96, 0xda, 0xd8, 0xe4, 0xab, 0xb3, 0xeb, 0x7b, 0xe1, + 0x10, 0xc0, 0xc4, 0xbe, 0xec, 0x79, 0x51, 0x55, 0x69, 0x26, 0xbb, 0x1a, 0xd7, 0xc9, 0x26, 0x5a, + 0xa3, 0x52, 0xc9, 0x7e, 0xa8, 0x62, 0xe3, 0x42, 0xb0, 0x5a, 0x30, 0xd7, 0xa2, 0x96, 0x75, 0xf0, + 0x7e, 0xb1, 0x55, 0x49, 0xcb, 0x1a, 0x42, 0xd5, 0x03, 0x8e, 0x1b, 0x7e, 0x6a, 0x65, 0x38, 0xbb, + 0xca, 0x78, 0x02, 0x39, 0xbe, 0x4f, 0x10, 0x9a, 0x69, 0x51, 0xd6, 0x8d, 0x23, 0xfc, 0xa0, 0x50, + 0xa4, 0x67, 0xb6, 0xe7, 0x3b, 0x65, 0x20, 0x2d, 0xe8, 0x14, 0xfa, 0xb0, 0x50, 0xe4, 0xe5, 0x74, + 0xba, 0x8d, 0xc0, 0xf1, 0x81, 0x57, 0x5c, 0x25, 0x84, 0x0b, 0x13, 0x0a, 0x63, 0x80, 0xe3, 0x47, + 0x09, 0x13, 0x1e, 0xd3, 0x52, 0xaa, 0x1b, 0x52, 0xdd, 0xc5, 0x87, 0x64, 0x0d, 0x91, 0xf4, 0x85, + 0x01, 0x50, 0xed, 0x3a, 0xc2, 0x58, 0xa5, 0xfb, 0xf8, 0xb1, 0xa7, 0x31, 0x89, 0x1b, 0xb0, 0x56, + 0xc8, 0x36, 0x7e, 0x42, 0xea, 0x68, 0xbb, 0x1c, 0x04, 0xd5, 0xac, 0x23, 0x7a, 0xe0, 0x42, 0xda, + 0x96, 0x60, 0x03, 0x21, 0xbb, 0xf8, 0xa9, 0x1f, 0x62, 0x72, 0x26, 0xd2, 0xea, 0x48, 0x04, 0xe0, + 0x22, 0xc1, 0x6c, 0xac, 0x01, 0x7f, 0x55, 0x54, 0xcb, 0x77, 0xec, 0xeb, 0x84, 0xcc, 0xd4, 0x4a, + 0xf2, 0x3d, 0xca, 0x95, 0xd8, 0xf4, 0xac, 0x69, 0xb0, 0x3a, 0x5d, 0xae, 0x8b, 0xc9, 0x67, 0xe4, + 0x00, 0x35, 0xae, 0xd5, 0x43, 0x29, 0xd7, 0x6f, 0x4a, 0xea, 0x0b, 0x70, 0xd6, 0x8a, 0xc1, 0xdf, + 0xfa, 0x5e, 0xf2, 0xa3, 0xf9, 0x0d, 0x3d, 0xd0, 0x85, 0xec, 0xf1, 0x73, 0xaf, 0x86, 0x4b, 0xef, + 0xbb, 0x00, 0x78, 0xe1, 0x4b, 0xe4, 0x1e, 0x54, 0x89, 0xf8, 0xae, 0xd0, 0x84, 0xd5, 0xb1, 0xb1, + 0xc0, 0x5d, 0x6c, 0x40, 0xe3, 0xef, 0x8b, 0x51, 0x4f, 0xa2, 0x8b, 0xfe, 0x7e, 0x28, 0x46, 0x7d, + 0xa9, 0x73, 0xc7, 0x81, 0x09, 0xe3, 0x0b, 0xff, 0x98, 0x9a, 0x4f, 0x05, 0x05, 0x01, 0xd0, 0x1e, + 0xe0, 0x9f, 0x7c, 0x3e, 0x29, 0x91, 0x49, 0xdc, 0xdb, 0x6d, 0x58, 0x2a, 0xfd, 0xe7, 0x62, 0xe6, + 0x86, 0xf6, 0x80, 0xe7, 0xae, 0x8c, 0x5f, 0x7a, 0x1b, 0x29, 0xeb, 0x32, 0x2a, 0x19, 0x04, 0x57, + 0x36, 0xee, 0x17, 0xcf, 0x4c, 0x96, 0xab, 0xec, 0xfb, 0x55, 0x31, 0xec, 0x2e, 0xf4, 0xfd, 0x07, + 0x08, 0xff, 0xea, 0xed, 0x3d, 0x8f, 0x30, 0xaa, 0xb9, 0xcb, 0xfc, 0xe3, 0xb7, 0x82, 0x22, 0xa3, + 0x98, 0xa0, 0x81, 0xf3, 0x3a, 0x32, 0xf8, 0x77, 0xb2, 0x8d, 0x6a, 0x49, 0x18, 0xa4, 0x49, 0x58, + 0x93, 0x34, 0x04, 0xc7, 0xc1, 0x52, 0x11, 0x60, 0x4a, 0x1e, 0xa2, 0xfd, 0x4a, 0xa5, 0x4f, 0x1a, + 0x17, 0x6e, 0x79, 0x7b, 0xbd, 0x11, 0xe6, 0xbc, 0x31, 0x00, 0x66, 0x5e, 0x2d, 0x13, 0xe2, 0xe6, + 0xe1, 0x84, 0xa5, 0xf0, 0xd6, 0xc2, 0x9f, 0x73, 0xcd, 0x67, 0x2f, 0xf3, 0x2f, 0xfb, 0xdb, 0x99, + 0xe4, 0xbf, 0x17, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xf3, 0x96, 0x25, 0x5f, 0x80, 0x08, 0x00, + 0x00, } diff --git a/protocol/protobuf/application_metadata_message.proto b/protocol/protobuf/application_metadata_message.proto index 3a4d94208..f2787a52d 100644 --- a/protocol/protobuf/application_metadata_message.proto +++ b/protocol/protobuf/application_metadata_message.proto @@ -78,9 +78,8 @@ message ApplicationMetadataMessage { SYNC_KEYCARD_ACTION = 63; SYNC_SOCIAL_LINKS = 64; SYNC_ENS_USERNAME_DETAIL = 65; - SYNC_FULL_KEYPAIR = 66; - SYNC_ACTIVITY_CENTER_NOTIFICATION = 67; - SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE = 68; - COMMUNITY_ADMIN_MESSAGE = 69; + SYNC_ACTIVITY_CENTER_NOTIFICATION = 66; + SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE = 67; + COMMUNITY_ADMIN_MESSAGE = 68; } } diff --git a/protocol/protobuf/pairing.pb.go b/protocol/protobuf/pairing.pb.go index c2bb3510b..1bed497d0 100644 --- a/protocol/protobuf/pairing.pb.go +++ b/protocol/protobuf/pairing.pb.go @@ -168,7 +168,7 @@ func (x SyncTrustedUser_TrustStatus) String() string { } func (SyncTrustedUser_TrustStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{31, 0} + return fileDescriptor_d61ab7221f0b5518, []int{30, 0} } type SyncVerificationRequest_VerificationStatus int32 @@ -202,7 +202,7 @@ func (x SyncVerificationRequest_VerificationStatus) String() string { } func (SyncVerificationRequest_VerificationStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{32, 0} + return fileDescriptor_d61ab7221f0b5518, []int{31, 0} } type SyncContactRequestDecision_DecisionStatus int32 @@ -227,7 +227,7 @@ func (x SyncContactRequestDecision_DecisionStatus) String() string { } func (SyncContactRequestDecision_DecisionStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{33, 0} + return fileDescriptor_d61ab7221f0b5518, []int{32, 0} } type SyncKeycardAction_Action int32 @@ -270,7 +270,7 @@ func (x SyncKeycardAction_Action) String() string { } func (SyncKeycardAction_Action) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{38, 0} + return fileDescriptor_d61ab7221f0b5518, []int{37, 0} } // `FetchingBackedUpDataDetails` is used to describe how many messages a single backup data structure consists of @@ -334,8 +334,8 @@ type Backup struct { ProfileDetails *FetchingBackedUpDataDetails `protobuf:"bytes,8,opt,name=profileDetails,proto3" json:"profileDetails,omitempty"` Setting *SyncSetting `protobuf:"bytes,9,opt,name=setting,proto3" json:"setting,omitempty"` SettingsDetails *FetchingBackedUpDataDetails `protobuf:"bytes,10,opt,name=settingsDetails,proto3" json:"settingsDetails,omitempty"` - FullKeypair *SyncKeypairFull `protobuf:"bytes,11,opt,name=fullKeypair,proto3" json:"fullKeypair,omitempty"` - FullKeypairDetails *FetchingBackedUpDataDetails `protobuf:"bytes,12,opt,name=fullKeypairDetails,proto3" json:"fullKeypairDetails,omitempty"` + Keypair *SyncKeypair `protobuf:"bytes,11,opt,name=keypair,proto3" json:"keypair,omitempty"` + KeypairDetails *FetchingBackedUpDataDetails `protobuf:"bytes,12,opt,name=keypairDetails,proto3" json:"keypairDetails,omitempty"` WatchOnlyAccount *SyncAccount `protobuf:"bytes,13,opt,name=watchOnlyAccount,proto3" json:"watchOnlyAccount,omitempty"` WatchOnlyAccountDetails *FetchingBackedUpDataDetails `protobuf:"bytes,14,opt,name=watchOnlyAccountDetails,proto3" json:"watchOnlyAccountDetails,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -438,16 +438,16 @@ func (m *Backup) GetSettingsDetails() *FetchingBackedUpDataDetails { return nil } -func (m *Backup) GetFullKeypair() *SyncKeypairFull { +func (m *Backup) GetKeypair() *SyncKeypair { if m != nil { - return m.FullKeypair + return m.Keypair } return nil } -func (m *Backup) GetFullKeypairDetails() *FetchingBackedUpDataDetails { +func (m *Backup) GetKeypairDetails() *FetchingBackedUpDataDetails { if m != nil { - return m.FullKeypairDetails + return m.KeypairDetails } return nil } @@ -2429,6 +2429,7 @@ type SyncAccount struct { Chat bool `protobuf:"varint,10,opt,name=chat,proto3" json:"chat,omitempty"` Hidden bool `protobuf:"varint,11,opt,name=hidden,proto3" json:"hidden,omitempty"` Removed bool `protobuf:"varint,12,opt,name=removed,proto3" json:"removed,omitempty"` + Position int64 `protobuf:"varint,13,opt,name=position,proto3" json:"position,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2543,6 +2544,13 @@ func (m *SyncAccount) GetRemoved() bool { return false } +func (m *SyncAccount) GetPosition() int64 { + if m != nil { + return m.Position + } + return 0 +} + type SyncKeypair struct { Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"` KeyUid string `protobuf:"bytes,2,opt,name=key_uid,json=keyUid,proto3" json:"key_uid,omitempty"` @@ -2552,6 +2560,8 @@ type SyncKeypair struct { LastUsedDerivationIndex uint64 `protobuf:"varint,6,opt,name=last_used_derivation_index,json=lastUsedDerivationIndex,proto3" json:"last_used_derivation_index,omitempty"` SyncedFrom string `protobuf:"bytes,7,opt,name=synced_from,json=syncedFrom,proto3" json:"synced_from,omitempty"` Accounts []*SyncAccount `protobuf:"bytes,8,rep,name=accounts,proto3" json:"accounts,omitempty"` + Keycards []*SyncKeycard `protobuf:"bytes,9,rep,name=keycards,proto3" json:"keycards,omitempty"` + Removed bool `protobuf:"varint,10,opt,name=removed,proto3" json:"removed,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2638,53 +2648,20 @@ func (m *SyncKeypair) GetAccounts() []*SyncAccount { return nil } -type SyncKeypairFull struct { - Keypair *SyncKeypair `protobuf:"bytes,1,opt,name=keypair,proto3" json:"keypair,omitempty"` - Keycards []*SyncKeycard `protobuf:"bytes,2,rep,name=keycards,proto3" json:"keycards,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *SyncKeypairFull) Reset() { *m = SyncKeypairFull{} } -func (m *SyncKeypairFull) String() string { return proto.CompactTextString(m) } -func (*SyncKeypairFull) ProtoMessage() {} -func (*SyncKeypairFull) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{28} -} - -func (m *SyncKeypairFull) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SyncKeypairFull.Unmarshal(m, b) -} -func (m *SyncKeypairFull) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SyncKeypairFull.Marshal(b, m, deterministic) -} -func (m *SyncKeypairFull) XXX_Merge(src proto.Message) { - xxx_messageInfo_SyncKeypairFull.Merge(m, src) -} -func (m *SyncKeypairFull) XXX_Size() int { - return xxx_messageInfo_SyncKeypairFull.Size(m) -} -func (m *SyncKeypairFull) XXX_DiscardUnknown() { - xxx_messageInfo_SyncKeypairFull.DiscardUnknown(m) -} - -var xxx_messageInfo_SyncKeypairFull proto.InternalMessageInfo - -func (m *SyncKeypairFull) GetKeypair() *SyncKeypair { - if m != nil { - return m.Keypair - } - return nil -} - -func (m *SyncKeypairFull) GetKeycards() []*SyncKeycard { +func (m *SyncKeypair) GetKeycards() []*SyncKeycard { if m != nil { return m.Keycards } return nil } +func (m *SyncKeypair) GetRemoved() bool { + if m != nil { + return m.Removed + } + return false +} + type SyncSavedAddress struct { Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` @@ -2703,7 +2680,7 @@ func (m *SyncSavedAddress) Reset() { *m = SyncSavedAddress{} } func (m *SyncSavedAddress) String() string { return proto.CompactTextString(m) } func (*SyncSavedAddress) ProtoMessage() {} func (*SyncSavedAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{29} + return fileDescriptor_d61ab7221f0b5518, []int{28} } func (m *SyncSavedAddress) XXX_Unmarshal(b []byte) error { @@ -2793,7 +2770,7 @@ func (m *SyncCommunitySettings) Reset() { *m = SyncCommunitySettings{} } func (m *SyncCommunitySettings) String() string { return proto.CompactTextString(m) } func (*SyncCommunitySettings) ProtoMessage() {} func (*SyncCommunitySettings) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{30} + return fileDescriptor_d61ab7221f0b5518, []int{29} } func (m *SyncCommunitySettings) XXX_Unmarshal(b []byte) error { @@ -2848,7 +2825,7 @@ func (m *SyncTrustedUser) Reset() { *m = SyncTrustedUser{} } func (m *SyncTrustedUser) String() string { return proto.CompactTextString(m) } func (*SyncTrustedUser) ProtoMessage() {} func (*SyncTrustedUser) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{31} + return fileDescriptor_d61ab7221f0b5518, []int{30} } func (m *SyncTrustedUser) XXX_Unmarshal(b []byte) error { @@ -2909,7 +2886,7 @@ func (m *SyncVerificationRequest) Reset() { *m = SyncVerificationRequest func (m *SyncVerificationRequest) String() string { return proto.CompactTextString(m) } func (*SyncVerificationRequest) ProtoMessage() {} func (*SyncVerificationRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{32} + return fileDescriptor_d61ab7221f0b5518, []int{31} } func (m *SyncVerificationRequest) XXX_Unmarshal(b []byte) error { @@ -3006,7 +2983,7 @@ func (m *SyncContactRequestDecision) Reset() { *m = SyncContactRequestDe func (m *SyncContactRequestDecision) String() string { return proto.CompactTextString(m) } func (*SyncContactRequestDecision) ProtoMessage() {} func (*SyncContactRequestDecision) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{33} + return fileDescriptor_d61ab7221f0b5518, []int{32} } func (m *SyncContactRequestDecision) XXX_Unmarshal(b []byte) error { @@ -3065,7 +3042,7 @@ func (m *BackedUpProfile) Reset() { *m = BackedUpProfile{} } func (m *BackedUpProfile) String() string { return proto.CompactTextString(m) } func (*BackedUpProfile) ProtoMessage() {} func (*BackedUpProfile) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{34} + return fileDescriptor_d61ab7221f0b5518, []int{33} } func (m *BackedUpProfile) XXX_Unmarshal(b []byte) error { @@ -3140,7 +3117,7 @@ func (m *RawMessage) Reset() { *m = RawMessage{} } func (m *RawMessage) String() string { return proto.CompactTextString(m) } func (*RawMessage) ProtoMessage() {} func (*RawMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{35} + return fileDescriptor_d61ab7221f0b5518, []int{34} } func (m *RawMessage) XXX_Unmarshal(b []byte) error { @@ -3189,7 +3166,7 @@ func (m *SyncRawMessage) Reset() { *m = SyncRawMessage{} } func (m *SyncRawMessage) String() string { return proto.CompactTextString(m) } func (*SyncRawMessage) ProtoMessage() {} func (*SyncRawMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{36} + return fileDescriptor_d61ab7221f0b5518, []int{35} } func (m *SyncRawMessage) XXX_Unmarshal(b []byte) error { @@ -3247,7 +3224,7 @@ func (m *SyncKeycard) Reset() { *m = SyncKeycard{} } func (m *SyncKeycard) String() string { return proto.CompactTextString(m) } func (*SyncKeycard) ProtoMessage() {} func (*SyncKeycard) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{37} + return fileDescriptor_d61ab7221f0b5518, []int{36} } func (m *SyncKeycard) XXX_Unmarshal(b []byte) error { @@ -3323,7 +3300,7 @@ func (m *SyncKeycardAction) Reset() { *m = SyncKeycardAction{} } func (m *SyncKeycardAction) String() string { return proto.CompactTextString(m) } func (*SyncKeycardAction) ProtoMessage() {} func (*SyncKeycardAction) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{38} + return fileDescriptor_d61ab7221f0b5518, []int{37} } func (m *SyncKeycardAction) XXX_Unmarshal(b []byte) error { @@ -3377,7 +3354,7 @@ func (m *SyncSocialLinks) Reset() { *m = SyncSocialLinks{} } func (m *SyncSocialLinks) String() string { return proto.CompactTextString(m) } func (*SyncSocialLinks) ProtoMessage() {} func (*SyncSocialLinks) Descriptor() ([]byte, []int) { - return fileDescriptor_d61ab7221f0b5518, []int{39} + return fileDescriptor_d61ab7221f0b5518, []int{38} } func (m *SyncSocialLinks) XXX_Unmarshal(b []byte) error { @@ -3451,7 +3428,6 @@ func init() { proto.RegisterType((*SyncProfilePictures)(nil), "protobuf.SyncProfilePictures") proto.RegisterType((*SyncAccount)(nil), "protobuf.SyncAccount") proto.RegisterType((*SyncKeypair)(nil), "protobuf.SyncKeypair") - proto.RegisterType((*SyncKeypairFull)(nil), "protobuf.SyncKeypairFull") proto.RegisterType((*SyncSavedAddress)(nil), "protobuf.SyncSavedAddress") proto.RegisterType((*SyncCommunitySettings)(nil), "protobuf.SyncCommunitySettings") proto.RegisterType((*SyncTrustedUser)(nil), "protobuf.SyncTrustedUser") @@ -3470,226 +3446,225 @@ func init() { } var fileDescriptor_d61ab7221f0b5518 = []byte{ - // 3528 bytes of a gzipped FileDescriptorProto + // 3517 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3a, 0x4d, 0x73, 0x23, 0x49, - 0x56, 0x53, 0x92, 0xac, 0x8f, 0x27, 0x59, 0x2e, 0x67, 0x7b, 0xa6, 0xd5, 0xee, 0x9e, 0xed, 0xee, - 0x9a, 0x9d, 0xd8, 0x86, 0x18, 0x3c, 0xe0, 0x01, 0x96, 0x9d, 0x8f, 0x18, 0xd4, 0x92, 0x66, 0xda, - 0xe3, 0xb6, 0x6c, 0xd2, 0xf6, 0x0c, 0x4b, 0x10, 0x51, 0xa4, 0xab, 0xd2, 0x56, 0xad, 0x4b, 0x55, - 0xa2, 0x32, 0x65, 0xa3, 0x3d, 0x10, 0x40, 0x04, 0x67, 0x08, 0x2e, 0xbb, 0xc7, 0x39, 0x13, 0x9c, - 0x88, 0xe0, 0x40, 0x04, 0x07, 0x4e, 0x04, 0xff, 0x01, 0x7e, 0x01, 0xc1, 0x85, 0x1b, 0x47, 0xe2, - 0x65, 0x66, 0x95, 0xaa, 0xf4, 0x61, 0xec, 0xe0, 0xc4, 0xc9, 0xf5, 0x5e, 0xbe, 0x7c, 0xf9, 0x32, - 0xdf, 0xf7, 0x93, 0x61, 0x73, 0xc2, 0x82, 0x24, 0x88, 0xae, 0xf6, 0x26, 0x49, 0x2c, 0x63, 0x52, - 0x57, 0x7f, 0x2e, 0xa6, 0x97, 0xbb, 0x8f, 0xbc, 0x11, 0x93, 0x6e, 0xe0, 0xf3, 0x48, 0x06, 0x72, - 0xa6, 0x97, 0x77, 0x1f, 0x89, 0x59, 0xe4, 0xb9, 0x82, 0x4b, 0x19, 0x44, 0x57, 0xc2, 0x20, 0x1d, - 0x36, 0x99, 0x84, 0x81, 0xc7, 0x64, 0x10, 0x47, 0xee, 0x98, 0x4b, 0xe6, 0x33, 0xc9, 0xdc, 0x31, - 0x17, 0x82, 0x5d, 0x71, 0x43, 0xb3, 0xed, 0xc5, 0xe3, 0xf1, 0x34, 0x0a, 0x64, 0xc0, 0xcd, 0x36, - 0x87, 0xc1, 0xd3, 0xaf, 0xb8, 0xf4, 0x46, 0x41, 0x74, 0xf5, 0x9a, 0x79, 0xd7, 0xdc, 0x3f, 0x9f, - 0xf4, 0x99, 0x64, 0x7d, 0x2e, 0x59, 0x10, 0x0a, 0xf2, 0x1c, 0x9a, 0x8a, 0x4f, 0x34, 0x1d, 0x5f, - 0xf0, 0xa4, 0x63, 0xbd, 0xb0, 0x5e, 0x6d, 0x52, 0x40, 0xd4, 0x50, 0x61, 0xc8, 0x4b, 0x68, 0xc9, - 0x58, 0xb2, 0x30, 0xa5, 0x28, 0x29, 0x8a, 0xa6, 0xc2, 0x69, 0x12, 0xe7, 0xaf, 0x6b, 0x50, 0x45, - 0xde, 0xd3, 0x09, 0xd9, 0x81, 0x0d, 0x2f, 0x8c, 0xbd, 0x6b, 0xc5, 0xa8, 0x42, 0x35, 0x40, 0xda, - 0x50, 0x0a, 0x7c, 0xb5, 0xb3, 0x41, 0x4b, 0x81, 0x4f, 0xbe, 0x84, 0xba, 0x17, 0x47, 0x92, 0x79, - 0x52, 0x74, 0xca, 0x2f, 0xca, 0xaf, 0x9a, 0xfb, 0x1f, 0xec, 0xa5, 0x2f, 0xb2, 0x77, 0x3a, 0x8b, - 0xbc, 0x83, 0x48, 0x48, 0x16, 0x86, 0xea, 0xae, 0x3d, 0x4d, 0xf9, 0xed, 0x3e, 0xcd, 0x36, 0x91, - 0x9f, 0x40, 0x33, 0x77, 0xd3, 0x4e, 0x45, 0xf1, 0x78, 0x5c, 0xe4, 0xd1, 0x33, 0x04, 0x33, 0x9a, - 0xa7, 0x25, 0xc7, 0xb0, 0x95, 0xb2, 0x31, 0x6f, 0xd0, 0xd9, 0x78, 0x61, 0xbd, 0x6a, 0xee, 0x7f, - 0x38, 0xdf, 0x7e, 0xc7, 0x83, 0xd1, 0xc5, 0xdd, 0xe4, 0x1c, 0x48, 0x8e, 0x7f, 0xca, 0xb3, 0xfa, - 0x10, 0x9e, 0x2b, 0x18, 0x90, 0x4f, 0xa0, 0x36, 0x49, 0xe2, 0xcb, 0x20, 0xe4, 0x9d, 0x9a, 0xe2, - 0xf5, 0x64, 0xce, 0x2b, 0xe5, 0x71, 0xa2, 0x09, 0x68, 0x4a, 0x49, 0x8e, 0xa0, 0x6d, 0x3e, 0x53, - 0x39, 0xea, 0x0f, 0x91, 0x63, 0x61, 0x33, 0xf9, 0x18, 0x6a, 0xc6, 0x08, 0x3b, 0x0d, 0xc5, 0xe7, - 0xdd, 0xe2, 0x13, 0x9f, 0xea, 0x45, 0x9a, 0x52, 0xe1, 0xe3, 0xa6, 0x56, 0x9b, 0x0a, 0x00, 0x0f, - 0x7a, 0xdc, 0x85, 0xdd, 0xe4, 0x33, 0x68, 0x5e, 0x4e, 0xc3, 0xf0, 0x90, 0xcf, 0xd0, 0x81, 0x3a, - 0xcd, 0xc5, 0x97, 0x40, 0x29, 0xcc, 0xe2, 0x57, 0xd3, 0x30, 0xa4, 0x79, 0x6a, 0xd4, 0x4c, 0x0e, - 0x4c, 0x05, 0x6a, 0x3d, 0x48, 0x33, 0xcb, 0x0c, 0x48, 0x17, 0xec, 0x5b, 0x26, 0xbd, 0xd1, 0x71, - 0x14, 0xce, 0xba, 0x9e, 0x17, 0x4f, 0x23, 0xd9, 0xd9, 0x5c, 0xf5, 0x3c, 0x66, 0x91, 0x2e, 0x91, - 0x13, 0x17, 0x1e, 0x2f, 0xe2, 0x52, 0xf1, 0xda, 0x0f, 0x11, 0x6f, 0x1d, 0x17, 0xe7, 0x3f, 0x2b, - 0xd0, 0x3a, 0x9a, 0x86, 0x32, 0x48, 0x4f, 0x24, 0x50, 0x89, 0xd8, 0x98, 0x2b, 0xbf, 0x6c, 0x50, - 0xf5, 0x4d, 0x9e, 0x41, 0x43, 0x06, 0x63, 0x2e, 0x24, 0x1b, 0x4f, 0x94, 0x77, 0x96, 0xe9, 0x1c, - 0x81, 0xab, 0x3a, 0x2c, 0x79, 0x71, 0xd4, 0x29, 0xab, 0x6d, 0x73, 0x04, 0xf9, 0x12, 0xc0, 0x8b, - 0xc3, 0x38, 0x71, 0x47, 0x4c, 0x8c, 0x8c, 0x03, 0xbe, 0x98, 0x0b, 0x9d, 0x3f, 0x7b, 0xaf, 0x87, - 0x84, 0x6f, 0x98, 0x18, 0xd1, 0x86, 0x97, 0x7e, 0x92, 0x27, 0x18, 0x03, 0x90, 0x41, 0xe0, 0x2b, - 0x07, 0x2c, 0xd3, 0x9a, 0x82, 0x0f, 0x7c, 0xf2, 0x23, 0xd8, 0xba, 0xe6, 0x33, 0x8f, 0x25, 0xbe, - 0x6b, 0xc2, 0xa6, 0x72, 0xa7, 0x06, 0x6d, 0x1b, 0xf4, 0x89, 0xc6, 0x92, 0xc7, 0x50, 0xbb, 0xe6, - 0x33, 0x77, 0x1a, 0xf8, 0xca, 0x47, 0x1a, 0xb4, 0x7a, 0xcd, 0x67, 0xe7, 0x81, 0x4f, 0x3e, 0x87, - 0x6a, 0x30, 0x66, 0x57, 0x1c, 0xed, 0x1f, 0x25, 0xfb, 0xe1, 0x1a, 0xc9, 0x0e, 0x4c, 0xdc, 0x3d, - 0x40, 0x62, 0x6a, 0xf6, 0x90, 0x8f, 0xe1, 0x91, 0x37, 0x15, 0x32, 0x1e, 0x07, 0x3f, 0xd7, 0xd1, - 0x56, 0x09, 0xa6, 0x5c, 0xa0, 0x41, 0x49, 0x61, 0x49, 0x5d, 0x6d, 0xf7, 0x25, 0x34, 0xb2, 0x3b, - 0x62, 0x08, 0x0c, 0x22, 0x9f, 0xff, 0x49, 0xc7, 0x7a, 0x51, 0x7e, 0x55, 0xa6, 0x1a, 0xd8, 0xfd, - 0x37, 0x0b, 0x36, 0x0b, 0xa7, 0xe5, 0x85, 0xb7, 0x0a, 0xc2, 0xa7, 0xaa, 0x2a, 0xe5, 0x54, 0xd5, - 0x81, 0xda, 0x84, 0xcd, 0xc2, 0x98, 0xf9, 0x4a, 0x15, 0x2d, 0x9a, 0x82, 0x78, 0xdc, 0x6d, 0xe0, - 0x4b, 0xd4, 0x01, 0x3e, 0xa2, 0x06, 0xc8, 0x7b, 0x50, 0x1d, 0xf1, 0xe0, 0x6a, 0x24, 0xcd, 0xdb, - 0x1a, 0x88, 0xec, 0x42, 0x1d, 0x1d, 0x5c, 0x04, 0x3f, 0xe7, 0xea, 0x4d, 0xcb, 0x34, 0x83, 0xc9, - 0x07, 0xb0, 0x99, 0xa8, 0x2f, 0x57, 0xb2, 0xe4, 0x8a, 0x4b, 0xf5, 0xa6, 0x65, 0xda, 0xd2, 0xc8, - 0x33, 0x85, 0x9b, 0x07, 0xf8, 0x7a, 0x2e, 0xc0, 0x3b, 0xbf, 0x28, 0xc1, 0xa3, 0xb7, 0xb1, 0xc7, - 0x42, 0xa3, 0x99, 0x13, 0x23, 0xdc, 0x6f, 0x41, 0xe5, 0x9a, 0xcf, 0x84, 0x7a, 0x8a, 0xe6, 0xfe, - 0xcb, 0xb9, 0x16, 0x56, 0x10, 0xef, 0x1d, 0xf2, 0x19, 0x55, 0xe4, 0xe4, 0x53, 0x68, 0x8d, 0x51, - 0x4d, 0xcc, 0x78, 0x57, 0x49, 0xf9, 0xc4, 0x7b, 0xab, 0x95, 0x48, 0x0b, 0xb4, 0x78, 0xc3, 0x09, - 0x13, 0xe2, 0x36, 0x4e, 0x7c, 0x63, 0xb5, 0x19, 0x8c, 0xaf, 0x88, 0xe9, 0xf6, 0x90, 0xcf, 0xd4, - 0x6b, 0x35, 0x68, 0x0a, 0x92, 0x57, 0x99, 0xc9, 0x19, 0xa1, 0x74, 0x56, 0x68, 0xd0, 0x45, 0xf4, - 0xee, 0xaf, 0x41, 0x19, 0x37, 0xac, 0xf2, 0x27, 0x02, 0x15, 0x4c, 0x9c, 0x4a, 0xdc, 0x16, 0x55, - 0xdf, 0xce, 0x3f, 0x5a, 0xf0, 0x6e, 0xe1, 0xb2, 0x9c, 0x27, 0x6f, 0x78, 0x18, 0xc6, 0x68, 0xe5, - 0xc6, 0xba, 0xdd, 0x1b, 0x9e, 0x88, 0x20, 0x8e, 0x14, 0xb3, 0x0d, 0xda, 0x36, 0xe8, 0x6f, 0x35, - 0x16, 0x0d, 0x65, 0xc2, 0xb9, 0x72, 0x14, 0xcd, 0xb9, 0x8a, 0xe0, 0x81, 0xaf, 0x72, 0x37, 0xbf, - 0x09, 0x3c, 0xee, 0x2a, 0x51, 0xf4, 0x6d, 0x41, 0xa3, 0x86, 0x28, 0xd0, 0x9c, 0x40, 0xce, 0x26, - 0xdc, 0xdc, 0xd9, 0x10, 0x9c, 0xcd, 0x26, 0x2a, 0x02, 0x88, 0xe0, 0x2a, 0x62, 0x72, 0x9a, 0x70, - 0x75, 0xe1, 0x16, 0x9d, 0x23, 0x9c, 0xef, 0x2d, 0xb0, 0x51, 0xec, 0x7c, 0x36, 0x5e, 0x93, 0xe1, - 0x7f, 0x04, 0x5b, 0x41, 0x8e, 0xca, 0xcd, 0xd2, 0x7d, 0x3b, 0x8f, 0x2e, 0xc8, 0xac, 0x44, 0x2a, - 0x2f, 0x89, 0x94, 0x3e, 0x6c, 0xa5, 0x68, 0xfd, 0xe9, 0x13, 0x6d, 0xa8, 0xf2, 0x23, 0x05, 0x9d, - 0xff, 0xb0, 0xe0, 0xf1, 0x9a, 0x82, 0xe1, 0x9e, 0xb5, 0xc8, 0x07, 0xb0, 0x69, 0xb2, 0x9e, 0xab, - 0xdc, 0xdf, 0x88, 0xd4, 0x32, 0x48, 0xed, 0xab, 0x4f, 0xa0, 0xce, 0x23, 0xe1, 0xe6, 0x04, 0xab, - 0xf1, 0x48, 0xa8, 0x37, 0x7e, 0x09, 0xad, 0x90, 0x09, 0xe9, 0x4e, 0x27, 0x3e, 0x93, 0x5c, 0xc7, - 0xb2, 0x0a, 0x6d, 0x22, 0xee, 0x5c, 0xa3, 0xf0, 0xce, 0x62, 0x26, 0x24, 0x1f, 0xbb, 0x92, 0x5d, - 0x61, 0x69, 0x50, 0xc6, 0x3b, 0x6b, 0xd4, 0x19, 0xbb, 0x12, 0xe4, 0x43, 0x68, 0x87, 0x68, 0x23, - 0x6e, 0x14, 0x78, 0xd7, 0xea, 0x10, 0x1d, 0xce, 0x36, 0x15, 0x76, 0x68, 0x90, 0xce, 0x9f, 0x57, - 0xe1, 0xc9, 0xda, 0xea, 0x88, 0xfc, 0x3a, 0xec, 0xe4, 0x05, 0x71, 0xd5, 0xde, 0x70, 0x66, 0x6e, - 0x4f, 0x72, 0x02, 0xbd, 0xd5, 0x2b, 0xff, 0x8f, 0x9f, 0x02, 0x75, 0xcb, 0x7c, 0x9f, 0xfb, 0x2a, - 0x28, 0xd7, 0xa9, 0x06, 0xd0, 0x4e, 0x2e, 0x50, 0xc9, 0xdc, 0x57, 0x65, 0x47, 0x9d, 0xa6, 0x20, - 0xd2, 0x8f, 0xa7, 0x28, 0x53, 0x53, 0xd3, 0x2b, 0x00, 0xe9, 0x13, 0x3e, 0x8e, 0x6f, 0xb8, 0xaf, - 0xaa, 0x82, 0x3a, 0x4d, 0x41, 0xf2, 0x02, 0x5a, 0x23, 0x26, 0x5c, 0xc5, 0xd6, 0x9d, 0x0a, 0x95, - 0xdf, 0xeb, 0x14, 0x46, 0x4c, 0x74, 0x11, 0x75, 0xae, 0x92, 0xc4, 0x0d, 0x4f, 0x82, 0xcb, 0xb4, - 0x22, 0x17, 0x92, 0xc9, 0xa9, 0x4e, 0xdf, 0x65, 0x4a, 0xf2, 0x4b, 0xa7, 0x6a, 0x45, 0x15, 0xd2, - 0xc9, 0x54, 0xc8, 0x94, 0x72, 0x4b, 0x51, 0x36, 0x15, 0xce, 0x90, 0x7c, 0x01, 0x4f, 0x4d, 0x75, - 0xe9, 0x26, 0xfc, 0x8f, 0xa7, 0x5c, 0x48, 0xad, 0x45, 0xb5, 0x85, 0x77, 0x6c, 0xb5, 0xa3, 0x63, - 0x48, 0xa8, 0xa6, 0x50, 0xca, 0xc4, 0xfd, 0x7c, 0xfd, 0x76, 0xed, 0x06, 0xdb, 0x6b, 0xb7, 0xf7, - 0x94, 0x67, 0x7c, 0x09, 0xcf, 0x16, 0xb7, 0xe3, 0x73, 0x48, 0x6e, 0x8e, 0x27, 0x6a, 0xff, 0x93, - 0xe2, 0x7e, 0xaa, 0x28, 0xf4, 0xf9, 0xeb, 0x19, 0x68, 0x01, 0x1e, 0xad, 0x67, 0xa0, 0x25, 0x78, - 0x09, 0x2d, 0x3f, 0x10, 0x93, 0x90, 0xcd, 0xb4, 0x7d, 0xed, 0x28, 0xd5, 0x37, 0x0d, 0x0e, 0x6d, - 0xcc, 0xb9, 0x5d, 0xf6, 0xf7, 0xb4, 0xc4, 0x59, 0xed, 0xef, 0x4b, 0x46, 0x5d, 0x5a, 0x61, 0xd4, - 0x8b, 0x96, 0x5b, 0x5e, 0xb2, 0x5c, 0xe7, 0x35, 0xec, 0x2e, 0x1e, 0x7c, 0x32, 0xbd, 0x08, 0x03, - 0xaf, 0x37, 0x62, 0xf7, 0x8c, 0x35, 0xce, 0x3f, 0x94, 0x61, 0xb3, 0xd0, 0x9a, 0xfc, 0xaf, 0xfb, - 0x5a, 0xca, 0x31, 0x9f, 0x43, 0x73, 0x92, 0x04, 0x37, 0x4c, 0x72, 0xf7, 0x9a, 0xcf, 0x4c, 0x05, - 0x00, 0x06, 0x85, 0xd9, 0xe8, 0x05, 0x46, 0x55, 0xe1, 0x25, 0xc1, 0x04, 0xe5, 0x52, 0x7e, 0xd9, - 0xa2, 0x79, 0x14, 0x16, 0x04, 0x3f, 0x8b, 0x83, 0xc8, 0x78, 0x65, 0x9d, 0x1a, 0x08, 0xd3, 0xa5, - 0xb6, 0x55, 0xee, 0xab, 0x82, 0xa0, 0x4e, 0x33, 0x78, 0xee, 0x34, 0xb5, 0xbc, 0xd3, 0x1c, 0x83, - 0x6d, 0xb4, 0x2b, 0x5c, 0x19, 0xbb, 0xc8, 0xc7, 0x54, 0x59, 0x1f, 0xae, 0x6b, 0xc0, 0x0c, 0xf9, - 0x59, 0xfc, 0x4d, 0x1c, 0x44, 0xb4, 0x9d, 0x14, 0x60, 0xf2, 0x19, 0xd4, 0xd3, 0xb2, 0xdf, 0xb4, - 0x19, 0xcf, 0xd7, 0x30, 0x32, 0xfd, 0x86, 0xa0, 0xd9, 0x06, 0xcc, 0x60, 0x3c, 0xf2, 0x92, 0xd9, - 0x44, 0x66, 0x4e, 0x3f, 0x47, 0xa8, 0xfc, 0x36, 0xe1, 0x9e, 0x64, 0x73, 0xd7, 0x9f, 0x23, 0x30, - 0x69, 0x19, 0x52, 0x74, 0x60, 0x55, 0xa8, 0xb4, 0xd4, 0xcb, 0xb5, 0xe7, 0xe8, 0x43, 0x3e, 0x13, - 0x58, 0xde, 0x3c, 0xbd, 0xe3, 0x46, 0x46, 0x5f, 0x56, 0xa6, 0xaf, 0xf7, 0x01, 0x26, 0xca, 0x36, - 0x94, 0xba, 0xb4, 0xfe, 0x1b, 0x1a, 0x83, 0xda, 0xca, 0x94, 0x5e, 0xce, 0x2b, 0xfd, 0x8e, 0xc0, - 0xfa, 0x58, 0xd7, 0x2d, 0x69, 0xa9, 0xdc, 0xa0, 0x55, 0x04, 0x0f, 0x7c, 0xb4, 0xdb, 0xb4, 0x75, - 0x9c, 0xe1, 0x6a, 0x55, 0x2b, 0x3e, 0xc3, 0x1d, 0x28, 0x25, 0x6a, 0xf7, 0xad, 0xe9, 0xc3, 0x14, - 0x40, 0xbe, 0x82, 0xed, 0x84, 0xdf, 0x70, 0x16, 0x72, 0xdf, 0x35, 0x95, 0x53, 0x5a, 0x2b, 0xe7, - 0xba, 0x2b, 0x6a, 0x48, 0xb2, 0x46, 0x26, 0x29, 0x22, 0x84, 0xf3, 0x37, 0x25, 0xb0, 0x17, 0xdd, - 0x82, 0x7c, 0x91, 0x6b, 0xef, 0x97, 0x2a, 0xbf, 0x35, 0x09, 0x2c, 0xd7, 0xdc, 0x7f, 0x0d, 0x2d, - 0xf3, 0x7a, 0x78, 0x4b, 0xd1, 0x29, 0x2d, 0x96, 0xf0, 0xeb, 0xfd, 0x90, 0x36, 0x27, 0xd9, 0x37, - 0x36, 0x8f, 0xb5, 0xb4, 0x82, 0x2c, 0x2b, 0xbb, 0xba, 0x43, 0x8c, 0xf4, 0x8a, 0xe9, 0x8e, 0xff, - 0xc3, 0x88, 0xc1, 0xf9, 0x31, 0x6c, 0xa9, 0x55, 0x14, 0xc8, 0xe4, 0x93, 0xfb, 0xc5, 0x87, 0xcf, - 0x61, 0x27, 0xdd, 0x78, 0xa4, 0xe7, 0x3a, 0x82, 0x72, 0x76, 0xdf, 0xdd, 0xbf, 0x0b, 0xef, 0xe9, - 0xae, 0x53, 0x06, 0x37, 0x81, 0x9c, 0xf5, 0x78, 0x24, 0x79, 0x72, 0xc7, 0x7e, 0x1b, 0xca, 0x81, - 0xaf, 0x9f, 0xb7, 0x45, 0xf1, 0xd3, 0xe9, 0xeb, 0x18, 0x57, 0xe4, 0xd0, 0xf5, 0x3c, 0xae, 0x9c, - 0xe9, 0xbe, 0x5c, 0x06, 0xda, 0x59, 0x8a, 0x5c, 0xfa, 0x81, 0x18, 0x07, 0x42, 0x3c, 0x80, 0x8d, - 0x0b, 0x1f, 0x2c, 0xb3, 0x19, 0xc6, 0xb2, 0x90, 0x57, 0x39, 0xfa, 0x5a, 0x5a, 0xf1, 0x30, 0x69, - 0x78, 0x36, 0x0c, 0xa6, 0x2b, 0xd1, 0xab, 0x30, 0x91, 0x0b, 0xce, 0x23, 0xf5, 0x54, 0x75, 0x5a, - 0x1b, 0x31, 0x71, 0xca, 0x79, 0xe4, 0xfc, 0x95, 0x05, 0xcf, 0xef, 0x3e, 0x41, 0x90, 0x10, 0xde, - 0x67, 0x66, 0xd9, 0xf5, 0xd4, 0xba, 0x1b, 0xe5, 0x09, 0x8c, 0x7d, 0xbf, 0x5a, 0x6c, 0xfc, 0xd7, - 0x71, 0xa4, 0x4f, 0xd9, 0xfa, 0xd3, 0x9c, 0x7f, 0x6a, 0xc0, 0x0f, 0xee, 0xde, 0xbf, 0x14, 0x6a, - 0x96, 0x7a, 0xf8, 0x4a, 0xbe, 0x87, 0xbf, 0x84, 0xed, 0xbc, 0xb8, 0xf3, 0x9a, 0xbb, 0xbd, 0xff, - 0x93, 0xfb, 0x8a, 0xbc, 0x97, 0x07, 0xb0, 0x44, 0xa7, 0x76, 0xb4, 0x80, 0xc9, 0x07, 0xa8, 0x4a, - 0x21, 0x40, 0x11, 0xa8, 0x24, 0x9c, 0xa5, 0x49, 0x47, 0x7d, 0xa3, 0xc8, 0x7e, 0x6a, 0x0d, 0x26, - 0xe7, 0xcc, 0x11, 0x98, 0x90, 0x98, 0xb1, 0x38, 0x93, 0x77, 0x32, 0x18, 0xeb, 0x35, 0x33, 0xef, - 0x54, 0xed, 0x67, 0x8b, 0xa6, 0x20, 0xa6, 0x37, 0x36, 0x95, 0xa3, 0xac, 0x4b, 0x37, 0x90, 0xee, - 0x69, 0x27, 0xe1, 0x2c, 0x9d, 0x93, 0xaa, 0x14, 0xd1, 0xc2, 0x9e, 0x76, 0x12, 0xce, 0x8c, 0x8f, - 0x2d, 0x45, 0xd1, 0xa6, 0x2e, 0x3b, 0xf2, 0x51, 0xf4, 0x12, 0xb6, 0xc7, 0x7c, 0x7c, 0xc1, 0x13, - 0x31, 0x0a, 0x26, 0x69, 0x05, 0xd7, 0x7a, 0xe0, 0x43, 0x1e, 0x65, 0x1c, 0x74, 0xbd, 0x47, 0xed, - 0xf1, 0x02, 0x86, 0xfc, 0x85, 0x35, 0xaf, 0xe1, 0x56, 0x95, 0x97, 0x9b, 0xea, 0xc8, 0xd7, 0xf7, - 0x3e, 0x32, 0x6d, 0x0f, 0x96, 0xca, 0xd1, 0xac, 0x0c, 0x5b, 0x5e, 0xc2, 0x67, 0xf6, 0x79, 0xc8, - 0x51, 0x03, 0x6d, 0xed, 0x32, 0x06, 0x5c, 0x70, 0xb6, 0xad, 0x05, 0x67, 0x73, 0xfe, 0xcb, 0x02, - 0x7b, 0xd1, 0x5a, 0x08, 0x40, 0x75, 0x18, 0xe3, 0x97, 0xfd, 0x0e, 0xd9, 0x82, 0xe6, 0x90, 0xdf, - 0x1e, 0x47, 0xfc, 0x2c, 0x3e, 0x8e, 0xb8, 0x6d, 0x91, 0xc7, 0xf0, 0x68, 0xc8, 0x6f, 0x4f, 0x74, - 0x25, 0xf3, 0x75, 0x12, 0x4f, 0x27, 0x18, 0xfc, 0xec, 0x12, 0x69, 0x42, 0xed, 0x88, 0x47, 0xc8, - 0xc4, 0x2e, 0x93, 0x06, 0x6c, 0x50, 0x54, 0x98, 0x5d, 0x21, 0x04, 0xda, 0xbd, 0x42, 0xfd, 0x68, - 0x6f, 0x20, 0x93, 0x2c, 0x12, 0x1f, 0x44, 0x37, 0x81, 0x54, 0x87, 0xdb, 0x55, 0xb2, 0x03, 0xf6, - 0x62, 0xca, 0xb6, 0x6b, 0xe4, 0x07, 0xb0, 0x9b, 0x61, 0xe7, 0x2a, 0x49, 0xd7, 0xeb, 0xe4, 0x11, - 0x6c, 0x65, 0xeb, 0x87, 0x01, 0xb6, 0x0f, 0x76, 0x43, 0x9f, 0xb1, 0xf4, 0x60, 0x36, 0x38, 0x7f, - 0x69, 0x81, 0xbd, 0xa8, 0x58, 0xd2, 0x81, 0x9d, 0x45, 0xdc, 0x81, 0x1f, 0xe2, 0x0b, 0x3c, 0x85, - 0xc7, 0x8b, 0x2b, 0x27, 0x3c, 0xf2, 0x83, 0xe8, 0xca, 0xb6, 0xc8, 0x33, 0xe8, 0x2c, 0x2e, 0xa6, - 0xd1, 0xd7, 0x2e, 0xad, 0x5a, 0xed, 0x73, 0x2f, 0xc4, 0x32, 0xce, 0x2e, 0x3b, 0x7f, 0x66, 0xc1, - 0x93, 0xb5, 0xda, 0xc6, 0xe7, 0x3c, 0x8f, 0xae, 0xa3, 0xf8, 0x36, 0xb2, 0xdf, 0x41, 0x60, 0x7e, - 0x66, 0x0b, 0xea, 0xb9, 0x33, 0x5a, 0x50, 0x9f, 0xf3, 0x24, 0x9b, 0xd0, 0xe8, 0xb1, 0xc8, 0xe3, - 0x61, 0xc8, 0x7d, 0xbb, 0x82, 0xfb, 0xce, 0xb0, 0x5b, 0xe1, 0xbe, 0xbd, 0x41, 0xb6, 0x61, 0xf3, - 0x3c, 0x52, 0xe0, 0x77, 0x71, 0x22, 0x47, 0x33, 0xbb, 0xea, 0x7c, 0x6f, 0x41, 0x0b, 0xed, 0xf1, - 0x75, 0x1c, 0x5f, 0x8f, 0x59, 0x72, 0xbd, 0x3e, 0xd4, 0x4f, 0x93, 0xd0, 0x24, 0x2e, 0xfc, 0xcc, - 0x7a, 0xfe, 0x72, 0xae, 0xe7, 0x7f, 0x0a, 0x0d, 0x55, 0xaf, 0xbb, 0x48, 0xab, 0x83, 0x4a, 0x5d, - 0x21, 0xce, 0x93, 0x30, 0xdf, 0xb8, 0x6d, 0x14, 0x1b, 0xb7, 0xf7, 0x01, 0x8c, 0xb1, 0xa2, 0x85, - 0x56, 0xb5, 0x85, 0x1a, 0x4c, 0x57, 0x3a, 0x7f, 0x0a, 0xef, 0xa2, 0x84, 0x83, 0x48, 0x9c, 0x0b, - 0x9e, 0xe0, 0x41, 0x7a, 0x62, 0xba, 0x46, 0xd4, 0x5d, 0xa8, 0x4f, 0x0d, 0x9d, 0x91, 0x37, 0x83, - 0xd5, 0x00, 0x73, 0xc4, 0x02, 0x35, 0xeb, 0xd0, 0x85, 0x5c, 0x4d, 0xc1, 0x07, 0x85, 0xbe, 0xb2, - 0x52, 0x10, 0xcf, 0xf9, 0x46, 0x97, 0x4b, 0xbd, 0x90, 0xb3, 0xe4, 0x4d, 0x20, 0x64, 0x9c, 0xcc, - 0xf2, 0xc1, 0xd3, 0x2a, 0x04, 0xcf, 0xf7, 0x01, 0x3c, 0x24, 0xd4, 0x77, 0x31, 0xc1, 0xdd, 0x60, - 0xba, 0xd2, 0xf9, 0x57, 0x0b, 0x08, 0x32, 0x33, 0xbf, 0x02, 0x9c, 0x04, 0x9e, 0x9c, 0x26, 0x7c, - 0xe5, 0x64, 0x2a, 0x37, 0x3e, 0x2c, 0xad, 0x19, 0x1f, 0x96, 0xd5, 0x60, 0x65, 0x69, 0x7c, 0x58, - 0x51, 0xe8, 0x74, 0x7c, 0xf8, 0x14, 0x1a, 0xaa, 0x93, 0x52, 0xf3, 0x43, 0x3d, 0x8a, 0x51, 0xf3, - 0xc3, 0xd3, 0x95, 0xf3, 0xc3, 0xaa, 0x22, 0x58, 0x33, 0x3f, 0xac, 0xe5, 0xe7, 0x87, 0x23, 0x78, - 0xb4, 0x7c, 0x13, 0xb1, 0x7e, 0x44, 0xfa, 0x3b, 0x50, 0x9f, 0x18, 0x22, 0x53, 0x1e, 0x3e, 0x2b, - 0x86, 0xc4, 0x22, 0x27, 0x9a, 0x51, 0x3b, 0x7f, 0x57, 0x82, 0x66, 0x6e, 0x36, 0xbf, 0x46, 0xef, - 0x1d, 0xa8, 0x31, 0xdf, 0x4f, 0xb8, 0x10, 0xe9, 0x7b, 0x19, 0x30, 0x2f, 0x52, 0xb9, 0x20, 0x52, - 0xb1, 0xe6, 0xd7, 0x1d, 0x58, 0xae, 0xe6, 0x27, 0x50, 0x99, 0x30, 0x39, 0x32, 0xf5, 0xbb, 0xfa, - 0xce, 0x34, 0x55, 0xcd, 0x69, 0x2a, 0x3f, 0x16, 0xaf, 0x99, 0x19, 0xa5, 0x19, 0x8b, 0xef, 0xc0, - 0x06, 0x1f, 0xc7, 0x3f, 0x0b, 0x54, 0xee, 0x6b, 0x50, 0x0d, 0xa0, 0xaa, 0x6e, 0x59, 0x18, 0x72, - 0x69, 0x46, 0x21, 0x06, 0x42, 0xe6, 0x68, 0x46, 0xa6, 0x27, 0x52, 0xdf, 0x4a, 0xad, 0x81, 0xef, - 0xf3, 0xc8, 0xf4, 0x42, 0x06, 0x5a, 0x3f, 0x07, 0x71, 0x7e, 0x69, 0x9e, 0x2b, 0xfd, 0x49, 0x65, - 0xf5, 0x73, 0xe5, 0x1e, 0xa5, 0xb4, 0x72, 0x94, 0x5d, 0x2e, 0x4e, 0x49, 0x73, 0xd3, 0x48, 0xf5, - 0xad, 0x1a, 0x7f, 0x9e, 0x04, 0x37, 0xdc, 0x77, 0x2f, 0x93, 0x78, 0x6c, 0x5e, 0xa9, 0x69, 0x70, - 0x5f, 0x25, 0xf1, 0x98, 0x7c, 0x06, 0xbb, 0xba, 0x45, 0x17, 0xdc, 0x77, 0xd5, 0x82, 0x99, 0x34, - 0xaa, 0x59, 0xbb, 0x76, 0xf4, 0xc7, 0xaa, 0x61, 0x17, 0xdc, 0xef, 0x67, 0xeb, 0x07, 0xb8, 0xac, - 0xc7, 0x4e, 0x91, 0x97, 0xb2, 0xd7, 0x0f, 0x0b, 0x1a, 0xa5, 0xb8, 0xff, 0x86, 0xaa, 0x3a, 0xf2, - 0x6d, 0xd0, 0x9a, 0xdf, 0x72, 0x32, 0x32, 0x67, 0xaa, 0xab, 0xfc, 0xdc, 0xaf, 0x4f, 0xe4, 0x63, - 0xf5, 0x0e, 0xea, 0x97, 0x2a, 0x6b, 0xd5, 0x0f, 0x42, 0x86, 0x96, 0xa6, 0x54, 0x78, 0xac, 0x99, - 0x2f, 0xa7, 0x76, 0xbc, 0xbc, 0x03, 0x57, 0x69, 0x46, 0xe6, 0xfc, 0xb7, 0xa5, 0x43, 0xc8, 0x29, - 0xbb, 0xe1, 0x7e, 0xd7, 0x58, 0x65, 0xce, 0x5e, 0xad, 0xa2, 0xbd, 0xae, 0xfa, 0x31, 0xe1, 0x19, - 0x34, 0x2e, 0xd9, 0x4d, 0x3c, 0x4d, 0x02, 0xa9, 0x55, 0x53, 0xa7, 0x73, 0xc4, 0x1d, 0xb1, 0xf5, - 0x25, 0xb4, 0x74, 0xae, 0x77, 0xf3, 0x2e, 0xdc, 0xd4, 0x38, 0x3d, 0xc1, 0xf9, 0x55, 0xd8, 0xd6, - 0x41, 0x51, 0x8c, 0xe2, 0x44, 0xaa, 0x66, 0x56, 0x18, 0x7b, 0xdd, 0x52, 0x0b, 0xa7, 0x88, 0xc7, - 0xa6, 0x56, 0x60, 0x1e, 0xe0, 0x91, 0x30, 0x05, 0x1b, 0x7e, 0xa2, 0x1d, 0x05, 0xc2, 0x95, 0x5c, - 0xa4, 0x66, 0x5b, 0x0d, 0xc4, 0x19, 0x17, 0xf2, 0x9b, 0x4a, 0xbd, 0x62, 0x6f, 0x38, 0xbf, 0xb0, - 0x74, 0xf4, 0x5e, 0x9a, 0x07, 0xac, 0x31, 0xcb, 0xc5, 0xba, 0xae, 0xb4, 0x5c, 0xd7, 0x0d, 0xe0, - 0xf9, 0x48, 0x87, 0x61, 0x97, 0x25, 0xde, 0x28, 0xb8, 0xe1, 0xae, 0x98, 0x4e, 0x26, 0x28, 0x3b, - 0x8f, 0xd8, 0x45, 0x68, 0x66, 0x41, 0x75, 0xfa, 0xcc, 0x90, 0x75, 0x35, 0xd5, 0xa9, 0x26, 0x1a, - 0x68, 0x1a, 0xe7, 0xef, 0x2d, 0x6d, 0x0c, 0x26, 0x3d, 0x62, 0x6e, 0xb9, 0xe7, 0xf8, 0xf9, 0x0b, - 0xa8, 0x9a, 0xd2, 0x4e, 0x97, 0xe5, 0x0b, 0x33, 0x94, 0x1c, 0xc3, 0xbd, 0xb3, 0xf9, 0xa4, 0x90, - 0x9a, 0x4d, 0xce, 0xa7, 0xd0, 0xcc, 0xa1, 0x55, 0x9a, 0x1f, 0x1e, 0x0e, 0x8f, 0xbf, 0x1b, 0xea, - 0x34, 0x7f, 0x46, 0xcf, 0x4f, 0xcf, 0x06, 0x7d, 0xdb, 0x52, 0xe9, 0x7a, 0xa8, 0xc0, 0xef, 0x8e, - 0xe9, 0xd9, 0x9b, 0x9f, 0xda, 0x25, 0xe7, 0xfb, 0xb2, 0x9e, 0xa5, 0xe5, 0xcb, 0x05, 0x53, 0x05, - 0xad, 0x11, 0x9e, 0x40, 0x45, 0xf9, 0x8f, 0x31, 0x26, 0xfc, 0xc6, 0x0b, 0xc9, 0xd8, 0x38, 0x78, - 0x49, 0xc6, 0x68, 0x5c, 0xde, 0x08, 0x43, 0x50, 0x74, 0x95, 0xfa, 0xf8, 0x1c, 0x81, 0x2a, 0x31, - 0xd3, 0x1f, 0x9d, 0xd4, 0xcc, 0x88, 0x38, 0xc3, 0x75, 0xd5, 0x0f, 0x38, 0x09, 0x17, 0x93, 0x38, - 0x12, 0x69, 0x64, 0xcc, 0x60, 0x0c, 0xb2, 0x58, 0xb9, 0x07, 0x7a, 0xb3, 0xb6, 0xbf, 0x86, 0xc1, - 0x74, 0x25, 0xe1, 0xab, 0x67, 0xb2, 0x75, 0xf5, 0xb2, 0xbf, 0x59, 0x7c, 0xd9, 0x15, 0xb7, 0xde, - 0x5b, 0x51, 0x26, 0xaf, 0x9a, 0xe4, 0x6a, 0x1d, 0x36, 0xb2, 0xc6, 0xfb, 0xf7, 0x81, 0xac, 0x29, - 0xb9, 0xf2, 0xba, 0x38, 0x19, 0x0c, 0xfb, 0x07, 0xc3, 0xaf, 0x4d, 0xc9, 0xd5, 0xeb, 0x0d, 0x4e, - 0x50, 0x33, 0xba, 0xe4, 0x1a, 0xf4, 0xde, 0x1e, 0x0c, 0x07, 0x7d, 0xbb, 0x8c, 0x50, 0xaf, 0x3b, - 0xec, 0x0d, 0xde, 0x0e, 0xfa, 0x76, 0xc5, 0xf9, 0x77, 0x4b, 0x77, 0xe4, 0xc5, 0x92, 0xb7, 0xcf, - 0xbd, 0x40, 0xac, 0xff, 0x2d, 0xe6, 0x19, 0x34, 0xcc, 0x7b, 0x1e, 0xa4, 0x96, 0x36, 0x47, 0x90, - 0x3f, 0x84, 0x2d, 0xdf, 0xec, 0x77, 0x0b, 0x96, 0xf7, 0xc9, 0xe2, 0x6c, 0x63, 0xd5, 0x91, 0x7b, - 0xe9, 0x87, 0x79, 0x9e, 0xb6, 0x5f, 0x80, 0x9d, 0x8f, 0xa0, 0x5d, 0xa4, 0x28, 0x5c, 0xf6, 0x9d, - 0xc2, 0x65, 0x2d, 0xe7, 0x5f, 0x4a, 0xb0, 0xb5, 0xf0, 0xbf, 0x0c, 0xeb, 0x73, 0xfe, 0xe2, 0x70, - 0xb8, 0xb4, 0x34, 0x1c, 0x26, 0x1f, 0x01, 0xc9, 0x93, 0xb8, 0xf9, 0x29, 0x9b, 0x9d, 0x23, 0xd4, - 0xb1, 0x2a, 0x5f, 0x44, 0x54, 0x1e, 0x52, 0x44, 0x90, 0xcf, 0xa1, 0x25, 0x62, 0x2f, 0x60, 0xa1, - 0x1b, 0x06, 0xd1, 0x75, 0xfa, 0x0f, 0x24, 0x0b, 0xff, 0x96, 0x70, 0xaa, 0x28, 0xde, 0x22, 0x01, - 0x6d, 0x8a, 0x39, 0x40, 0x7e, 0x0f, 0x76, 0x78, 0x24, 0xdc, 0xb4, 0x90, 0x74, 0xfd, 0xec, 0x5f, - 0x46, 0xca, 0xcb, 0xb3, 0xcf, 0xa5, 0x4a, 0x95, 0x12, 0xbe, 0x88, 0x12, 0x8e, 0x00, 0xa0, 0xec, - 0x36, 0xed, 0x67, 0x73, 0xd5, 0x9e, 0x55, 0xac, 0xf6, 0x0e, 0xa1, 0x69, 0x1a, 0x61, 0x6c, 0xc8, - 0xd4, 0x13, 0xb6, 0xf7, 0x7f, 0x65, 0x7e, 0x62, 0x77, 0xfe, 0x2f, 0x46, 0x47, 0xe6, 0x3f, 0x8c, - 0x0c, 0xd3, 0x3d, 0xd5, 0xf9, 0xe7, 0x77, 0x3b, 0x7f, 0x6b, 0x41, 0x1b, 0x45, 0xcc, 0x9d, 0xfc, - 0xdb, 0xd0, 0x4c, 0x32, 0x28, 0x1d, 0x8e, 0xec, 0xe4, 0x06, 0x8a, 0xd9, 0x22, 0xcd, 0x13, 0x92, - 0x7d, 0xd8, 0x11, 0xd3, 0x8b, 0x74, 0xaa, 0xf8, 0x8d, 0x88, 0xa3, 0xd7, 0x33, 0xc9, 0xd3, 0xe2, - 0x6b, 0xe5, 0x1a, 0xf9, 0x08, 0xb6, 0xd3, 0x29, 0xf0, 0x7c, 0x83, 0x1e, 0x8d, 0x2f, 0x2f, 0x38, - 0xbf, 0xb4, 0xb2, 0x42, 0x06, 0xf3, 0xa8, 0x6a, 0x42, 0x32, 0x13, 0xc3, 0xcf, 0x95, 0x99, 0xf2, - 0x3d, 0xa8, 0x9a, 0xdf, 0x93, 0x74, 0x16, 0x30, 0x50, 0xde, 0x48, 0x2b, 0x05, 0x23, 0x7d, 0x06, - 0x0d, 0x93, 0x79, 0x39, 0x9a, 0x45, 0x19, 0x8b, 0xc0, 0x0c, 0x31, 0xf7, 0xd7, 0x6a, 0xbe, 0xf8, - 0xfd, 0xe7, 0x12, 0x6c, 0xe7, 0x44, 0xc3, 0x6e, 0x3e, 0x8e, 0xc8, 0xa7, 0x50, 0x65, 0xea, 0x4b, - 0xc9, 0xd8, 0xde, 0x77, 0x56, 0x16, 0x06, 0x9a, 0x78, 0x4f, 0xff, 0xa1, 0x66, 0x07, 0xf9, 0x21, - 0x6c, 0xc6, 0xa1, 0x6f, 0x48, 0xce, 0xb3, 0x7c, 0x53, 0x44, 0x9a, 0x6a, 0x05, 0x21, 0x33, 0x1e, - 0x5d, 0x53, 0x7b, 0xa4, 0x54, 0x98, 0x7f, 0xab, 0x46, 0xba, 0x6d, 0xd8, 0x3c, 0x1c, 0xfc, 0xb4, - 0xd7, 0xa5, 0x7d, 0xb7, 0xdb, 0xef, 0x2b, 0xd7, 0x26, 0xd0, 0xee, 0xf6, 0x7a, 0xc7, 0xe7, 0xc3, - 0xb3, 0x53, 0x83, 0xb3, 0xb0, 0x95, 0x4e, 0xc9, 0xfa, 0x83, 0xb7, 0x03, 0x1d, 0xf0, 0x76, 0xc0, - 0xce, 0x08, 0xe9, 0xe0, 0xe8, 0xf8, 0x5b, 0x15, 0xf8, 0x00, 0xaa, 0x6f, 0x8f, 0x7b, 0x87, 0x18, - 0xf6, 0x30, 0x4a, 0x9c, 0x0f, 0x0d, 0xb4, 0x41, 0xb6, 0xa0, 0x79, 0x7e, 0xd0, 0x77, 0xcf, 0x4f, - 0xfa, 0x5d, 0x64, 0x50, 0x25, 0x36, 0xb4, 0x86, 0xdd, 0xa3, 0x81, 0xdb, 0x7b, 0xd3, 0x1d, 0x7e, - 0x3d, 0xe8, 0xdb, 0x35, 0xe7, 0x8f, 0x74, 0xfa, 0xcd, 0xb9, 0x1c, 0xf9, 0xf1, 0x82, 0x8f, 0x2e, - 0xd9, 0xe2, 0x9c, 0xb8, 0xe8, 0x9e, 0x99, 0x92, 0x4a, 0x39, 0x25, 0xbd, 0xde, 0xfc, 0x83, 0xe6, - 0xde, 0xc7, 0x9f, 0xa5, 0x9b, 0x2f, 0xaa, 0xea, 0xeb, 0x93, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, - 0x69, 0x10, 0xa1, 0xb7, 0xd8, 0x27, 0x00, 0x00, + 0x56, 0xa3, 0x0f, 0xeb, 0xe3, 0x49, 0x96, 0xcb, 0x69, 0xcf, 0x58, 0xed, 0xf6, 0x6c, 0x77, 0x57, + 0xef, 0xc4, 0x36, 0xc4, 0xe0, 0x01, 0x0f, 0xb0, 0xec, 0xf4, 0x4c, 0x0c, 0x6a, 0x49, 0xd3, 0xed, + 0x76, 0x5b, 0x36, 0x69, 0x7b, 0x86, 0x25, 0x88, 0x28, 0xd2, 0x55, 0xd9, 0x56, 0xad, 0x4b, 0x55, + 0xa2, 0x32, 0x65, 0xa3, 0x3d, 0x10, 0x40, 0x04, 0x67, 0x22, 0xb8, 0x2c, 0xc7, 0x39, 0x73, 0x24, + 0x82, 0x03, 0x11, 0x1c, 0x38, 0x11, 0xfb, 0x1f, 0xe0, 0xca, 0x85, 0xe0, 0xc2, 0x8d, 0x03, 0x07, + 0xe2, 0x65, 0x66, 0x95, 0xaa, 0xf4, 0x61, 0xec, 0xe0, 0xc4, 0xc9, 0xf5, 0x5e, 0xbe, 0x7c, 0xf9, + 0x32, 0xdf, 0xf7, 0xb3, 0x60, 0x7d, 0xcc, 0xfc, 0xd8, 0x0f, 0xaf, 0xf6, 0xc7, 0x71, 0x24, 0x23, + 0x52, 0x53, 0x7f, 0x2e, 0x27, 0xef, 0x77, 0xb7, 0xdc, 0x21, 0x93, 0x8e, 0xef, 0xf1, 0x50, 0xfa, + 0x72, 0xaa, 0x97, 0x77, 0xb7, 0xc4, 0x34, 0x74, 0x1d, 0xc1, 0xa5, 0xf4, 0xc3, 0x2b, 0x61, 0x90, + 0x36, 0x1b, 0x8f, 0x03, 0xdf, 0x65, 0xd2, 0x8f, 0x42, 0x67, 0xc4, 0x25, 0xf3, 0x98, 0x64, 0xce, + 0x88, 0x0b, 0xc1, 0xae, 0xb8, 0xa1, 0xd9, 0x74, 0xa3, 0xd1, 0x68, 0x12, 0xfa, 0xd2, 0xe7, 0x66, + 0x9b, 0xcd, 0xe0, 0xf1, 0x37, 0x5c, 0xba, 0x43, 0x3f, 0xbc, 0x7a, 0xc5, 0xdc, 0x6b, 0xee, 0x5d, + 0x8c, 0x7b, 0x4c, 0xb2, 0x1e, 0x97, 0xcc, 0x0f, 0x04, 0x79, 0x02, 0x0d, 0xc5, 0x27, 0x9c, 0x8c, + 0x2e, 0x79, 0xdc, 0x2e, 0x3c, 0x2d, 0xbc, 0x58, 0xa7, 0x80, 0xa8, 0x81, 0xc2, 0x90, 0x67, 0xd0, + 0x94, 0x91, 0x64, 0x41, 0x42, 0x51, 0x54, 0x14, 0x0d, 0x85, 0xd3, 0x24, 0xf6, 0x7f, 0x57, 0xa0, + 0x82, 0xbc, 0x27, 0x63, 0xb2, 0x0d, 0x6b, 0x6e, 0x10, 0xb9, 0xd7, 0x8a, 0x51, 0x99, 0x6a, 0x80, + 0xb4, 0xa0, 0xe8, 0x7b, 0x6a, 0x67, 0x9d, 0x16, 0x7d, 0x8f, 0x7c, 0x0d, 0x35, 0x37, 0x0a, 0x25, + 0x73, 0xa5, 0x68, 0x97, 0x9e, 0x96, 0x5e, 0x34, 0x0e, 0x9e, 0xef, 0x27, 0x2f, 0xb2, 0x7f, 0x36, + 0x0d, 0xdd, 0xc3, 0x50, 0x48, 0x16, 0x04, 0xea, 0xae, 0x5d, 0x4d, 0xf9, 0xed, 0x01, 0x4d, 0x37, + 0x91, 0x9f, 0x40, 0x23, 0x73, 0xd3, 0x76, 0x59, 0xf1, 0xd8, 0xc9, 0xf3, 0xe8, 0x1a, 0x82, 0x29, + 0xcd, 0xd2, 0x92, 0x13, 0xd8, 0x48, 0xd8, 0x98, 0x37, 0x68, 0xaf, 0x3d, 0x2d, 0xbc, 0x68, 0x1c, + 0x7c, 0x32, 0xdb, 0x7e, 0xc7, 0x83, 0xd1, 0xf9, 0xdd, 0xe4, 0x02, 0x48, 0x86, 0x7f, 0xc2, 0xb3, + 0xf2, 0x10, 0x9e, 0x4b, 0x18, 0x90, 0xcf, 0xa1, 0x3a, 0x8e, 0xa3, 0xf7, 0x7e, 0xc0, 0xdb, 0x55, + 0xc5, 0xeb, 0xd1, 0x8c, 0x57, 0xc2, 0xe3, 0x54, 0x13, 0xd0, 0x84, 0x92, 0x1c, 0x43, 0xcb, 0x7c, + 0x26, 0x72, 0xd4, 0x1e, 0x22, 0xc7, 0xdc, 0x66, 0xf2, 0x19, 0x54, 0x8d, 0x11, 0xb6, 0xeb, 0x8a, + 0xcf, 0x87, 0xf9, 0x27, 0x3e, 0xd3, 0x8b, 0x34, 0xa1, 0xc2, 0xc7, 0x4d, 0xac, 0x36, 0x11, 0x00, + 0x1e, 0xf4, 0xb8, 0x73, 0xbb, 0x51, 0x82, 0x6b, 0x3e, 0x45, 0xe7, 0x69, 0x37, 0x96, 0x49, 0x70, + 0xa4, 0x17, 0x69, 0x42, 0x85, 0x2f, 0x60, 0x3e, 0x13, 0x01, 0x9a, 0x0f, 0x7a, 0x81, 0xfc, 0x66, + 0xd2, 0x01, 0xeb, 0x96, 0x49, 0x77, 0x78, 0x12, 0x06, 0xd3, 0x8e, 0xeb, 0x46, 0x93, 0x50, 0xb6, + 0xd7, 0x97, 0x09, 0x62, 0x16, 0xe9, 0x02, 0x39, 0x71, 0x60, 0x67, 0x1e, 0x97, 0x88, 0xd6, 0x7a, + 0x88, 0x68, 0xab, 0xb8, 0xd8, 0xff, 0x51, 0x86, 0xe6, 0xf1, 0x24, 0x90, 0x7e, 0x72, 0x22, 0x81, + 0x72, 0xc8, 0x46, 0x5c, 0xf9, 0x60, 0x9d, 0xaa, 0x6f, 0xb2, 0x07, 0x75, 0xe9, 0x8f, 0xb8, 0x90, + 0x6c, 0x34, 0x56, 0x9e, 0x58, 0xa2, 0x33, 0x04, 0xae, 0xea, 0x10, 0xe4, 0x46, 0x61, 0xbb, 0xa4, + 0xb6, 0xcd, 0x10, 0xe4, 0x6b, 0x00, 0x37, 0x0a, 0xa2, 0xd8, 0x19, 0x32, 0x31, 0x34, 0xce, 0xf6, + 0x74, 0x26, 0x74, 0xf6, 0xec, 0xfd, 0x2e, 0x12, 0xbe, 0x61, 0x62, 0x48, 0xeb, 0x6e, 0xf2, 0x49, + 0x1e, 0xa1, 0xbf, 0x23, 0x03, 0xdf, 0x53, 0xce, 0x56, 0xa2, 0x55, 0x05, 0x1f, 0x7a, 0xe4, 0x47, + 0xb0, 0x71, 0xcd, 0xa7, 0x2e, 0x8b, 0x3d, 0xc7, 0x84, 0x48, 0xe5, 0x3a, 0x75, 0xa5, 0x09, 0x44, + 0x9f, 0x6a, 0x2c, 0xd9, 0x51, 0x96, 0xe0, 0x4c, 0x7c, 0x4f, 0xf9, 0x43, 0x9d, 0x56, 0xae, 0xf9, + 0xf4, 0xc2, 0xf7, 0xc8, 0x97, 0x50, 0xf1, 0x47, 0xec, 0x8a, 0xa3, 0xad, 0xa3, 0x64, 0x3f, 0x5c, + 0x21, 0xd9, 0xa1, 0x89, 0xb1, 0x87, 0x48, 0x4c, 0xcd, 0x1e, 0xf2, 0x19, 0x6c, 0xb9, 0x13, 0x21, + 0xa3, 0x91, 0xff, 0x73, 0x1d, 0x59, 0x95, 0x60, 0xca, 0xdc, 0xeb, 0x94, 0xe4, 0x96, 0xd4, 0xd5, + 0x76, 0x9f, 0x41, 0x3d, 0xbd, 0x23, 0x86, 0x3b, 0x3f, 0xf4, 0xf8, 0x9f, 0xb4, 0x0b, 0x4f, 0x4b, + 0x2f, 0x4a, 0x54, 0x03, 0xbb, 0xff, 0x52, 0x80, 0xf5, 0xdc, 0x69, 0x59, 0xe1, 0x0b, 0x39, 0xe1, + 0x13, 0x55, 0x15, 0x33, 0xaa, 0x6a, 0x43, 0x75, 0xcc, 0xa6, 0x41, 0xc4, 0x3c, 0xa5, 0x8a, 0x26, + 0x4d, 0x40, 0x3c, 0xee, 0xd6, 0xf7, 0x24, 0xea, 0x00, 0x1f, 0x51, 0x03, 0xe4, 0x23, 0xa8, 0x0c, + 0xb9, 0x7f, 0x35, 0x94, 0xe6, 0x6d, 0x0d, 0x44, 0x76, 0xa1, 0x86, 0xce, 0x2c, 0xfc, 0x9f, 0x73, + 0xf5, 0xa6, 0x25, 0x9a, 0xc2, 0xe4, 0x39, 0xac, 0xc7, 0xea, 0xcb, 0x91, 0x2c, 0xbe, 0xe2, 0x52, + 0xbd, 0x69, 0x89, 0x36, 0x35, 0xf2, 0x5c, 0xe1, 0x66, 0xc1, 0xbc, 0x96, 0x09, 0xe6, 0xf6, 0x2f, + 0x8a, 0xb0, 0xf5, 0x2e, 0x72, 0x59, 0x60, 0x34, 0x73, 0x6a, 0x84, 0xfb, 0x2d, 0x28, 0x5f, 0xf3, + 0xa9, 0x50, 0x4f, 0xd1, 0x38, 0x78, 0x36, 0xd3, 0xc2, 0x12, 0xe2, 0xfd, 0x23, 0x3e, 0xa5, 0x8a, + 0x9c, 0x7c, 0x01, 0xcd, 0x11, 0xaa, 0x89, 0x19, 0xef, 0x2a, 0x2a, 0x9f, 0xf8, 0x68, 0xb9, 0x12, + 0x69, 0x8e, 0x16, 0x6f, 0x38, 0x66, 0x42, 0xdc, 0x46, 0xb1, 0x67, 0xac, 0x36, 0x85, 0xf1, 0x15, + 0x31, 0xb5, 0x1e, 0xf1, 0xa9, 0x7a, 0xad, 0x3a, 0x4d, 0x40, 0xf2, 0x22, 0x35, 0x39, 0x23, 0x94, + 0xce, 0x00, 0x75, 0x3a, 0x8f, 0xde, 0xfd, 0x35, 0x28, 0xe1, 0x86, 0x65, 0xfe, 0x44, 0xa0, 0x8c, + 0x49, 0x52, 0x89, 0xdb, 0xa4, 0xea, 0xdb, 0xfe, 0x87, 0x02, 0x7c, 0x98, 0xbb, 0x2c, 0xe7, 0xf1, + 0x1b, 0x1e, 0x04, 0x11, 0x5a, 0xb9, 0xb1, 0x6e, 0xe7, 0x86, 0xc7, 0xc2, 0x8f, 0x42, 0xc5, 0x6c, + 0x8d, 0xb6, 0x0c, 0xfa, 0x5b, 0x8d, 0x45, 0x43, 0x19, 0x73, 0xae, 0x1c, 0x45, 0x73, 0xae, 0x20, + 0x78, 0xe8, 0xa9, 0x3c, 0xcd, 0x6f, 0x7c, 0x97, 0x3b, 0x4a, 0x14, 0x7d, 0x5b, 0xd0, 0xa8, 0x01, + 0x0a, 0x34, 0x23, 0x90, 0xd3, 0x31, 0x37, 0x77, 0x36, 0x04, 0xe7, 0xd3, 0xb1, 0x8a, 0x00, 0xc2, + 0xbf, 0x0a, 0x99, 0x9c, 0xc4, 0x5c, 0x5d, 0xb8, 0x49, 0x67, 0x08, 0xfb, 0xfb, 0x02, 0x58, 0x28, + 0x76, 0x36, 0xf3, 0xae, 0xc8, 0xe6, 0x3f, 0x82, 0x0d, 0x3f, 0x43, 0xe5, 0xa4, 0xa9, 0xbd, 0x95, + 0x45, 0xe7, 0x64, 0x56, 0x22, 0x95, 0x16, 0x44, 0x4a, 0x1e, 0xb6, 0x9c, 0xb7, 0xfe, 0xe4, 0x89, + 0xd6, 0x54, 0xa9, 0x91, 0x80, 0xf6, 0xbf, 0x17, 0x60, 0x67, 0x45, 0x71, 0x70, 0xcf, 0xba, 0xe3, + 0x39, 0xac, 0x9b, 0x0c, 0xe7, 0x28, 0xf7, 0x37, 0x22, 0x35, 0x0d, 0x52, 0xfb, 0xea, 0x23, 0xa8, + 0xf1, 0x50, 0x38, 0x19, 0xc1, 0xaa, 0x3c, 0x14, 0xea, 0x8d, 0x9f, 0x41, 0x33, 0x60, 0x42, 0x3a, + 0x93, 0xb1, 0xc7, 0x24, 0xd7, 0xb1, 0xac, 0x4c, 0x1b, 0x88, 0xbb, 0xd0, 0x28, 0xbc, 0xb3, 0x98, + 0x0a, 0xc9, 0x47, 0x8e, 0x64, 0x57, 0x58, 0x06, 0x94, 0xf0, 0xce, 0x1a, 0x75, 0xce, 0xae, 0x04, + 0xf9, 0x04, 0x5a, 0x01, 0xda, 0x88, 0x13, 0xfa, 0xee, 0xb5, 0x3a, 0x44, 0x87, 0xb3, 0x75, 0x85, + 0x1d, 0x18, 0xa4, 0xfd, 0xe7, 0x15, 0x78, 0xb4, 0xb2, 0x12, 0x22, 0xbf, 0x0e, 0xdb, 0x59, 0x41, + 0x1c, 0xb5, 0x37, 0x98, 0x9a, 0xdb, 0x93, 0x8c, 0x40, 0xef, 0xf4, 0xca, 0xff, 0xe3, 0xa7, 0x40, + 0xdd, 0x32, 0xcf, 0xe3, 0x9e, 0x0a, 0xca, 0x35, 0xaa, 0x01, 0xb4, 0x93, 0x4b, 0x54, 0x32, 0xf7, + 0x54, 0x89, 0x51, 0xa3, 0x09, 0x88, 0xf4, 0xa3, 0x09, 0xca, 0xd4, 0xd0, 0xf4, 0x0a, 0x40, 0xfa, + 0x98, 0x8f, 0xa2, 0x1b, 0xee, 0xa9, 0x8a, 0xa0, 0x46, 0x13, 0x90, 0x3c, 0x85, 0xe6, 0x90, 0x09, + 0x47, 0xb1, 0x75, 0x26, 0x42, 0xe5, 0xf7, 0x1a, 0x85, 0x21, 0x13, 0x1d, 0x44, 0x5d, 0xa8, 0x24, + 0x71, 0xc3, 0x63, 0xff, 0x7d, 0x52, 0x7d, 0x0b, 0xc9, 0xe4, 0x44, 0xa7, 0xef, 0x12, 0x25, 0xd9, + 0xa5, 0x33, 0xb5, 0xa2, 0x8a, 0xe6, 0x78, 0x22, 0x64, 0x42, 0xb9, 0xa1, 0x28, 0x1b, 0x0a, 0x67, + 0x48, 0xbe, 0x82, 0xc7, 0xa6, 0x92, 0x74, 0x62, 0xfe, 0xc7, 0x13, 0x2e, 0xa4, 0xd6, 0xa2, 0xda, + 0xc2, 0xdb, 0x96, 0xda, 0xd1, 0x36, 0x24, 0x54, 0x53, 0x28, 0x65, 0xe2, 0x7e, 0xbe, 0x7a, 0xbb, + 0x76, 0x83, 0xcd, 0x95, 0xdb, 0xbb, 0xca, 0x33, 0xbe, 0x86, 0xbd, 0xf9, 0xed, 0xf8, 0x1c, 0x92, + 0x9b, 0xe3, 0x89, 0xda, 0xff, 0x28, 0xbf, 0x9f, 0x2a, 0x0a, 0x7d, 0xfe, 0x6a, 0x06, 0x5a, 0x80, + 0xad, 0xd5, 0x0c, 0xb4, 0x04, 0xcf, 0xa0, 0xe9, 0xf9, 0x62, 0x1c, 0xb0, 0xa9, 0xb6, 0xaf, 0x6d, + 0xa5, 0xfa, 0x86, 0xc1, 0xa1, 0x8d, 0xd9, 0xb7, 0x8b, 0xfe, 0x9e, 0x94, 0x38, 0xcb, 0xfd, 0x7d, + 0xc1, 0xa8, 0x8b, 0x4b, 0x8c, 0x7a, 0xde, 0x72, 0x4b, 0x0b, 0x96, 0x6b, 0xbf, 0x82, 0xdd, 0xf9, + 0x83, 0x4f, 0x27, 0x97, 0x81, 0xef, 0x76, 0x87, 0xec, 0x9e, 0xb1, 0xc6, 0xfe, 0xfb, 0x12, 0xac, + 0xe7, 0xda, 0x90, 0xff, 0x75, 0x5f, 0x53, 0x39, 0xe6, 0x13, 0x68, 0x8c, 0x63, 0xff, 0x86, 0x49, + 0xee, 0x5c, 0xf3, 0xa9, 0xa9, 0x00, 0xc0, 0xa0, 0x30, 0x1b, 0x3d, 0xc5, 0xa8, 0x2a, 0xdc, 0xd8, + 0x1f, 0xa3, 0x5c, 0xca, 0x2f, 0x9b, 0x34, 0x8b, 0xc2, 0x82, 0xe0, 0x67, 0x91, 0x1f, 0x1a, 0xaf, + 0xac, 0x51, 0x03, 0x61, 0xba, 0xd4, 0xb6, 0xca, 0x3d, 0x55, 0x10, 0xd4, 0x68, 0x0a, 0xcf, 0x9c, + 0xa6, 0x9a, 0x75, 0x9a, 0x13, 0xb0, 0x8c, 0x76, 0x85, 0x23, 0x23, 0x07, 0xf9, 0x98, 0x2a, 0xeb, + 0x93, 0x55, 0xcd, 0x96, 0x21, 0x3f, 0x8f, 0xde, 0x46, 0x7e, 0x48, 0x5b, 0x71, 0x0e, 0x26, 0x2f, + 0xa1, 0x96, 0x94, 0xf8, 0xa6, 0xa5, 0x78, 0xb2, 0x82, 0x91, 0xe9, 0x2d, 0x04, 0x4d, 0x37, 0x60, + 0x06, 0xe3, 0xa1, 0x1b, 0x4f, 0xc7, 0x32, 0x75, 0xfa, 0x19, 0x42, 0xe5, 0xb7, 0x31, 0x77, 0x25, + 0x9b, 0xb9, 0xfe, 0x0c, 0x81, 0x49, 0xcb, 0x90, 0xa2, 0x03, 0xab, 0x42, 0xa5, 0xa9, 0x5e, 0xae, + 0x35, 0x43, 0x1f, 0xf1, 0xa9, 0xc0, 0xf2, 0xe6, 0xf1, 0x1d, 0x37, 0x32, 0xfa, 0x2a, 0xa4, 0xfa, + 0xfa, 0x18, 0x60, 0xac, 0x6c, 0x43, 0xa9, 0x4b, 0xeb, 0xbf, 0xae, 0x31, 0xa8, 0xad, 0x54, 0xe9, + 0xa5, 0xac, 0xd2, 0xef, 0x08, 0xac, 0x3b, 0xba, 0x6e, 0x49, 0x4a, 0xe5, 0x3a, 0xad, 0x20, 0x78, + 0xe8, 0xa1, 0xdd, 0x26, 0x6d, 0xe2, 0x14, 0x57, 0x2b, 0x5a, 0xf1, 0x29, 0xee, 0x50, 0x29, 0x51, + 0xbb, 0x6f, 0x55, 0x1f, 0xa6, 0x00, 0xf2, 0x0d, 0x6c, 0xc6, 0xfc, 0x86, 0xb3, 0x80, 0x7b, 0x8e, + 0xa9, 0x9c, 0x92, 0x5a, 0x39, 0xd3, 0x53, 0x52, 0x43, 0x92, 0x36, 0x32, 0x71, 0x1e, 0x21, 0xec, + 0xbf, 0x2e, 0x82, 0x35, 0xef, 0x16, 0xe4, 0xab, 0x4c, 0x2b, 0xbf, 0x50, 0xf9, 0xad, 0x48, 0x60, + 0x99, 0x46, 0xfe, 0x35, 0x34, 0xcd, 0xeb, 0xe1, 0x2d, 0x45, 0xbb, 0x38, 0x5f, 0xc2, 0xaf, 0xf6, + 0x43, 0xda, 0x18, 0xa7, 0xdf, 0x82, 0xbc, 0x84, 0x6a, 0x52, 0x41, 0x96, 0x94, 0x5d, 0xdd, 0x21, + 0x46, 0x72, 0xc5, 0x64, 0xc7, 0xff, 0x61, 0x9c, 0x60, 0xff, 0x18, 0x36, 0xd4, 0x2a, 0x0a, 0x64, + 0xf2, 0xc9, 0xfd, 0xe2, 0xc3, 0x97, 0xb0, 0x9d, 0x6c, 0x3c, 0xd6, 0x33, 0x1c, 0x41, 0x39, 0xbb, + 0xef, 0xee, 0xdf, 0x85, 0x8f, 0x74, 0xd7, 0x29, 0xfd, 0x1b, 0x5f, 0x4e, 0xbb, 0x3c, 0x94, 0x3c, + 0xbe, 0x63, 0xbf, 0x05, 0x25, 0xdf, 0xd3, 0xcf, 0xdb, 0xa4, 0xf8, 0x69, 0xf7, 0x74, 0x8c, 0xcb, + 0x73, 0xe8, 0xb8, 0x2e, 0x57, 0xce, 0x74, 0x5f, 0x2e, 0x7d, 0xed, 0x2c, 0x79, 0x2e, 0x3d, 0x5f, + 0x8c, 0x7c, 0x21, 0x1e, 0xc0, 0xc6, 0x81, 0xe7, 0x8b, 0x6c, 0x06, 0x91, 0xcc, 0xe5, 0x55, 0x8e, + 0xbe, 0x96, 0x54, 0x3c, 0x4c, 0x1a, 0x9e, 0x75, 0x83, 0xe9, 0x48, 0xf4, 0x2a, 0x4c, 0xe4, 0x82, + 0xf3, 0x50, 0x3d, 0x55, 0x8d, 0x56, 0x87, 0x4c, 0x9c, 0x71, 0x1e, 0xda, 0x7f, 0x55, 0x80, 0x27, + 0x77, 0x9f, 0x20, 0x48, 0x00, 0x1f, 0x33, 0xb3, 0xec, 0xb8, 0x6a, 0xdd, 0x09, 0xb3, 0x04, 0xc6, + 0xbe, 0x5f, 0xcc, 0x37, 0xfe, 0xab, 0x38, 0xd2, 0xc7, 0x6c, 0xf5, 0x69, 0xf6, 0x3f, 0xd6, 0xe1, + 0x07, 0x77, 0xef, 0x5f, 0x08, 0x35, 0x0b, 0x3d, 0x7c, 0x39, 0xdb, 0xc3, 0xbf, 0x87, 0xcd, 0xac, + 0xb8, 0xb3, 0x9a, 0xbb, 0x75, 0xf0, 0x93, 0xfb, 0x8a, 0xbc, 0x9f, 0x05, 0xb0, 0x44, 0xa7, 0x56, + 0x38, 0x87, 0xc9, 0x06, 0xa8, 0x72, 0x2e, 0x40, 0x11, 0x28, 0xc7, 0x9c, 0x25, 0x49, 0x47, 0x7d, + 0xa3, 0xc8, 0x5e, 0x62, 0x0d, 0x26, 0xe7, 0xcc, 0x10, 0x98, 0x90, 0x98, 0xb1, 0x38, 0x93, 0x77, + 0x52, 0x18, 0xeb, 0x35, 0x33, 0xdb, 0x54, 0xed, 0x67, 0x93, 0x26, 0x20, 0xa6, 0x37, 0x36, 0x91, + 0xc3, 0xb4, 0x4b, 0x37, 0x90, 0xee, 0x69, 0xc7, 0xc1, 0x34, 0x99, 0x89, 0xaa, 0x14, 0xd1, 0xc4, + 0x9e, 0x76, 0x1c, 0x4c, 0x8d, 0x8f, 0x2d, 0x44, 0xd1, 0x86, 0x2e, 0x3b, 0xb2, 0x51, 0xf4, 0x3d, + 0x6c, 0x8e, 0xf8, 0xe8, 0x92, 0xc7, 0x62, 0xe8, 0x8f, 0x93, 0x0a, 0xae, 0xf9, 0xc0, 0x87, 0x3c, + 0x4e, 0x39, 0xe8, 0x7a, 0x8f, 0x5a, 0xa3, 0x39, 0x0c, 0xf9, 0x8b, 0xc2, 0xac, 0x86, 0x5b, 0x56, + 0x5e, 0xae, 0xab, 0x23, 0x5f, 0xdd, 0xfb, 0xc8, 0xa4, 0x3d, 0x58, 0x28, 0x47, 0xd3, 0x32, 0x6c, + 0x71, 0x09, 0x9f, 0xd9, 0xe3, 0x01, 0x47, 0x0d, 0xb4, 0xb4, 0xcb, 0x18, 0x70, 0xce, 0xd9, 0x36, + 0xe6, 0x9c, 0xcd, 0xfe, 0xcf, 0x02, 0x58, 0xf3, 0xd6, 0x42, 0x00, 0x2a, 0x83, 0x08, 0xbf, 0xac, + 0x0f, 0xc8, 0x06, 0x34, 0x06, 0xfc, 0xf6, 0x24, 0xe4, 0xe7, 0xd1, 0x49, 0xc8, 0xad, 0x02, 0xd9, + 0x81, 0xad, 0x01, 0xbf, 0x3d, 0xd5, 0x95, 0xcc, 0xeb, 0x38, 0x9a, 0x8c, 0x31, 0xf8, 0x59, 0x45, + 0xd2, 0x80, 0xea, 0x31, 0x0f, 0x91, 0x89, 0x55, 0x22, 0x75, 0x58, 0xa3, 0xa8, 0x30, 0xab, 0x4c, + 0x08, 0xb4, 0xba, 0xb9, 0xfa, 0xd1, 0x5a, 0x43, 0x26, 0x69, 0x24, 0x3e, 0x0c, 0x6f, 0x7c, 0xa9, + 0x0e, 0xb7, 0x2a, 0x64, 0x1b, 0xac, 0xf9, 0x94, 0x6d, 0x55, 0xc9, 0x0f, 0x60, 0x37, 0xc5, 0xce, + 0x54, 0x92, 0xac, 0xd7, 0xc8, 0x16, 0x6c, 0xa4, 0xeb, 0x47, 0x3e, 0xb6, 0x0f, 0x56, 0x5d, 0x9f, + 0xb1, 0xf0, 0x60, 0x16, 0xd8, 0x7f, 0x59, 0x00, 0x6b, 0x5e, 0xb1, 0xa4, 0x0d, 0xdb, 0xf3, 0xb8, + 0x43, 0x2f, 0xc0, 0x17, 0x78, 0x0c, 0x3b, 0xf3, 0x2b, 0xa7, 0x3c, 0xf4, 0xfc, 0xf0, 0xca, 0x2a, + 0x90, 0x3d, 0x68, 0xcf, 0x2f, 0x26, 0xd1, 0xd7, 0x2a, 0x2e, 0x5b, 0xed, 0x71, 0x37, 0xc0, 0x32, + 0xce, 0x2a, 0xd9, 0x7f, 0x56, 0x80, 0x47, 0x2b, 0xb5, 0x8d, 0xcf, 0x79, 0x11, 0x5e, 0x87, 0xd1, + 0x6d, 0x68, 0x7d, 0x80, 0xc0, 0xec, 0xcc, 0x26, 0xd4, 0x32, 0x67, 0x34, 0xa1, 0x36, 0xe3, 0x49, + 0xd6, 0xa1, 0xde, 0x65, 0xa1, 0xcb, 0x83, 0x80, 0x7b, 0x56, 0x19, 0xf7, 0x9d, 0x63, 0xb7, 0xc2, + 0x3d, 0x6b, 0x8d, 0x6c, 0xc2, 0xfa, 0x45, 0xa8, 0xc0, 0xef, 0xa2, 0x58, 0x0e, 0xa7, 0x56, 0xc5, + 0xfe, 0xbe, 0x00, 0x4d, 0xb4, 0xc7, 0x57, 0x51, 0x74, 0x3d, 0x62, 0xf1, 0xf5, 0xea, 0x50, 0x3f, + 0x89, 0x03, 0x93, 0xb8, 0xf0, 0x33, 0xed, 0xf9, 0x4b, 0x99, 0x9e, 0xff, 0x31, 0xd4, 0x55, 0xbd, + 0xee, 0x20, 0xad, 0x0e, 0x2a, 0x35, 0x85, 0xb8, 0x88, 0x83, 0x6c, 0xe3, 0xb6, 0x96, 0x6f, 0xdc, + 0x3e, 0x06, 0x30, 0xc6, 0x8a, 0x16, 0x5a, 0xd1, 0x16, 0x6a, 0x30, 0x1d, 0x69, 0xff, 0x29, 0x7c, + 0x88, 0x12, 0xf6, 0x43, 0x71, 0x21, 0x78, 0x8c, 0x07, 0xe9, 0x89, 0xe9, 0x0a, 0x51, 0x77, 0xa1, + 0x36, 0x31, 0x74, 0x46, 0xde, 0x14, 0x56, 0x03, 0xcc, 0x21, 0xf3, 0xd5, 0xac, 0x43, 0x17, 0x72, + 0x55, 0x05, 0x1f, 0xe6, 0xfa, 0xca, 0x72, 0x4e, 0x3c, 0xfb, 0xad, 0x2e, 0x97, 0xba, 0x01, 0x67, + 0xf1, 0x1b, 0x5f, 0xc8, 0x28, 0x9e, 0x66, 0x83, 0x67, 0x21, 0x17, 0x3c, 0x3f, 0x06, 0x70, 0x91, + 0x50, 0xdf, 0xc5, 0x04, 0x77, 0x83, 0xe9, 0x48, 0xfb, 0x97, 0x05, 0x20, 0xc8, 0xcc, 0x4c, 0xfc, + 0x4f, 0x7d, 0x57, 0x4e, 0x62, 0xbe, 0x74, 0x32, 0x95, 0x19, 0x1f, 0x16, 0x57, 0x8c, 0x0f, 0x4b, + 0x6a, 0xb0, 0xb2, 0x30, 0x3e, 0x2c, 0x2b, 0x74, 0x32, 0x3e, 0x7c, 0x0c, 0x75, 0xd5, 0x49, 0xa9, + 0xf9, 0xa1, 0x1e, 0xc5, 0xa8, 0xf9, 0xe1, 0xd9, 0xd2, 0xf9, 0x61, 0x45, 0x11, 0xac, 0x98, 0x1f, + 0x56, 0xb3, 0xf3, 0xc3, 0x21, 0x6c, 0x2d, 0xde, 0x44, 0xac, 0x1e, 0x91, 0xfe, 0x0e, 0xd4, 0xc6, + 0x86, 0xc8, 0x94, 0x87, 0x7b, 0xf9, 0x90, 0x98, 0xe7, 0x44, 0x53, 0x6a, 0xfb, 0x97, 0x45, 0x68, + 0x64, 0x66, 0xf3, 0x2b, 0xf4, 0xde, 0x86, 0x2a, 0xf3, 0xbc, 0x98, 0x0b, 0x91, 0xbc, 0x97, 0x01, + 0xb3, 0x22, 0x95, 0x72, 0x22, 0xe5, 0x6b, 0x7e, 0xdd, 0x81, 0x65, 0x6a, 0x7e, 0x02, 0xe5, 0x31, + 0x93, 0x43, 0x53, 0xbf, 0xab, 0xef, 0x54, 0x53, 0x95, 0x8c, 0xa6, 0xb2, 0x63, 0xf1, 0xaa, 0x99, + 0x51, 0x9a, 0xb1, 0xf8, 0x36, 0xac, 0xf1, 0x51, 0xf4, 0x33, 0x5f, 0xe5, 0xbe, 0x3a, 0xd5, 0x00, + 0xaa, 0xea, 0x96, 0x05, 0x01, 0x97, 0x66, 0x14, 0x62, 0x20, 0x64, 0x8e, 0x66, 0x64, 0x7a, 0x22, + 0xf5, 0xad, 0xd4, 0xea, 0x7b, 0x1e, 0x0f, 0x4d, 0x2f, 0x64, 0xa0, 0x3b, 0xe6, 0x20, 0xbb, 0x50, + 0x1b, 0x47, 0xc2, 0x57, 0x5d, 0xe5, 0xba, 0x9e, 0x17, 0x27, 0xb0, 0xfd, 0x6f, 0xe6, 0x29, 0xcd, + 0xff, 0x5b, 0x56, 0x3c, 0x65, 0xe6, 0xc1, 0x8a, 0x4b, 0xc7, 0xdc, 0xa5, 0xfc, 0x04, 0x35, 0x33, + 0xa9, 0x54, 0xdf, 0x6a, 0x28, 0xc0, 0x63, 0xff, 0x86, 0x7b, 0xce, 0xfb, 0x38, 0x1a, 0x99, 0x17, + 0x6c, 0x18, 0xdc, 0x37, 0x71, 0x34, 0x22, 0x2f, 0x61, 0x57, 0xb7, 0xef, 0x82, 0x7b, 0x8e, 0x5a, + 0x30, 0x53, 0x48, 0x35, 0x87, 0xd7, 0x41, 0x60, 0x47, 0x35, 0xf3, 0x82, 0x7b, 0xbd, 0x74, 0xfd, + 0x10, 0x97, 0xf5, 0x48, 0x2a, 0x74, 0x13, 0xf6, 0xfa, 0xd1, 0x41, 0xa3, 0x14, 0xf7, 0xdf, 0x50, + 0x15, 0x49, 0xb6, 0x45, 0x5a, 0xf1, 0x7f, 0x9e, 0x94, 0x0c, 0xb7, 0x98, 0xb9, 0x31, 0xb6, 0xb4, + 0xa5, 0xa5, 0xff, 0xa3, 0xc2, 0x55, 0x9a, 0x92, 0x65, 0x75, 0x00, 0xf9, 0x98, 0xf1, 0x5f, 0x05, + 0x1d, 0x34, 0xce, 0xd8, 0x0d, 0xf7, 0x3a, 0xc6, 0x0e, 0x33, 0x16, 0x5a, 0xc8, 0x5b, 0xe8, 0xb2, + 0x7f, 0x1f, 0xec, 0x41, 0xfd, 0x3d, 0xbb, 0x89, 0x26, 0xb1, 0x2f, 0xf5, 0x83, 0xd7, 0xe8, 0x0c, + 0x71, 0x47, 0x34, 0x7d, 0x06, 0x4d, 0x9d, 0xdd, 0x9d, 0xac, 0xd3, 0x36, 0x34, 0x4e, 0xcf, 0x6c, + 0x7e, 0x15, 0x36, 0x75, 0x18, 0x14, 0xc3, 0x28, 0x96, 0xaa, 0x7d, 0x15, 0xc6, 0x42, 0x37, 0xd4, + 0xc2, 0x19, 0xe2, 0xb1, 0x8d, 0x15, 0x18, 0xf9, 0x79, 0x28, 0x4c, 0x89, 0x86, 0x9f, 0x68, 0x1d, + 0xbe, 0x70, 0x24, 0x17, 0x89, 0xa1, 0x56, 0x7c, 0x71, 0xce, 0x85, 0x7c, 0x5b, 0xae, 0x95, 0xad, + 0x35, 0xfb, 0x17, 0x05, 0x1d, 0xaf, 0x17, 0x26, 0x00, 0x2b, 0x8c, 0x6d, 0xbe, 0x92, 0x2b, 0x2e, + 0x56, 0x72, 0x7d, 0x78, 0x32, 0xd4, 0x81, 0xd7, 0x61, 0xb1, 0x3b, 0xf4, 0x6f, 0xb8, 0x23, 0x26, + 0xe3, 0x31, 0xca, 0xce, 0x43, 0x76, 0x19, 0x98, 0xe9, 0x4f, 0x8d, 0xee, 0x19, 0xb2, 0x8e, 0xa6, + 0x3a, 0xd3, 0x44, 0x7d, 0x4d, 0x63, 0xff, 0x5d, 0x41, 0x37, 0x79, 0x26, 0x21, 0x62, 0x36, 0xb9, + 0xe7, 0xc0, 0xf9, 0x2b, 0xa8, 0x98, 0x62, 0x4e, 0x17, 0xe2, 0x73, 0x53, 0x93, 0x0c, 0xc3, 0xfd, + 0xf3, 0xd9, 0x6c, 0x90, 0x9a, 0x4d, 0xf6, 0x17, 0xd0, 0xc8, 0xa0, 0x55, 0x62, 0x1f, 0x1c, 0x0d, + 0x4e, 0xbe, 0x1b, 0xe8, 0xc4, 0x7e, 0x4e, 0x2f, 0xce, 0xce, 0xfb, 0x3d, 0xab, 0xa0, 0x12, 0xf4, + 0x40, 0x81, 0xdf, 0x9d, 0xd0, 0xf3, 0x37, 0x3f, 0xb5, 0x8a, 0xf6, 0xf7, 0x25, 0x3d, 0x3d, 0xcb, + 0x16, 0x08, 0xa6, 0xee, 0x59, 0x21, 0x3c, 0x81, 0xb2, 0xf2, 0x0a, 0x63, 0x4c, 0xf8, 0x8d, 0x17, + 0x92, 0x91, 0x71, 0xdb, 0xa2, 0x8c, 0xd0, 0xb8, 0xdc, 0x21, 0x06, 0x9d, 0xf0, 0x2a, 0xf1, 0xdc, + 0x19, 0x02, 0x55, 0x62, 0xe6, 0x3d, 0x3a, 0x8d, 0x99, 0xa1, 0x70, 0x8a, 0xeb, 0xa8, 0x7f, 0xd9, + 0xc4, 0x5c, 0x8c, 0xa3, 0x50, 0x24, 0xb1, 0x30, 0x85, 0x31, 0xac, 0x62, 0xad, 0xee, 0xeb, 0xcd, + 0xda, 0xfe, 0xea, 0x06, 0xd3, 0x91, 0x84, 0x2f, 0x9f, 0xc2, 0xd6, 0xd4, 0xcb, 0xfe, 0x66, 0xfe, + 0x65, 0x97, 0xdc, 0x7a, 0x7f, 0x49, 0x61, 0xbc, 0x6c, 0x76, 0xab, 0x75, 0x58, 0x4f, 0x5b, 0xed, + 0xdf, 0x07, 0xb2, 0xa2, 0xc8, 0xca, 0xea, 0xe2, 0xb4, 0x3f, 0xe8, 0x1d, 0x0e, 0x5e, 0x9b, 0x22, + 0xab, 0xdb, 0xed, 0x9f, 0xa2, 0x66, 0x74, 0x91, 0xd5, 0xef, 0xbe, 0x3b, 0x1c, 0xf4, 0x7b, 0x56, + 0x09, 0xa1, 0x6e, 0x67, 0xd0, 0xed, 0xbf, 0xeb, 0xf7, 0xac, 0xb2, 0xfd, 0xaf, 0x05, 0xdd, 0x83, + 0xe7, 0x8b, 0xdc, 0x1e, 0x77, 0x7d, 0xb1, 0xfa, 0xbf, 0x2f, 0x7b, 0x50, 0x37, 0xef, 0x79, 0x98, + 0x58, 0xda, 0x0c, 0x41, 0xfe, 0x10, 0x36, 0x3c, 0xb3, 0xdf, 0xc9, 0x59, 0xde, 0xe7, 0xf3, 0xd3, + 0x8c, 0x65, 0x47, 0xee, 0x27, 0x1f, 0xe6, 0x79, 0x5a, 0x5e, 0x0e, 0xb6, 0x3f, 0x85, 0x56, 0x9e, + 0x22, 0x77, 0xd9, 0x0f, 0x72, 0x97, 0x2d, 0xd8, 0xff, 0x5c, 0x84, 0x8d, 0xb9, 0x5f, 0x2a, 0xac, + 0xce, 0xf2, 0xf3, 0xe3, 0xe0, 0xe2, 0xc2, 0x38, 0x98, 0x7c, 0x0a, 0x24, 0x4b, 0xe2, 0x64, 0xe7, + 0x6a, 0x56, 0x86, 0x50, 0xc7, 0xaa, 0x6c, 0xd9, 0x50, 0x7e, 0x48, 0xd9, 0x40, 0xbe, 0x84, 0xa6, + 0x88, 0x5c, 0x9f, 0x05, 0x4e, 0xe0, 0x87, 0xd7, 0xc9, 0xcf, 0x43, 0x1e, 0xcd, 0xfd, 0xf4, 0x41, + 0x51, 0xbc, 0x43, 0x02, 0xda, 0x10, 0x33, 0x80, 0xfc, 0x1e, 0x6c, 0xf3, 0x50, 0x38, 0x49, 0xe9, + 0xe8, 0x78, 0xe9, 0x0f, 0x42, 0x4a, 0x8b, 0xd3, 0xce, 0x85, 0xda, 0x94, 0x12, 0x3e, 0x8f, 0x12, + 0xb6, 0x00, 0xa0, 0xec, 0x36, 0xe9, 0x60, 0x33, 0xf5, 0x5d, 0x21, 0x5f, 0xdf, 0x1d, 0x41, 0xc3, + 0xb4, 0xbe, 0xd8, 0x82, 0xa9, 0x27, 0x6c, 0x1d, 0xfc, 0xca, 0xec, 0xc4, 0xce, 0xec, 0x07, 0x44, + 0xc7, 0xe6, 0xf7, 0x43, 0x86, 0xe9, 0xbe, 0xea, 0xf5, 0xb3, 0xbb, 0xed, 0xbf, 0x2d, 0x40, 0x0b, + 0x45, 0xcc, 0x9c, 0xfc, 0xdb, 0xd0, 0x88, 0x53, 0x28, 0x19, 0x87, 0x6c, 0x67, 0x46, 0x88, 0xe9, + 0x22, 0xcd, 0x12, 0x92, 0x03, 0xd8, 0x16, 0x93, 0xcb, 0x64, 0x8e, 0xf8, 0x56, 0x44, 0xe1, 0xab, + 0xa9, 0xe4, 0x49, 0xb9, 0xb5, 0x74, 0x8d, 0x7c, 0x0a, 0x9b, 0xc9, 0xdc, 0x77, 0xb6, 0x41, 0x0f, + 0xc3, 0x17, 0x17, 0xec, 0xbf, 0x29, 0xa4, 0xe5, 0x09, 0x66, 0x58, 0xd5, 0x76, 0xa4, 0x26, 0x86, + 0x9f, 0x4b, 0x33, 0xe5, 0x47, 0x50, 0x31, 0xff, 0x41, 0xd2, 0x59, 0xc0, 0x40, 0x59, 0x23, 0x2d, + 0xe7, 0x8c, 0x74, 0x0f, 0xea, 0x26, 0xf3, 0x72, 0x34, 0x8b, 0x12, 0x96, 0x7d, 0x29, 0x62, 0xe6, + 0xaf, 0x95, 0x6c, 0xb9, 0xfb, 0x4f, 0x45, 0xd8, 0xcc, 0x88, 0x86, 0xfd, 0x7b, 0x14, 0x92, 0x2f, + 0xa0, 0xc2, 0xd4, 0x97, 0x92, 0xb1, 0x75, 0x60, 0x2f, 0x2d, 0x19, 0x34, 0xf1, 0xbe, 0xfe, 0x43, + 0xcd, 0x0e, 0xf2, 0x43, 0x58, 0x8f, 0x02, 0xcf, 0x90, 0x5c, 0xa4, 0xf9, 0x26, 0x8f, 0x34, 0xbf, + 0x9c, 0x41, 0xc8, 0x0c, 0x44, 0x57, 0x54, 0x25, 0x09, 0x15, 0xe6, 0xdf, 0x8a, 0x91, 0x6e, 0x13, + 0xd6, 0x8f, 0xfa, 0x3f, 0xed, 0x76, 0x68, 0xcf, 0xe9, 0xf4, 0x7a, 0xca, 0xb5, 0x09, 0xb4, 0x3a, + 0xdd, 0xee, 0xc9, 0xc5, 0xe0, 0xfc, 0xcc, 0xe0, 0x0a, 0xd8, 0x3c, 0x27, 0x64, 0xbd, 0xfe, 0xbb, + 0xbe, 0x0e, 0x78, 0xdb, 0x60, 0xa5, 0x84, 0xb4, 0x7f, 0x7c, 0xf2, 0xad, 0x0a, 0x7c, 0x00, 0x95, + 0x77, 0x27, 0xdd, 0x23, 0x0c, 0x7b, 0x18, 0x25, 0x2e, 0x06, 0x06, 0x5a, 0x23, 0x1b, 0xd0, 0xb8, + 0x38, 0xec, 0x39, 0x17, 0xa7, 0xbd, 0x0e, 0x32, 0xa8, 0x10, 0x0b, 0x9a, 0x83, 0xce, 0x71, 0xdf, + 0xe9, 0xbe, 0xe9, 0x0c, 0x5e, 0xf7, 0x7b, 0x56, 0xd5, 0xfe, 0x23, 0x9d, 0x7e, 0x33, 0x2e, 0x47, + 0x7e, 0x3c, 0xe7, 0xa3, 0x0b, 0xb6, 0x38, 0x23, 0xce, 0xbb, 0x67, 0xaa, 0xa4, 0x62, 0x46, 0x49, + 0xaf, 0xd6, 0xff, 0xa0, 0xb1, 0xff, 0xd9, 0xcb, 0x64, 0xf3, 0x65, 0x45, 0x7d, 0x7d, 0xfe, 0x3f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x9a, 0xb1, 0xaf, 0x0c, 0xb6, 0x27, 0x00, 0x00, } diff --git a/protocol/protobuf/pairing.proto b/protocol/protobuf/pairing.proto index fc4882464..a86e4baee 100644 --- a/protocol/protobuf/pairing.proto +++ b/protocol/protobuf/pairing.proto @@ -28,8 +28,8 @@ message Backup { FetchingBackedUpDataDetails profileDetails = 8; SyncSetting setting = 9; FetchingBackedUpDataDetails settingsDetails = 10; - SyncKeypairFull fullKeypair = 11; - FetchingBackedUpDataDetails fullKeypairDetails = 12; + SyncKeypair keypair = 11; + FetchingBackedUpDataDetails keypairDetails = 12; SyncAccount watchOnlyAccount = 13; FetchingBackedUpDataDetails watchOnlyAccountDetails = 14; } @@ -296,6 +296,7 @@ message SyncAccount { bool chat = 10; bool hidden = 11; bool removed = 12; + int64 position = 13; } message SyncKeypair { @@ -307,11 +308,8 @@ message SyncKeypair { uint64 last_used_derivation_index = 6; string synced_from = 7; repeated SyncAccount accounts = 8; -} - -message SyncKeypairFull { - SyncKeypair keypair = 1; - repeated SyncKeycard keycards = 2; + repeated SyncKeycard keycards = 9; + bool removed = 10; } message SyncSavedAddress { diff --git a/protocol/v1/status_message.go b/protocol/v1/status_message.go index 3680c6d01..936a730f4 100644 --- a/protocol/v1/status_message.go +++ b/protocol/v1/status_message.go @@ -326,8 +326,6 @@ func (m *StatusMessage) HandleApplication() error { return m.unmarshalProtobufData(new(protobuf.SyncEnsUsernameDetail)) case protobuf.ApplicationMetadataMessage_SYNC_KEYPAIR: return m.unmarshalProtobufData(new(protobuf.SyncKeypair)) - case protobuf.ApplicationMetadataMessage_SYNC_FULL_KEYPAIR: - return m.unmarshalProtobufData(new(protobuf.SyncKeypairFull)) case protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION: return m.unmarshalProtobufData(new(protobuf.SyncActivityCenterNotifications)) case protobuf.ApplicationMetadataMessage_SYNC_ACTIVITY_CENTER_NOTIFICATION_STATE: diff --git a/protocol/wakusync/response.go b/protocol/wakusync/response.go index 54737eab8..e4e522115 100644 --- a/protocol/wakusync/response.go +++ b/protocol/wakusync/response.go @@ -13,7 +13,6 @@ type WakuBackedUpDataResponse struct { FetchingDataProgress map[string]protobuf.FetchingBackedUpDataDetails // key represents the data/section backup details refer to Profile *BackedUpProfile Setting *settings.SyncSettingField - Keycards []*accounts.Keycard Keypair *accounts.Keypair WatchOnlyAccount *accounts.Account } @@ -24,14 +23,12 @@ func (sfwr *WakuBackedUpDataResponse) MarshalJSON() ([]byte, error) { FetchingDataProgress map[string]FetchingBackupedDataDetails `json:"fetchingBackedUpDataProgress,omitempty"` Profile *BackedUpProfile `json:"backedUpProfile,omitempty"` Setting *settings.SyncSettingField `json:"backedUpSettings,omitempty"` - Keycards []*accounts.Keycard `json:"backedUpKeycards,omitempty"` Keypair *accounts.Keypair `json:"backedUpKeypair,omitempty"` WatchOnlyAccount *accounts.Account `json:"backedUpWatchOnlyAccount,omitempty"` }{ Clock: sfwr.Clock, Profile: sfwr.Profile, Setting: sfwr.Setting, - Keycards: sfwr.Keycards, Keypair: sfwr.Keypair, WatchOnlyAccount: sfwr.WatchOnlyAccount, } diff --git a/services/accounts/accounts.go b/services/accounts/accounts.go index 649d7398c..3dd889f7a 100644 --- a/services/accounts/accounts.go +++ b/services/accounts/accounts.go @@ -78,7 +78,7 @@ func (api *API) UpdateKeypairName(ctx context.Context, keyUID string, name strin } func (api *API) UpdateAccountPosition(ctx context.Context, address types.Address, position int64) error { - return api.db.UpdateAccountPosition(address, position) + return (*api.messenger).UpdateAccountPosition(address, position) } func (api *API) GetAccounts(ctx context.Context) ([]*accounts.Account, error) { @@ -102,66 +102,17 @@ func (api *API) GetKeypairByKeyUID(ctx context.Context, keyUID string) (*account } func (api *API) DeleteAccount(ctx context.Context, address types.Address) error { - acc, err := api.db.GetAccountByAddress(address) + err := (*api.messenger).DeleteAccount(address) if err != nil { return err } - if acc.Type != accounts.AccountTypeWatch { - kp, err := api.db.GetKeypairByKeyUID(acc.KeyUID) - if err != nil { - return err - } - - lastAcccountOfKeypairWithTheSameKey := len(kp.Accounts) == 1 - - knownKeycardsForKeyUID, err := api.db.GetKeycardByKeyUID(acc.KeyUID) - if err != nil { - return err - } - - if len(knownKeycardsForKeyUID) == 0 { - err = api.manager.DeleteAccount(address) - var e *account.ErrCannotLocateKeyFile - if err != nil && !errors.As(err, &e) { - return err - } - - if acc.Type != accounts.AccountTypeKey { - if lastAcccountOfKeypairWithTheSameKey { - err = api.manager.DeleteAccount(types.Address(common.HexToAddress(kp.DerivedFrom))) - var e *account.ErrCannotLocateKeyFile - if err != nil && !errors.As(err, &e) { - return err - } - } - } - } else { - if lastAcccountOfKeypairWithTheSameKey { - knownKeycards, err := api.db.GetAllKnownKeycards() - if err != nil { - return err - } - - for _, kc := range knownKeycards { - if kc.KeyUID == acc.KeyUID { - clock := uint64(time.Now().Unix()) - err = (*api.messenger).RemoveMigratedAccountsForKeycard(ctx, kc.KeycardUID, kc.AccountsAddresses, clock) - if err != nil { - return err - } - } - } - } - } - } - api.feed.Send(accountsevent.Event{ Type: accountsevent.EventTypeRemoved, Accounts: []common.Address{common.Address(address)}, }) - return (*api.messenger).DeleteAccount(address) + return nil } func (api *API) AddKeypair(ctx context.Context, password string, keypair *accounts.Keypair) error { diff --git a/services/ext/signal.go b/services/ext/signal.go index 677d5bc94..452c545ab 100644 --- a/services/ext/signal.go +++ b/services/ext/signal.go @@ -161,10 +161,6 @@ func (m *MessengerSignalsHandler) SendWakuBackedUpKeypair(response *wakusync.Wak signal.SendWakuBackedUpKeypair(response) } -func (m *MessengerSignalsHandler) SendWakuBackedUpKeycards(response *wakusync.WakuBackedUpDataResponse) { - signal.SendWakuBackedUpKeycards(response) -} - func (m *MessengerSignalsHandler) SendWakuBackedUpWatchOnlyAccount(response *wakusync.WakuBackedUpDataResponse) { signal.SendWakuBackedUpWatchOnlyAccount(response) } diff --git a/services/web3provider/api_test.go b/services/web3provider/api_test.go index e164592e3..63d7e45df 100644 --- a/services/web3provider/api_test.go +++ b/services/web3provider/api_test.go @@ -79,7 +79,7 @@ func setupTestAPI(t *testing.T) (*API, func()) { accounts := []*accounts.Account{ {Address: types.HexToAddress(utils.TestConfig.Account1.WalletAddress), Chat: true, Wallet: true}, } - require.NoError(t, service.accountsDB.SaveOrUpdateAccounts(accounts)) + require.NoError(t, service.accountsDB.SaveOrUpdateAccounts(accounts, false)) require.NoError(t, service.accountsDB.CreateSettings(settings, *nodeConfig)) diff --git a/signal/events_sync_from_waku.go b/signal/events_sync_from_waku.go index cef552ad3..d9558282b 100644 --- a/signal/events_sync_from_waku.go +++ b/signal/events_sync_from_waku.go @@ -15,9 +15,6 @@ const ( // EventWakuBackedUpKeypair is emitted while applying fetched keypair data from waku EventWakuBackedUpKeypair = "waku.backedup.keypair" - // EventWakuBackedUpKeycards is emitted while applying fetched keycard data from waku - EventWakuBackedUpKeycards = "waku.backedup.keycards" - // EventWakuBackedUpWatchOnlyAccount is emitted while applying fetched watch only account data from waku EventWakuBackedUpWatchOnlyAccount = "waku.backedup.watch-only-account" // #nosec G101 ) @@ -38,10 +35,6 @@ func SendWakuBackedUpKeypair(obj json.Marshaler) { send(EventWakuBackedUpKeypair, obj) } -func SendWakuBackedUpKeycards(obj json.Marshaler) { - send(EventWakuBackedUpKeycards, obj) -} - func SendWakuBackedUpWatchOnlyAccount(obj json.Marshaler) { send(EventWakuBackedUpWatchOnlyAccount, obj) }