fix: synced from field updated if recovered keypairs made fully operable

This commit is contained in:
Sale Djenic 2023-08-09 13:14:17 +02:00 committed by saledjenic
parent 2325bc5565
commit 6ee7038809
7 changed files with 39 additions and 21 deletions

View File

@ -21,8 +21,7 @@ const (
statusChatPath = "m/43'/60'/1581'/0'/0" statusChatPath = "m/43'/60'/1581'/0'/0"
statusWalletRootPath = "m/44'/60'/0'/0/" statusWalletRootPath = "m/44'/60'/0'/0/"
zeroAddress = "0x0000000000000000000000000000000000000000" zeroAddress = "0x0000000000000000000000000000000000000000"
SyncedFromBackup = "backup" // means a account is coming from backed up data SyncedFromBackup = "backup" // means a keypair is coming from backed up data
SyncedFromLocalPairing = "local-pairing" // means a account is coming from another device when user is reocovering Status account
ThirtyDaysInMilliseconds = 30 * 24 * 60 * 60 * 1000 ThirtyDaysInMilliseconds = 30 * 24 * 60 * 60 * 1000
) )
@ -1266,8 +1265,12 @@ func (db *Database) GetNodeConfig() (*params.NodeConfig, error) {
return nodecfg.GetNodeConfigFromDB(db.db) return nodecfg.GetNodeConfigFromDB(db.db)
} }
// This function should not update the clock, cause it marks keypair/accounts locally. // Basically this function should not update the clock, cause it marks keypair/accounts locally. But...
func (db *Database) MarkKeypairFullyOperable(keyUID string) (err error) { // we need to cover the case when user recovers a Status account from waku, then pairs another device via
// local pairing and then imports seed/private key for the non profile keypair on one of those two devices
// to make that keypair fully operable. In that case we need to inform other device about the change, that
// other device may offer other options for importing that keypair on it.
func (db *Database) MarkKeypairFullyOperable(keyUID string, clock uint64) (err error) {
tx, err := db.db.Begin() tx, err := db.db.Begin()
if err != nil { if err != nil {
return err return err
@ -1293,7 +1296,11 @@ func (db *Database) MarkKeypairFullyOperable(keyUID string) (err error) {
} }
_, err = tx.Exec(`UPDATE keypairs SET synced_from = "" WHERE key_uid = ?`, keyUID) _, err = tx.Exec(`UPDATE keypairs SET synced_from = "" WHERE key_uid = ?`, keyUID)
if err != nil {
return err return err
}
return db.updateKeypairClock(tx, keyUID, clock)
} }
// This function should not update the clock, cause it marks a keypair locally. // This function should not update the clock, cause it marks a keypair locally.

View File

@ -2464,7 +2464,6 @@ func (m *Messenger) syncProfilePictures(rawMessageHandler RawMessageHandler) err
// SyncDevices sends all public chats and contacts to paired devices // SyncDevices sends all public chats and contacts to paired devices
// TODO remove use of photoPath in contacts // TODO remove use of photoPath in contacts
func (m *Messenger) SyncDevices(ctx context.Context, ensName, photoPath string, rawMessageHandler RawMessageHandler) (err error) { func (m *Messenger) SyncDevices(ctx context.Context, ensName, photoPath string, rawMessageHandler RawMessageHandler) (err error) {
syncedFromLocalPairing := rawMessageHandler != nil
if rawMessageHandler == nil { if rawMessageHandler == nil {
rawMessageHandler = m.dispatchMessage rawMessageHandler = m.dispatchMessage
} }
@ -2606,9 +2605,6 @@ func (m *Messenger) SyncDevices(ctx context.Context, ensName, photoPath string,
} }
for _, kp := range keypairs { for _, kp := range keypairs {
if syncedFromLocalPairing {
kp.SyncedFrom = accounts.SyncedFromLocalPairing
}
err = m.syncKeypair(kp, rawMessageHandler) err = m.syncKeypair(kp, rawMessageHandler)
if err != nil { if err != nil {
return err return err
@ -4425,7 +4421,7 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte
p := msg.ParsedMessage.Interface().(protobuf.SyncKeypair) p := msg.ParsedMessage.Interface().(protobuf.SyncKeypair)
m.outputToCSV(msg.TransportMessage.Timestamp, msg.ID, senderID, filter.Topic, filter.ChatID, msg.Type, p) m.outputToCSV(msg.TransportMessage.Timestamp, msg.ID, senderID, filter.Topic, filter.ChatID, msg.Type, p)
logger.Debug("Handling SyncKeypair", zap.Any("message", p)) logger.Debug("Handling SyncKeypair", zap.Any("message", p))
err = m.HandleSyncKeypair(messageState, p) err = m.HandleSyncKeypair(messageState, p, false)
if err != nil { if err != nil {
logger.Warn("failed to handle SyncKeypair", zap.Error(err)) logger.Warn("failed to handle SyncKeypair", zap.Error(err))
allMessagesProcessed = false allMessagesProcessed = false

View File

@ -211,7 +211,7 @@ func (m *Messenger) handleKeypair(message *protobuf.SyncKeypair) error {
message.Keycards = []*protobuf.SyncKeycard{} message.Keycards = []*protobuf.SyncKeycard{}
} }
keypair, err := m.handleSyncKeypair(message) keypair, err := m.handleSyncKeypair(message, false)
if err != nil { if err != nil {
if err == ErrTryingToStoreOldKeypair { if err == ErrTryingToStoreOldKeypair {
return nil return nil

View File

@ -3150,7 +3150,7 @@ func (m *Messenger) handleSyncAccountsPositions(message *protobuf.SyncAccountsPo
return accs, nil return accs, nil
} }
func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.Keypair, error) { func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair, fromLocalPairing bool) (*accounts.Keypair, error) {
if message == nil { if message == nil {
return nil, errors.New("handleSyncKeypair receive a nil message") return nil, errors.New("handleSyncKeypair receive a nil message")
} }
@ -3170,14 +3170,18 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.
Removed: message.Removed, Removed: message.Removed,
} }
accountReceivedFromLocalPairing := message.SyncedFrom == accounts.SyncedFromLocalPairing
if dbKeypair != nil { if dbKeypair != nil {
if dbKeypair.Clock >= kp.Clock { if dbKeypair.Clock >= kp.Clock {
return nil, ErrTryingToStoreOldKeypair 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 // 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
// but in case if keypair on this device came from the backup (e.g. device A recovered from waku, then device B paired with the device A
// via local pairing, before device A made its keypairs fully operable) we need to update syncedFrom when user on this device when that
// keypair becomes operable on any of other paired devices
if dbKeypair.SyncedFrom != accounts.SyncedFromBackup {
kp.SyncedFrom = dbKeypair.SyncedFrom kp.SyncedFrom = dbKeypair.SyncedFrom
} }
}
for _, sAcc := range message.Accounts { for _, sAcc := range message.Accounts {
syncKpMigratedToKeycard := len(message.Keycards) > 0 syncKpMigratedToKeycard := len(message.Keycards) > 0
@ -3190,7 +3194,7 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.
} }
syncKpMigratedToKeycard = multiAcc != nil && multiAcc.KeycardPairing != "" syncKpMigratedToKeycard = multiAcc != nil && multiAcc.KeycardPairing != ""
} }
accountOperability, err := m.resolveAccountOperability(sAcc, syncKpMigratedToKeycard, accountReceivedFromLocalPairing) accountOperability, err := m.resolveAccountOperability(sAcc, syncKpMigratedToKeycard, fromLocalPairing)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3205,7 +3209,7 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else if !accountReceivedFromLocalPairing && dbKeypair != nil { } else if !fromLocalPairing && dbKeypair != nil {
for _, dbAcc := range dbKeypair.Accounts { for _, dbAcc := range dbKeypair.Accounts {
found := false found := false
for _, acc := range kp.Accounts { for _, acc := range kp.Accounts {
@ -3306,8 +3310,8 @@ func (m *Messenger) HandleSyncWatchOnlyAccount(state *ReceivedMessageState, mess
return nil return nil
} }
func (m *Messenger) HandleSyncKeypair(state *ReceivedMessageState, message protobuf.SyncKeypair) error { func (m *Messenger) HandleSyncKeypair(state *ReceivedMessageState, message protobuf.SyncKeypair, fromLocalPairing bool) error {
kp, err := m.handleSyncKeypair(&message) kp, err := m.handleSyncKeypair(&message, fromLocalPairing)
if err != nil { if err != nil {
if err == ErrTryingToStoreOldKeypair { if err == ErrTryingToStoreOldKeypair {
return nil return nil

View File

@ -209,7 +209,7 @@ func (m *Messenger) HandleSyncRawMessages(rawMessages []*protobuf.RawMessage) er
if err != nil { if err != nil {
return err return err
} }
err = m.HandleSyncKeypair(state, message) err = m.HandleSyncKeypair(state, message, true)
if err != nil { if err != nil {
m.logger.Error("failed to HandleSyncKeypair when HandleSyncRawMessages", zap.Error(err)) m.logger.Error("failed to HandleSyncKeypair when HandleSyncRawMessages", zap.Error(err))
continue continue

View File

@ -174,6 +174,17 @@ func (m *Messenger) SaveOrUpdateAccount(acc *accounts.Account) error {
return m.resolveAndSyncKeypairOrJustWalletAccount(acc.KeyUID, acc.Address, acc.Clock, m.dispatchMessage) return m.resolveAndSyncKeypairOrJustWalletAccount(acc.KeyUID, acc.Address, acc.Clock, m.dispatchMessage)
} }
func (m *Messenger) MarkKeypairFullyOperable(keyUID string) error {
clock, _ := m.getLastClockWithRelatedChat()
err := m.settings.MarkKeypairFullyOperable(keyUID, clock)
if err != nil {
return err
}
return m.resolveAndSyncKeypairOrJustWalletAccount(keyUID, types.Address{}, clock, m.dispatchMessage)
}
func (m *Messenger) deleteKeystoreFileForAddress(address types.Address) error { func (m *Messenger) deleteKeystoreFileForAddress(address types.Address) error {
acc, err := m.settings.GetAccountByAddress(address) acc, err := m.settings.GetAccountByAddress(address)
if err != nil { if err != nil {

View File

@ -337,7 +337,7 @@ func (api *API) MakePrivateKeyKeypairFullyOperable(ctx context.Context, privateK
return err return err
} }
return api.db.MarkKeypairFullyOperable(info.KeyUID) return (*api.messenger).MarkKeypairFullyOperable(info.KeyUID)
} }
// Imports a new mnemonic and creates local keystore file. // Imports a new mnemonic and creates local keystore file.
@ -395,7 +395,7 @@ func (api *API) MakeSeedPhraseKeypairFullyOperable(ctx context.Context, mnemonic
return err return err
} }
return api.db.MarkKeypairFullyOperable(generatedAccountInfo.KeyUID) return (*api.messenger).MarkKeypairFullyOperable(generatedAccountInfo.KeyUID)
} }
// Creates a random new mnemonic. // Creates a random new mnemonic.