Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/7879.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Reduce number of crypto database transactions when handling the sync response
3 changes: 3 additions & 0 deletions library/ui-strings/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3501,4 +3501,7 @@
<string name="message_reply_to_sender_sent_video">sent a video.</string>
<string name="message_reply_to_sender_sent_sticker">sent a sticker.</string>
<string name="message_reply_to_sender_created_poll">created a poll.</string>

<string name="settings_access_token">Access Token</string>
<string name="settings_access_token_summary">Your access token gives full access to your account. Do not share it with anyone.</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2023 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.matrix.android.sdk.api.session.crypto.crosssigning

/**
* Container for the three cross signing keys: master, self signing and user signing.
*/
data class CryptoCrossSigningKeys(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd call that UserIdentity?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

val masterKey: CryptoCrossSigningKey?,
val selfSigningKey: CryptoCrossSigningKey?,
val userSigningKey: CryptoCrossSigningKey?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ internal class DefaultCryptoService @Inject constructor(
}
}
}
cryptoStore.onSyncWillProcess()
}

private fun internalStart() {
Expand Down Expand Up @@ -432,6 +433,7 @@ internal class DefaultCryptoService @Inject constructor(
* @param syncResponse the syncResponse
*/
fun onSyncCompleted(syncResponse: SyncResponse) {
cryptoStore.onSyncCompleted()
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
runCatching {
if (syncResponse.deviceLists != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.extensions.measureMetric
import org.matrix.android.sdk.api.metrics.DownloadDeviceKeysMetricsPlugin
import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKeys
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.internal.crypto.model.CryptoInfoMapper
import org.matrix.android.sdk.internal.crypto.model.rest.KeysQueryResponse
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.store.UserDataToStore
import org.matrix.android.sdk.internal.crypto.tasks.DownloadKeysForUsersTask
import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.session.sync.SyncTokenStore
Expand Down Expand Up @@ -371,6 +373,8 @@ internal class DeviceListManager @Inject constructor(
Timber.v("## CRYPTO | doKeyDownloadForUsers() : Got keys for " + filteredUsers.size + " users")
}

val userDataToStore = UserDataToStore()

for (userId in filteredUsers) {
// al devices =
val models = response.deviceKeys?.get(userId)?.mapValues { entry -> CryptoInfoMapper.map(entry.value) }
Expand Down Expand Up @@ -404,7 +408,7 @@ internal class DeviceListManager @Inject constructor(
}
// Update the store
// Note that devices which aren't in the response will be removed from the stores
cryptoStore.storeUserDevices(userId, workingCopy)
userDataToStore.userDevices[userId] = workingCopy
}

val masterKey = response.masterKeys?.get(userId)?.toCryptoModel().also {
Expand All @@ -416,14 +420,15 @@ internal class DeviceListManager @Inject constructor(
val userSigningKey = response.userSigningKeys?.get(userId)?.toCryptoModel()?.also {
Timber.v("## CRYPTO | CrossSigning : Got keys for $userId : USK ${it.unpaddedBase64PublicKey}")
}
cryptoStore.storeUserCrossSigningKeys(
userId,
masterKey,
selfSigningKey,
userSigningKey
userDataToStore.userCrossSigningKeys[userId] = CryptoCrossSigningKeys(
masterKey = masterKey,
selfSigningKey = selfSigningKey,
userSigningKey = userSigningKey
)
}

cryptoStore.storeUserDataToStore(userDataToStore)

// Update devices trust for these users
// dispatchDeviceChange(downloadUsers)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.crypto.GlobalCryptoConfig
import org.matrix.android.sdk.api.session.crypto.NewSessionListener
import org.matrix.android.sdk.api.session.crypto.OutgoingKeyRequest
import org.matrix.android.sdk.api.session.crypto.OutgoingRoomKeyRequestState
import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey
import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKeys
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo
import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo
Expand All @@ -48,6 +48,21 @@ import org.matrix.olm.OlmOutboundGroupSession
*/
internal interface IMXCryptoStore {

/**
* Notify the store that a sync response treatment is starting.
* Impacted methods:
* - [setShouldShareHistory]
* - [setShouldEncryptForInvitedMembers]
* @See [onSyncCompleted] to notify that the treatment is over.
*/
fun onSyncWillProcess()

/**
* Notify the store that the sync treatment response is finished.
* The store will save all aggregated data.
*/
fun onSyncCompleted()

/**
* @return the device id
*/
Expand Down Expand Up @@ -232,9 +247,7 @@ internal interface IMXCryptoStore {

fun storeUserCrossSigningKeys(
userId: String,
masterKey: CryptoCrossSigningKey?,
selfSigningKey: CryptoCrossSigningKey?,
userSigningKey: CryptoCrossSigningKey?
cryptoCrossSigningKeys: CryptoCrossSigningKeys
)

/**
Expand Down Expand Up @@ -290,13 +303,17 @@ internal interface IMXCryptoStore {

fun shouldEncryptForInvitedMembers(roomId: String): Boolean

/**
* The data is not stored immediately, this MUST be call during a sync response treatment.
*/
fun setShouldEncryptForInvitedMembers(roomId: String, shouldEncryptForInvitedMembers: Boolean)

fun shouldShareHistory(roomId: String): Boolean

/**
* Sets a boolean flag that will determine whether or not room history (existing inbound sessions)
* will be shared to new user invites.
* The data is not stored immediately, this MUST be call during a sync response treatment.
*
* @param roomId the room id
* @param shouldShareHistory The boolean flag
Expand Down Expand Up @@ -580,4 +597,9 @@ internal interface IMXCryptoStore {
fun areDeviceKeysUploaded(): Boolean
fun tidyUpDataBase()
fun getOutgoingRoomKeyRequests(inStates: Set<OutgoingRoomKeyRequestState>): List<OutgoingKeyRequest>

/**
* Store a bunch of data related to the users. @See [UserDataToStore].
*/
fun storeUserDataToStore(userDataToStore: UserDataToStore)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name seems a bit redoudant. storeToStore

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to storeData.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2023 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.matrix.android.sdk.internal.crypto.store

import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKeys
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo

internal data class UserDataToStore(
/**
* Map of userId -> (Map of deviceId -> [CryptoDeviceInfo]).
*/
val userDevices: MutableMap<String, Map<String, CryptoDeviceInfo>> = mutableMapOf(),
/**
* Map of userId -> [CryptoCrossSigningKeys].
*/
val userCrossSigningKeys: MutableMap<String, CryptoCrossSigningKeys> = mutableMapOf(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.matrix.android.sdk.internal.crypto.store.db

data class CryptoStoreAggregator(
val setShouldShareHistoryData: MutableMap<String, Boolean> = mutableMapOf(),
val setShouldEncryptForInvitedMembersData: MutableMap<String, Boolean> = mutableMapOf(),
) {
fun isEmpty(): Boolean {
return setShouldShareHistoryData.isEmpty() &&
setShouldEncryptForInvitedMembersData.isEmpty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import android.util.Base64
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmObject
import timber.log.Timber
import java.io.ByteArrayOutputStream
import java.io.ObjectOutputStream
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import kotlin.system.measureTimeMillis

/**
* Get realm, invoke the action, close realm, and return the result of the action.
Expand Down Expand Up @@ -55,10 +57,12 @@ internal fun <T : RealmObject> doRealmQueryAndCopyList(realmConfiguration: Realm
/**
* Get realm instance, invoke the action in a transaction and close realm.
*/
internal fun doRealmTransaction(realmConfiguration: RealmConfiguration, action: (Realm) -> Unit) {
Realm.getInstance(realmConfiguration).use { realm ->
realm.executeTransaction { action.invoke(it) }
}
internal fun doRealmTransaction(tag: String, realmConfiguration: RealmConfiguration, action: (Realm) -> Unit) {
measureTimeMillis {
Realm.getInstance(realmConfiguration).use { realm ->
realm.executeTransaction { action.invoke(it) }
}
}.also { Timber.w("doRealmTransaction for $tag took $it millis") }
}

internal fun doRealmTransactionAsync(realmConfiguration: RealmConfiguration, action: (Realm) -> Unit) {
Expand Down
Loading