mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 13:08:46 +00:00
Reduce expensive group operations during message processing.
This commit is contained in:
@@ -9,6 +9,7 @@ import androidx.annotation.WorkerThread;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.zkgroup.VerificationFailedException;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
|
||||
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
|
||||
import org.signal.storageservice.protos.groups.GroupExternalCredential;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
@@ -185,9 +186,21 @@ public final class GroupManager {
|
||||
long timestamp,
|
||||
@Nullable byte[] signedGroupChange)
|
||||
throws GroupChangeBusyException, IOException, GroupNotAMemberException
|
||||
{
|
||||
return updateGroupFromServer(context, groupMasterKey, null, revision, timestamp, signedGroupChange);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public static GroupsV2StateProcessor.GroupUpdateResult updateGroupFromServer(@NonNull Context context,
|
||||
@NonNull GroupMasterKey groupMasterKey,
|
||||
@Nullable GroupSecretParams groupSecretParams,
|
||||
int revision,
|
||||
long timestamp,
|
||||
@Nullable byte[] signedGroupChange)
|
||||
throws GroupChangeBusyException, IOException, GroupNotAMemberException
|
||||
{
|
||||
try (GroupManagerV2.GroupUpdater updater = new GroupManagerV2(context).updater(groupMasterKey)) {
|
||||
return updater.updateLocalToServerRevision(revision, timestamp, signedGroupChange);
|
||||
return updater.updateLocalToServerRevision(revision, timestamp, groupSecretParams, signedGroupChange);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -797,10 +797,10 @@ final class GroupManagerV2 {
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
GroupsV2StateProcessor.GroupUpdateResult updateLocalToServerRevision(int revision, long timestamp, @Nullable byte[] signedGroupChange)
|
||||
GroupsV2StateProcessor.GroupUpdateResult updateLocalToServerRevision(int revision, long timestamp, @Nullable GroupSecretParams groupSecretParams, @Nullable byte[] signedGroupChange)
|
||||
throws IOException, GroupNotAMemberException
|
||||
{
|
||||
return new GroupsV2StateProcessor(context).forGroup(serviceIds, groupMasterKey)
|
||||
return new GroupsV2StateProcessor(context).forGroup(serviceIds, groupMasterKey, groupSecretParams)
|
||||
.updateLocalGroupToRevision(revision, timestamp, getDecryptedGroupChange(signedGroupChange));
|
||||
}
|
||||
|
||||
|
||||
@@ -107,9 +107,15 @@ public class GroupsV2StateProcessor {
|
||||
}
|
||||
|
||||
public StateProcessorForGroup forGroup(@NonNull ServiceIds serviceIds, @NonNull GroupMasterKey groupMasterKey) {
|
||||
ProfileAndMessageHelper profileAndMessageHelper = new ProfileAndMessageHelper(context, serviceIds.getAci(), groupMasterKey, GroupId.v2(groupMasterKey), recipientTable);
|
||||
return forGroup(serviceIds, groupMasterKey, null);
|
||||
}
|
||||
|
||||
return new StateProcessorForGroup(serviceIds, context, groupDatabase, groupsV2Api, groupsV2Authorization, groupMasterKey, profileAndMessageHelper);
|
||||
public StateProcessorForGroup forGroup(@NonNull ServiceIds serviceIds, @NonNull GroupMasterKey groupMasterKey, @Nullable GroupSecretParams groupSecretParams) {
|
||||
if (groupSecretParams == null) {
|
||||
return new StateProcessorForGroup(serviceIds, context, groupDatabase, groupsV2Api, groupsV2Authorization, groupMasterKey, recipientTable);
|
||||
} else {
|
||||
return new StateProcessorForGroup(serviceIds, context, groupDatabase, groupsV2Api, groupsV2Authorization, groupMasterKey, groupSecretParams, recipientTable);
|
||||
}
|
||||
}
|
||||
|
||||
public enum GroupState {
|
||||
@@ -153,6 +159,37 @@ public class GroupsV2StateProcessor {
|
||||
private final GroupSecretParams groupSecretParams;
|
||||
private final ProfileAndMessageHelper profileAndMessageHelper;
|
||||
|
||||
private StateProcessorForGroup(@NonNull ServiceIds serviceIds,
|
||||
@NonNull Context context,
|
||||
@NonNull GroupTable groupDatabase,
|
||||
@NonNull GroupsV2Api groupsV2Api,
|
||||
@NonNull GroupsV2Authorization groupsV2Authorization,
|
||||
@NonNull GroupMasterKey groupMasterKey,
|
||||
@NonNull RecipientTable recipientTable)
|
||||
{
|
||||
this(serviceIds, context, groupDatabase, groupsV2Api, groupsV2Authorization, groupMasterKey, GroupSecretParams.deriveFromMasterKey(groupMasterKey), recipientTable);
|
||||
}
|
||||
|
||||
private StateProcessorForGroup(@NonNull ServiceIds serviceIds,
|
||||
@NonNull Context context,
|
||||
@NonNull GroupTable groupDatabase,
|
||||
@NonNull GroupsV2Api groupsV2Api,
|
||||
@NonNull GroupsV2Authorization groupsV2Authorization,
|
||||
@NonNull GroupMasterKey groupMasterKey,
|
||||
@NonNull GroupSecretParams groupSecretParams,
|
||||
@NonNull RecipientTable recipientTable)
|
||||
{
|
||||
this.serviceIds = serviceIds;
|
||||
this.context = context;
|
||||
this.groupDatabase = groupDatabase;
|
||||
this.groupsV2Api = groupsV2Api;
|
||||
this.groupsV2Authorization = groupsV2Authorization;
|
||||
this.masterKey = groupMasterKey;
|
||||
this.groupSecretParams = groupSecretParams;
|
||||
this.groupId = GroupId.v2(groupSecretParams.getPublicParams().getGroupIdentifier());
|
||||
this.profileAndMessageHelper = new ProfileAndMessageHelper(context, serviceIds.getAci(), groupMasterKey, groupId, recipientTable);
|
||||
}
|
||||
|
||||
@VisibleForTesting StateProcessorForGroup(@NonNull ServiceIds serviceIds,
|
||||
@NonNull Context context,
|
||||
@NonNull GroupTable groupDatabase,
|
||||
@@ -167,8 +204,8 @@ public class GroupsV2StateProcessor {
|
||||
this.groupsV2Api = groupsV2Api;
|
||||
this.groupsV2Authorization = groupsV2Authorization;
|
||||
this.masterKey = groupMasterKey;
|
||||
this.groupId = GroupId.v2(masterKey);
|
||||
this.groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
|
||||
this.groupId = GroupId.v2(groupSecretParams.getPublicParams().getGroupIdentifier());
|
||||
this.profileAndMessageHelper = profileAndMessageHelper;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.orNull
|
||||
import org.signal.core.util.toOptional
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams
|
||||
import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialPresentation
|
||||
import org.thoughtcrime.securesms.attachments.Attachment
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
|
||||
@@ -120,11 +121,12 @@ object DataMessageProcessor {
|
||||
earlyMessageCacheEntry: EarlyMessageCacheEntry?
|
||||
) {
|
||||
val message: DataMessage = content.dataMessage
|
||||
val groupId: GroupId.V2? = if (message.hasGroupContext) GroupId.v2(message.groupV2.groupMasterKey) else null
|
||||
val groupSecretParams = if (message.hasGroupContext) GroupSecretParams.deriveFromMasterKey(message.groupV2.groupMasterKey) else null
|
||||
val groupId: GroupId.V2? = if (groupSecretParams != null) GroupId.v2(groupSecretParams.publicParams.groupIdentifier) else null
|
||||
|
||||
var groupProcessResult: MessageContentProcessorV2.Gv2PreProcessResult? = null
|
||||
if (groupId != null) {
|
||||
groupProcessResult = MessageContentProcessorV2.handleGv2PreProcessing(context, envelope.timestamp, content, metadata, groupId, message.groupV2, senderRecipient)
|
||||
groupProcessResult = MessageContentProcessorV2.handleGv2PreProcessing(context, envelope.timestamp, content, metadata, groupId, message.groupV2, senderRecipient, groupSecretParams)
|
||||
if (groupProcessResult == MessageContentProcessorV2.Gv2PreProcessResult.IGNORE) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.signal.core.util.orNull
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey
|
||||
import org.signal.libsignal.protocol.message.DecryptionErrorMessage
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MessageLogEntry
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
@@ -219,7 +220,8 @@ open class MessageContentProcessorV2(private val context: Context) {
|
||||
metadata: EnvelopeMetadata,
|
||||
groupId: GroupId.V2,
|
||||
groupV2: SignalServiceProtos.GroupContextV2,
|
||||
senderRecipient: Recipient
|
||||
senderRecipient: Recipient,
|
||||
groupSecretParams: GroupSecretParams? = null
|
||||
): Gv2PreProcessResult {
|
||||
val possibleV1OrV2Group = SignalDatabase.groups.getGroupV1OrV2ByExpectedV2(groupId)
|
||||
val needsV1Migration = possibleV1OrV2Group.isPresent && possibleV1OrV2Group.get().isV1Group
|
||||
@@ -227,7 +229,7 @@ open class MessageContentProcessorV2(private val context: Context) {
|
||||
GroupsV1MigrationUtil.performLocalMigration(context, possibleV1OrV2Group.get().id.requireV1())
|
||||
}
|
||||
|
||||
val groupUpdateResult = updateGv2GroupFromServerOrP2PChange(context, timestamp, groupV2)
|
||||
val groupUpdateResult = updateGv2GroupFromServerOrP2PChange(context, timestamp, groupV2, groupSecretParams)
|
||||
if (groupUpdateResult == null) {
|
||||
log(timestamp, "Ignoring GV2 message for group we are not currently in $groupId")
|
||||
return Gv2PreProcessResult.IGNORE
|
||||
@@ -266,12 +268,13 @@ open class MessageContentProcessorV2(private val context: Context) {
|
||||
fun updateGv2GroupFromServerOrP2PChange(
|
||||
context: Context,
|
||||
timestamp: Long,
|
||||
groupV2: SignalServiceProtos.GroupContextV2
|
||||
groupV2: SignalServiceProtos.GroupContextV2,
|
||||
groupSecretParams: GroupSecretParams? = null
|
||||
): GroupsV2StateProcessor.GroupUpdateResult? {
|
||||
return try {
|
||||
val signedGroupChange: ByteArray? = if (groupV2.hasSignedGroupChange) groupV2.signedGroupChange else null
|
||||
val updatedTimestamp = if (signedGroupChange != null) timestamp else timestamp - 1
|
||||
GroupManager.updateGroupFromServer(context, groupV2.groupMasterKey, groupV2.revision, updatedTimestamp, signedGroupChange)
|
||||
GroupManager.updateGroupFromServer(context, groupV2.groupMasterKey, groupSecretParams, groupV2.revision, updatedTimestamp, signedGroupChange)
|
||||
} catch (e: GroupNotAMemberException) {
|
||||
warn(timestamp, "Ignoring message for a group we're not in")
|
||||
null
|
||||
|
||||
Reference in New Issue
Block a user