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"
statusWalletRootPath = "m/44'/60'/0'/0/"
zeroAddress = "0x0000000000000000000000000000000000000000"
SyncedFromBackup = "backup" // means a account is coming from backed up data
SyncedFromLocalPairing = "local-pairing" // means a account is coming from another device when user is reocovering Status account
SyncedFromBackup = "backup" // means a keypair is coming from backed up data
ThirtyDaysInMilliseconds = 30 * 24 * 60 * 60 * 1000
)
@ -1266,8 +1265,12 @@ func (db *Database) GetNodeConfig() (*params.NodeConfig, error) {
return nodecfg.GetNodeConfigFromDB(db.db)
}
// This function should not update the clock, cause it marks keypair/accounts locally.
func (db *Database) MarkKeypairFullyOperable(keyUID string) (err error) {
// Basically this function should not update the clock, cause it marks keypair/accounts locally. But...
// 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()
if err != nil {
return err
@ -1293,9 +1296,13 @@ func (db *Database) MarkKeypairFullyOperable(keyUID string) (err error) {
}
_, err = tx.Exec(`UPDATE keypairs SET synced_from = "" WHERE key_uid = ?`, keyUID)
if err != nil {
return err
}
return db.updateKeypairClock(tx, keyUID, clock)
}
// This function should not update the clock, cause it marks a keypair locally.
func (db *Database) SetKeypairSyncedFrom(address types.Address, operable AccountOperable) (err error) {
tx, err := db.db.Begin()

View File

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

View File

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

View File

@ -3150,7 +3150,7 @@ func (m *Messenger) handleSyncAccountsPositions(message *protobuf.SyncAccountsPo
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 {
return nil, errors.New("handleSyncKeypair receive a nil message")
}
@ -3170,14 +3170,18 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.
Removed: message.Removed,
}
accountReceivedFromLocalPairing := message.SyncedFrom == accounts.SyncedFromLocalPairing
if dbKeypair != nil {
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
// 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
}
}
for _, sAcc := range message.Accounts {
syncKpMigratedToKeycard := len(message.Keycards) > 0
@ -3190,7 +3194,7 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.
}
syncKpMigratedToKeycard = multiAcc != nil && multiAcc.KeycardPairing != ""
}
accountOperability, err := m.resolveAccountOperability(sAcc, syncKpMigratedToKeycard, accountReceivedFromLocalPairing)
accountOperability, err := m.resolveAccountOperability(sAcc, syncKpMigratedToKeycard, fromLocalPairing)
if err != nil {
return nil, err
}
@ -3205,7 +3209,7 @@ func (m *Messenger) handleSyncKeypair(message *protobuf.SyncKeypair) (*accounts.
if err != nil {
return nil, err
}
} else if !accountReceivedFromLocalPairing && dbKeypair != nil {
} else if !fromLocalPairing && dbKeypair != nil {
for _, dbAcc := range dbKeypair.Accounts {
found := false
for _, acc := range kp.Accounts {
@ -3306,8 +3310,8 @@ func (m *Messenger) HandleSyncWatchOnlyAccount(state *ReceivedMessageState, mess
return nil
}
func (m *Messenger) HandleSyncKeypair(state *ReceivedMessageState, message protobuf.SyncKeypair) error {
kp, err := m.handleSyncKeypair(&message)
func (m *Messenger) HandleSyncKeypair(state *ReceivedMessageState, message protobuf.SyncKeypair, fromLocalPairing bool) error {
kp, err := m.handleSyncKeypair(&message, fromLocalPairing)
if err != nil {
if err == ErrTryingToStoreOldKeypair {
return nil

View File

@ -209,7 +209,7 @@ func (m *Messenger) HandleSyncRawMessages(rawMessages []*protobuf.RawMessage) er
if err != nil {
return err
}
err = m.HandleSyncKeypair(state, message)
err = m.HandleSyncKeypair(state, message, true)
if err != nil {
m.logger.Error("failed to HandleSyncKeypair when HandleSyncRawMessages", zap.Error(err))
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)
}
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 {
acc, err := m.settings.GetAccountByAddress(address)
if err != nil {

View File

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