From 1b015323276b2f9b95b850e9cf51dcbd2aeb4895 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 12 Feb 2025 10:33:03 -0500 Subject: [PATCH] Update to the standard SignalService.proto --- .../securesms/testing/MessageContentFuzzer.kt | 2 +- .../securesms/database/CallTable.kt | 2 +- .../securesms/jobs/CallLinkUpdateSendJob.kt | 2 +- .../jobs/MultiDeviceCallLinkSyncJob.kt | 2 +- .../jobs/MultiDeviceContactSyncJob.kt | 38 - .../jobs/MultiDeviceContactUpdateJob.java | 27 +- .../jobs/MultiDeviceDeleteSyncJob.kt | 2 +- .../jobs/MultiDeviceProfileKeyUpdateJob.java | 6 +- .../jobs/RefreshCallLinkDetailsJob.kt | 2 +- .../messages/IncomingMessageObserver.kt | 2 +- .../securesms/messages/MessageDecryptor.kt | 4 +- .../messages/SyncMessageProcessor.kt | 23 +- .../securesms/mms/MessageGroupContext.java | 6 - .../MobileCoinPublicAddressProfileUtil.java | 16 +- .../webrtc/CallEventSyncMessageUtil.kt | 2 +- app/src/main/protowire/Database.proto | 1 + .../MobileCoinPublicAddressProfileUtilTest.kt | 22 +- .../api/SignalServiceMessageSender.java | 6 +- .../messages/multidevice/DeviceContact.java | 30 +- .../DeviceContactsInputStream.java | 41 +- .../DeviceContactsOutputStream.java | 30 - .../messages/multidevice/RequestMessage.java | 6 +- .../api/util/AttachmentPointerUtil.java | 8 +- .../src/main/protowire/SignalService.proto | 1023 ++++++++--------- .../main/protowire/SignalServiceLegacy.proto | 40 + .../DeviceContactsInputStreamTest.java | 27 +- 26 files changed, 593 insertions(+), 777 deletions(-) create mode 100644 libsignal-service/src/main/protowire/SignalServiceLegacy.proto diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/testing/MessageContentFuzzer.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/testing/MessageContentFuzzer.kt index 35ace0612a..2b8610d281 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/testing/MessageContentFuzzer.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/testing/MessageContentFuzzer.kt @@ -258,7 +258,7 @@ object MessageContentFuzzer { authorServiceId = Recipient.resolved(message.first).requireAci().toString(), sentTimestamp = message.second ), - uuid = uuid?.let { UuidUtil.toByteString(it) }, + clientUuid = uuid?.let { UuidUtil.toByteString(it) }, fallbackDigest = digest?.toByteString(), fallbackPlaintextHash = plainTextHash?.let { Base64.decodeOrNull(it)?.toByteString() } ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt index 73e6639301..41413ea87d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt @@ -1525,7 +1525,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl @JvmStatic fun from(event: CallEvent.Event?): Event? { return when (event) { - null, CallEvent.Event.UNKNOWN_ACTION, CallEvent.Event.OBSERVED -> null + null, CallEvent.Event.UNKNOWN_EVENT, CallEvent.Event.OBSERVED -> null CallEvent.Event.ACCEPTED -> ACCEPTED CallEvent.Event.NOT_ACCEPTED -> NOT_ACCEPTED CallEvent.Event.DELETE -> DELETE diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/CallLinkUpdateSendJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/CallLinkUpdateSendJob.kt index 874497b408..b0d7707a54 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/CallLinkUpdateSendJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/CallLinkUpdateSendJob.kt @@ -70,7 +70,7 @@ class CallLinkUpdateSendJob private constructor( val callLinkUpdate = CallLinkUpdate( rootKey = callLink.credentials.linkKeyBytes.toByteString(), - adminPassKey = callLink.credentials.adminPassBytes?.toByteString(), + adminPasskey = callLink.credentials.adminPassBytes?.toByteString(), type = callLinkUpdateType ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceCallLinkSyncJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceCallLinkSyncJob.kt index f3d7be2e73..f85a357ac2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceCallLinkSyncJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceCallLinkSyncJob.kt @@ -34,7 +34,7 @@ class MultiDeviceCallLinkSyncJob private constructor( .build(), CallLinkUpdate( rootKey = credentials.linkKeyBytes.toByteString(), - adminPassKey = credentials.adminPassBytes!!.toByteString() + adminPasskey = credentials.adminPassBytes!!.toByteString() ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactSyncJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactSyncJob.kt index e3f2ed09a4..75e919d5d0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactSyncJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactSyncJob.kt @@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.jobs import org.signal.core.util.isAbsent import org.signal.core.util.logging.Log import org.signal.libsignal.protocol.InvalidMessageException -import org.thoughtcrime.securesms.database.IdentityTable.VerifiedStatus import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.jobmanager.Job @@ -16,7 +15,6 @@ import org.thoughtcrime.securesms.recipients.Recipient import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer import org.whispersystems.signalservice.api.messages.multidevice.DeviceContact import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsInputStream -import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage.VerifiedState import org.whispersystems.signalservice.api.push.SignalServiceAddress import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException import org.whispersystems.signalservice.api.util.AttachmentPointerUtil @@ -103,42 +101,6 @@ class MultiDeviceContactSyncJob(parameters: Parameters, private val attachmentPo } } - if (contact.profileKey.isPresent) { - val profileKey = contact.profileKey.get() - recipients.setProfileKey(recipient.id, profileKey) - } - - if (contact.verified.isPresent) { - val verifiedStatus: VerifiedStatus = when (contact.verified.get().verified) { - VerifiedState.VERIFIED -> VerifiedStatus.VERIFIED - VerifiedState.UNVERIFIED -> VerifiedStatus.UNVERIFIED - else -> VerifiedStatus.DEFAULT - } - - if (recipient.serviceId.isPresent) { - AppDependencies.protocolStore.aci().identities().saveIdentityWithoutSideEffects( - recipient.id, - recipient.serviceId.get(), - contact.verified.get().identityKey, - verifiedStatus, - false, - contact.verified.get().timestamp, - true - ) - } else { - Log.w(TAG, "Missing serviceId for ${recipient.id} -- cannot save identity!") - } - } - - val threadRecord = threads.getThreadRecord(threads.getThreadIdFor(recipient.id)) - if (threadRecord != null && contact.isArchived != threadRecord.isArchived) { - if (contact.isArchived) { - threads.archiveConversation(threadRecord.threadId) - } else { - threads.unarchiveConversation(threadRecord.threadId) - } - } - if (contact.avatar.isPresent) { try { AvatarHelper.setSyncAvatar(context, recipient.id, contact.avatar.get().inputStream) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java index f1da62537c..c69797a181 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java @@ -157,8 +157,6 @@ public class MultiDeviceContactUpdateJob extends BaseJob { return; } - Optional identityRecord = AppDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipient.getId()); - Optional verifiedMessage = getVerifiedMessage(recipient, identityRecord); Map inboxPositions = SignalDatabase.threads().getInboxPositions(); Set archived = SignalDatabase.threads().getArchivedRecipients(); @@ -166,14 +164,10 @@ public class MultiDeviceContactUpdateJob extends BaseJob { recipient.getE164(), Optional.ofNullable(recipient.isGroup() || recipient.isSystemContact() ? recipient.getDisplayName(context) : null), getSystemAvatar(recipient.getContactUri()), - Optional.of(ChatColorsMapper.getMaterialColor(recipient.getChatColors()).serialize()), - verifiedMessage, - ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey()), recipient.getExpiresInSeconds() > 0 ? Optional.of(recipient.getExpiresInSeconds()) : Optional.empty(), Optional.of(recipient.getExpireTimerVersion()), - Optional.ofNullable(inboxPositions.get(recipientId)), - archived.contains(recipientId))); + Optional.ofNullable(inboxPositions.get(recipientId)))); out.close(); updateUri = writeDetails.getUri(); @@ -185,7 +179,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob { length, false); - } catch(InvalidNumberException | InterruptedException e) { + } catch(InterruptedException e) { Log.w(TAG, e); } finally { if (updateUri != null) { @@ -222,10 +216,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob { for (Recipient recipient : recipients) { Optional identity = AppDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipient.getId()); - Optional verified = getVerifiedMessage(recipient, identity); Optional name = Optional.ofNullable(recipient.isSystemContact() ? recipient.getDisplayName(context) : recipient.getGroupName(context)); - Optional profileKey = ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey()); - boolean blocked = recipient.isBlocked(); Optional expireTimer = recipient.getExpiresInSeconds() > 0 ? Optional.of(recipient.getExpiresInSeconds()) : Optional.empty(); Optional expireTimerVersion = Optional.of(recipient.getExpireTimerVersion()); Optional inboxPosition = Optional.ofNullable(inboxPositions.get(recipient.getId())); @@ -234,13 +225,9 @@ public class MultiDeviceContactUpdateJob extends BaseJob { recipient.getE164(), name, getSystemAvatar(recipient.getContactUri()), - Optional.of(ChatColorsMapper.getMaterialColor(recipient.getChatColors()).serialize()), - verified, - profileKey, expireTimer, expireTimerVersion, - inboxPosition, - archived.contains(recipient.getId()))); + inboxPosition)); } @@ -252,13 +239,9 @@ public class MultiDeviceContactUpdateJob extends BaseJob { Optional.of(SignalStore.account().getE164()), Optional.empty(), Optional.empty(), - Optional.of(ChatColorsMapper.getMaterialColor(self.getChatColors()).serialize()), - Optional.empty(), - ProfileKeyUtil.profileKeyOptionalOrThrow(self.getProfileKey()), self.getExpiresInSeconds() > 0 ? Optional.of(self.getExpiresInSeconds()) : Optional.empty(), Optional.of(self.getExpireTimerVersion()), - Optional.ofNullable(inboxPositions.get(self.getId())), - archived.contains(self.getId()))); + Optional.ofNullable(inboxPositions.get(self.getId())))); } out.close(); @@ -271,7 +254,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob { BlobProvider.getInstance().getStream(context, updateUri), length, true); - } catch(InvalidNumberException | InterruptedException e) { + } catch(InterruptedException e) { Log.w(TAG, e); } finally { if (updateUri != null) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceDeleteSyncJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceDeleteSyncJob.kt index e17efbeeea..0b4c8b35e4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceDeleteSyncJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceDeleteSyncJob.kt @@ -316,7 +316,7 @@ class MultiDeviceDeleteSyncJob private constructor( DeleteForMe.AttachmentDelete( conversation = conversation, targetMessage = targetMessage, - uuid = it.uuid, + clientUuid = it.uuid, fallbackDigest = it.digest, fallbackPlaintextHash = it.plaintextHash ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java index a53fa2640e..b5c277ee07 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java @@ -81,11 +81,7 @@ public class MultiDeviceProfileKeyUpdateJob extends BaseJob { Optional.empty(), Optional.empty(), Optional.empty(), - profileKey, - Optional.empty(), - Optional.empty(), - Optional.empty(), - false)); + Optional.empty())); out.close(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshCallLinkDetailsJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshCallLinkDetailsJob.kt index d0dc447ceb..8eee7c2186 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshCallLinkDetailsJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshCallLinkDetailsJob.kt @@ -48,7 +48,7 @@ class RefreshCallLinkDetailsJob private constructor( val manager: SignalCallLinkManager = AppDependencies.signalCallManager.callLinkManager val credentials = CallLinkCredentials( linkKeyBytes = callLinkUpdate.rootKey!!.toByteArray(), - adminPassBytes = callLinkUpdate.adminPassKey?.toByteArray() + adminPassBytes = callLinkUpdate.adminPasskey?.toByteArray() ) when (val result = manager.readCallLink(credentials).safeBlockingGet()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageObserver.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageObserver.kt index 0e7eacd5b1..feda8e2072 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageObserver.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageObserver.kt @@ -274,7 +274,7 @@ class IncomingMessageObserver(private val context: Application, private val sign @VisibleForTesting fun processEnvelope(bufferedProtocolStore: BufferedProtocolStore, envelope: Envelope, serverDeliveredTimestamp: Long): List? { return when (envelope.type) { - Envelope.Type.RECEIPT -> { + Envelope.Type.SERVER_DELIVERY_RECEIPT -> { processReceipt(envelope) null } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptor.kt index 03ed4b3ea6..9a88c70833 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptor.kt @@ -197,9 +197,9 @@ object MessageDecryptor { } // TODO We can move this to the "message processing" stage once we give it access to the envelope. But for now it'll stay here. - if (envelope.reportingToken != null && envelope.reportingToken!!.size > 0) { + if (envelope.report_spam_token != null && envelope.report_spam_token!!.size > 0) { val sender = RecipientId.from(cipherResult.metadata.sourceServiceId) - SignalDatabase.recipients.setReportingToken(sender, envelope.reportingToken!!.toByteArray()) + SignalDatabase.recipients.setReportingToken(sender, envelope.report_spam_token!!.toByteArray()) } Result.Success(envelope, serverDeliveredTimestamp, cipherResult.content, cipherResult.metadata, followUpOperations.toUnmodifiableList()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt index a107e268c6..8c507470ac 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt @@ -157,7 +157,6 @@ object SyncMessageProcessor { syncMessage.fetchLatest?.type != null -> handleSynchronizeFetchMessage(syncMessage.fetchLatest!!.type!!, envelope.timestamp!!) syncMessage.messageRequestResponse != null -> handleSynchronizeMessageRequestResponse(syncMessage.messageRequestResponse!!, envelope.timestamp!!) syncMessage.outgoingPayment != null -> handleSynchronizeOutgoingPayment(syncMessage.outgoingPayment!!, envelope.timestamp!!) - syncMessage.keys?.storageService != null -> handleSynchronizeKeys(syncMessage.keys!!.storageService!!, envelope.timestamp!!) syncMessage.contacts != null -> handleSynchronizeContacts(syncMessage.contacts!!, envelope.timestamp!!) syncMessage.callEvent != null -> handleSynchronizeCallEvent(syncMessage.callEvent!!, envelope.timestamp!!) syncMessage.callLinkUpdate != null -> handleSynchronizeCallLink(syncMessage.callLinkUpdate!!, envelope.timestamp!!) @@ -262,7 +261,7 @@ object SyncMessageProcessor { private fun handlePniIdentityKeys(envelope: Envelope, sent: Sent) { for (status in sent.unidentifiedStatus) { - if (status.destinationIdentityKey == null) { + if (status.destinationPniIdentityKey == null) { continue } @@ -280,7 +279,7 @@ object SyncMessageProcessor { try { log(envelope.timestamp!!, "Saving identity from sent transcript for $pni") - val identityKey = IdentityKey(status.destinationIdentityKey!!.toByteArray()) + val identityKey = IdentityKey(status.destinationPniIdentityKey!!.toByteArray()) AppDependencies.protocolStore.aci().identities().saveIdentity(address, identityKey) } catch (e: InvalidKeyException) { warn(envelope.timestamp!!, "Failed to deserialize identity key for $pni") @@ -1262,7 +1261,7 @@ object SyncMessageProcessor { } private fun handleSynchronizeCallEvent(callEvent: SyncMessage.CallEvent, envelopeTimestamp: Long) { - if (callEvent.id == null) { + if (callEvent.callId == null) { log(envelopeTimestamp, "Synchronize call event missing call id, ignoring. type: ${callEvent.type}") return } @@ -1346,7 +1345,7 @@ object SyncMessageProcessor { roomId, CallLinkCredentials( callLinkUpdate.rootKey!!.toByteArray(), - callLinkUpdate.adminPassKey?.toByteArray() + callLinkUpdate.adminPasskey?.toByteArray() ) ) } else { @@ -1357,7 +1356,7 @@ object SyncMessageProcessor { roomId = roomId, credentials = CallLinkCredentials( linkKeyBytes = callLinkRootKey.keyBytes, - adminPassBytes = callLinkUpdate.adminPassKey?.toByteArray() + adminPassBytes = callLinkUpdate.adminPasskey?.toByteArray() ), state = SignalCallLinkState(), deletionTimestamp = 0L @@ -1371,7 +1370,7 @@ object SyncMessageProcessor { } private fun handleSynchronizeOneToOneCallEvent(callEvent: SyncMessage.CallEvent, envelopeTimestamp: Long) { - val callId: Long = callEvent.id!! + val callId: Long = callEvent.callId!! val timestamp: Long = callEvent.timestamp ?: 0L val type: CallTable.Type? = CallTable.Type.from(callEvent.type) val direction: CallTable.Direction? = CallTable.Direction.from(callEvent.direction) @@ -1410,7 +1409,7 @@ object SyncMessageProcessor { @Throws(BadGroupIdException::class) private fun handleSynchronizeGroupOrAdHocCallEvent(callEvent: SyncMessage.CallEvent, envelopeTimestamp: Long) { - val callId: Long = callEvent.id!! + val callId: Long = callEvent.callId!! val timestamp: Long = callEvent.timestamp ?: 0L val type: CallTable.Type? = CallTable.Type.from(callEvent.type) val direction: CallTable.Direction? = CallTable.Direction.from(callEvent.direction) @@ -1491,11 +1490,11 @@ object SyncMessageProcessor { } } else { when (event) { - CallTable.Event.DELETE -> SignalDatabase.calls.insertDeletedCallFromSyncEvent(callEvent.id!!, recipient.id, type, direction, timestamp) - CallTable.Event.ACCEPTED -> SignalDatabase.calls.insertAcceptedGroupCall(callEvent.id!!, recipient.id, direction, timestamp) + CallTable.Event.DELETE -> SignalDatabase.calls.insertDeletedCallFromSyncEvent(callEvent.callId!!, recipient.id, type, direction, timestamp) + CallTable.Event.ACCEPTED -> SignalDatabase.calls.insertAcceptedGroupCall(callEvent.callId!!, recipient.id, direction, timestamp) CallTable.Event.NOT_ACCEPTED -> { if (callEvent.direction == SyncMessage.CallEvent.Direction.INCOMING) { - SignalDatabase.calls.insertDeclinedGroupCall(callEvent.id!!, recipient.id, timestamp) + SignalDatabase.calls.insertDeclinedGroupCall(callEvent.callId!!, recipient.id, timestamp) } else { warn(envelopeTimestamp, "Invalid direction OUTGOING for event NOT_ACCEPTED for non-existing call") } @@ -1677,7 +1676,7 @@ object SyncMessageProcessor { } private fun SyncMessage.DeleteForMe.AttachmentDelete.toSyncAttachmentId(syncMessageId: MessageTable.SyncMessageId?, envelopeTimestamp: Long): AttachmentTable.SyncAttachmentId? { - val uuid = UuidUtil.fromByteStringOrNull(uuid) + val uuid = UuidUtil.fromByteStringOrNull(clientUuid) val digest = fallbackDigest?.toByteArray() val plaintextHash = fallbackPlaintextHash?.let { Base64.encodeWithPadding(it.toByteArray()) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java b/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java index ae252aed23..2526ed762c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java @@ -61,12 +61,6 @@ public final class MessageGroupContext { } } - public MessageGroupContext(@NonNull GroupContext group) { - this.groupV1 = new GroupV1Properties(group); - this.groupV2 = null; - this.group = groupV1; - } - public MessageGroupContext(@NonNull DecryptedGroupV2Context group) { this.groupV1 = null; this.groupV2 = new GroupV2Properties(group); diff --git a/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinPublicAddressProfileUtil.java b/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinPublicAddressProfileUtil.java index d34970a3d7..7dbd77cb1c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinPublicAddressProfileUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/payments/MobileCoinPublicAddressProfileUtil.java @@ -21,10 +21,10 @@ public final class MobileCoinPublicAddressProfileUtil { byte[] signature = identityKeyPair.getPrivateKey().calculateSignature(publicAddressBytes); return new PaymentAddress.Builder() - .mobileCoinAddress(new PaymentAddress.MobileCoinAddress.Builder() - .address(ByteString.of(publicAddressBytes)) - .signature(ByteString.of(signature)) - .build()) + .mobileCoin(new PaymentAddress.MobileCoin.Builder() + .publicAddress(ByteString.of(publicAddressBytes)) + .signature(ByteString.of(signature)) + .build()) .build(); } @@ -37,16 +37,16 @@ public final class MobileCoinPublicAddressProfileUtil { @NonNull IdentityKey identityKey) throws PaymentsAddressException { - if (paymentAddress.mobileCoinAddress == null) { + if (paymentAddress.mobileCoin == null) { throw new PaymentsAddressException(PaymentsAddressException.Code.NO_ADDRESS); } - if (paymentAddress.mobileCoinAddress.address == null || paymentAddress.mobileCoinAddress.signature == null) { + if (paymentAddress.mobileCoin.publicAddress == null || paymentAddress.mobileCoin.signature == null) { throw new PaymentsAddressException(PaymentsAddressException.Code.INVALID_ADDRESS_SIGNATURE); } - byte[] bytes = paymentAddress.mobileCoinAddress.address.toByteArray(); - byte[] signature = paymentAddress.mobileCoinAddress.signature.toByteArray(); + byte[] bytes = paymentAddress.mobileCoin.publicAddress.toByteArray(); + byte[] signature = paymentAddress.mobileCoin.signature.toByteArray(); if (signature.length != 64 || !identityKey.getPublicKey().verifySignature(bytes, signature)) { throw new PaymentsAddressException(PaymentsAddressException.Code.INVALID_ADDRESS_SIGNATURE); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallEventSyncMessageUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallEventSyncMessageUtil.kt index da26e59e06..4a946d870c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallEventSyncMessageUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallEventSyncMessageUtil.kt @@ -83,7 +83,7 @@ object CallEventSyncMessageUtil { return CallEvent( conversationId = conversationId, - id = callId, + callId = callId, timestamp = timestamp, type = callType, direction = if (isOutgoing) CallEvent.Direction.OUTGOING else CallEvent.Direction.INCOMING, diff --git a/app/src/main/protowire/Database.proto b/app/src/main/protowire/Database.proto index 61f91fe3d1..c3fa672681 100644 --- a/app/src/main/protowire/Database.proto +++ b/app/src/main/protowire/Database.proto @@ -12,6 +12,7 @@ option java_package = "org.thoughtcrime.securesms.database.model.database option java_multiple_files = true; import Backup.proto; +import SignalServiceLegacy.proto; // DEPRECATED -- only here for database migrations message ReactionList { diff --git a/app/src/test/java/org/thoughtcrime/securesms/payments/MobileCoinPublicAddressProfileUtilTest.kt b/app/src/test/java/org/thoughtcrime/securesms/payments/MobileCoinPublicAddressProfileUtilTest.kt index f201c1e595..d3f8fb077a 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/payments/MobileCoinPublicAddressProfileUtilTest.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/payments/MobileCoinPublicAddressProfileUtilTest.kt @@ -46,12 +46,12 @@ class MobileCoinPublicAddressProfileUtilTest { val identityKeyPair = IdentityKeyUtil.generateIdentityKeyPair() val address = Util.getSecretBytes(100) val signedPaymentAddress = MobileCoinPublicAddressProfileUtil.signPaymentsAddress(address, identityKeyPair) - val mobileCoinAddress = signedPaymentAddress.mobileCoinAddress!! + val mobileCoinAddress = signedPaymentAddress.mobileCoin!! val signature = mobileCoinAddress.signature!!.toByteArray() signature[0] = (signature[0].toInt() xor 0x01).toByte() val tamperedSignature = signedPaymentAddress.newBuilder() - .mobileCoinAddress( + .mobileCoin( mobileCoinAddress .newBuilder() .signature(ByteString.of(*signature)) @@ -69,15 +69,15 @@ class MobileCoinPublicAddressProfileUtilTest { val identityKeyPair = IdentityKeyUtil.generateIdentityKeyPair() val addressBytes = Util.getSecretBytes(100) val signedPaymentAddress = MobileCoinPublicAddressProfileUtil.signPaymentsAddress(addressBytes, identityKeyPair) - val mobileCoinAddress = signedPaymentAddress.mobileCoinAddress!! + val mobileCoinAddress = signedPaymentAddress.mobileCoin!! - val address = mobileCoinAddress.address!!.toByteArray() + val address = mobileCoinAddress.publicAddress!!.toByteArray() address[0] = (address[0].toInt() xor 0x01).toByte() val tamperedAddress = signedPaymentAddress.newBuilder() - .mobileCoinAddress( + .mobileCoin( mobileCoinAddress .newBuilder() - .address(ByteString.of(*address)) + .publicAddress(ByteString.of(*address)) .build() ) .build() @@ -94,8 +94,8 @@ class MobileCoinPublicAddressProfileUtilTest { val signedPaymentAddress = MobileCoinPublicAddressProfileUtil.signPaymentsAddress(address, identityKeyPair) val removedSignature = signedPaymentAddress.newBuilder() - .mobileCoinAddress( - signedPaymentAddress.mobileCoinAddress!! + .mobileCoin( + signedPaymentAddress.mobileCoin!! .newBuilder() .signature(null) .build() @@ -114,10 +114,10 @@ class MobileCoinPublicAddressProfileUtilTest { val signedPaymentAddress = MobileCoinPublicAddressProfileUtil.signPaymentsAddress(address, identityKeyPair) val removedAddress = signedPaymentAddress.newBuilder() - .mobileCoinAddress( - signedPaymentAddress.mobileCoinAddress!! + .mobileCoin( + signedPaymentAddress.mobileCoin!! .newBuilder() - .address(null) + .publicAddress(null) .build() ) .build() diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 38b45266a6..dcf75e17e1 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -1391,7 +1391,7 @@ public class SignalServiceMessageSender { unidentifiedDeliveryStatuses.add(new SyncMessage.Sent.UnidentifiedDeliveryStatus.Builder() .destinationServiceId(result.getAddress().getServiceId().toString()) .unidentified(false) - .destinationIdentityKey(identity) + .destinationPniIdentityKey(identity) .build()); } } @@ -1665,10 +1665,6 @@ public class SignalServiceMessageSender { SyncMessage.Builder syncMessage = createSyncMessageBuilder(); SyncMessage.Keys.Builder builder = new SyncMessage.Keys.Builder(); - if (keysMessage.getStorageService() != null) { - builder.storageService(ByteString.of(keysMessage.getStorageService().serialize())); - } - if (keysMessage.getMaster() != null) { builder.master(ByteString.of(keysMessage.getMaster().serialize())); } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContact.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContact.java index 638cf7c755..82b44e590e 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContact.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContact.java @@ -17,25 +17,17 @@ public class DeviceContact { private final Optional e164; private final Optional name; private final Optional avatar; - private final Optional color; - private final Optional verified; - private final Optional profileKey; private final Optional expirationTimer; private final Optional expirationTimerVersion; private final Optional inboxPosition; - private final boolean archived; public DeviceContact(Optional aci, Optional e164, Optional name, Optional avatar, - Optional color, - Optional verified, - Optional profileKey, Optional expirationTimer, Optional expirationTimerVersion, - Optional inboxPosition, - boolean archived) + Optional inboxPosition) { if (aci.isEmpty() && e164.isEmpty()) { throw new IllegalArgumentException("Must have either ACI or E164"); @@ -45,13 +37,9 @@ public class DeviceContact { this.e164 = e164; this.name = name; this.avatar = avatar; - this.color = color; - this.verified = verified; - this.profileKey = profileKey; this.expirationTimer = expirationTimer; this.expirationTimerVersion = expirationTimerVersion; this.inboxPosition = inboxPosition; - this.archived = archived; } public Optional getAvatar() { @@ -70,18 +58,6 @@ public class DeviceContact { return e164; } - public Optional getColor() { - return color; - } - - public Optional getVerified() { - return verified; - } - - public Optional getProfileKey() { - return profileKey; - } - public Optional getExpirationTimer() { return expirationTimer; } @@ -93,8 +69,4 @@ public class DeviceContact { public Optional getInboxPosition() { return inboxPosition; } - - public boolean isArchived() { - return archived; - } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStream.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStream.java index f5df38d1b9..462654b8d7 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStream.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStream.java @@ -50,13 +50,9 @@ public class DeviceContactsInputStream extends ChunkedInputStream { Optional e164 = Optional.ofNullable(details.number); Optional name = Optional.ofNullable(details.name); Optional avatar = Optional.empty(); - Optional color = details.color != null ? Optional.of(details.color) : Optional.empty(); - Optional verified = Optional.empty(); - Optional profileKey = Optional.empty(); Optional expireTimer = Optional.empty(); Optional expireTimerVersion = Optional.empty(); Optional inboxPosition = Optional.empty(); - boolean archived = false; if (details.avatar != null && details.avatar.length != null) { long avatarLength = details.avatar.length; @@ -66,39 +62,6 @@ public class DeviceContactsInputStream extends ChunkedInputStream { avatar = Optional.of(new DeviceContactAvatar(avatarStream, avatarLength, avatarContentType)); } - if (details.verified != null) { - try { - if (!SignalServiceAddress.isValidAddress(details.verified.destinationAci, null)) { - throw new InvalidMessageException("Missing Verified address!"); - } - - IdentityKey identityKey = new IdentityKey(details.verified.identityKey.toByteArray(), 0); - SignalServiceAddress destination = new SignalServiceAddress(ServiceId.parseOrThrow(details.verified.destinationAci)); - - VerifiedMessage.VerifiedState state; - - switch (details.verified.state) { - case VERIFIED: state = VerifiedMessage.VerifiedState.VERIFIED; break; - case UNVERIFIED:state = VerifiedMessage.VerifiedState.UNVERIFIED; break; - case DEFAULT: state = VerifiedMessage.VerifiedState.DEFAULT; break; - default: throw new InvalidMessageException("Unknown state: " + details.verified.state); - } - - verified = Optional.of(new VerifiedMessage(destination, identityKey, state, System.currentTimeMillis())); - } catch (InvalidKeyException | InvalidMessageException e) { - Log.w(TAG, e); - verified = Optional.empty(); - } - } - - if (details.profileKey != null) { - try { - profileKey = Optional.ofNullable(new ProfileKey(details.profileKey.toByteArray())); - } catch (InvalidInputException e) { - Log.w(TAG, "Invalid profile key ignored", e); - } - } - if (details.expireTimer != null && details.expireTimer > 0) { expireTimer = Optional.of(details.expireTimer); } @@ -111,9 +74,7 @@ public class DeviceContactsInputStream extends ChunkedInputStream { inboxPosition = Optional.of(details.inboxPosition); } - archived = details.archived; - - return new DeviceContact(aci, e164, name, avatar, color, verified, profileKey, expireTimer, expireTimerVersion, inboxPosition, archived); + return new DeviceContact(aci, e164, name, avatar, expireTimer, expireTimerVersion, inboxPosition); } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsOutputStream.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsOutputStream.java index 5e2d4bf6ea..03d5091788 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsOutputStream.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsOutputStream.java @@ -57,34 +57,6 @@ public class DeviceContactsOutputStream extends ChunkedOutputStream { contactDetails.avatar(avatarBuilder.build()); } - if (contact.getColor().isPresent()) { - contactDetails.color(contact.getColor().get()); - } - - if (contact.getVerified().isPresent()) { - Verified.State state; - - switch (contact.getVerified().get().getVerified()) { - case VERIFIED: - state = Verified.State.VERIFIED; break; - case UNVERIFIED: - state = Verified.State.UNVERIFIED; break; - default: - state = Verified.State.DEFAULT; break; - } - - Verified.Builder verifiedBuilder = new Verified.Builder() - .identityKey(ByteString.of(contact.getVerified().get().getIdentityKey().serialize())) - .destinationAci(contact.getVerified().get().getDestination().getServiceId().toString()) - .state(state); - - contactDetails.verified(verifiedBuilder.build()); - } - - if (contact.getProfileKey().isPresent()) { - contactDetails.profileKey(ByteString.of(contact.getProfileKey().get().serialize())); - } - if (contact.getExpirationTimer().isPresent()) { contactDetails.expireTimer(contact.getExpirationTimer().get()); } @@ -93,8 +65,6 @@ public class DeviceContactsOutputStream extends ChunkedOutputStream { contactDetails.inboxPosition(contact.getInboxPosition().get()); } - contactDetails.archived(contact.isArchived()); - byte[] serializedContactDetails = contactDetails.build().encode(); writeVarint32(serializedContactDetails.length); diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/RequestMessage.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/RequestMessage.java index 82e684039c..47bb739e6c 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/RequestMessage.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/RequestMessage.java @@ -40,11 +40,7 @@ public class RequestMessage { return request.type == Request.Type.KEYS; } - public boolean isPniIdentityRequest() { - return request.type == Request.Type.PNI_IDENTITY; - } - public boolean isUrgent() { - return isContactsRequest() || isKeysRequest() || isPniIdentityRequest(); + return isContactsRequest() || isKeysRequest(); } } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/util/AttachmentPointerUtil.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/util/AttachmentPointerUtil.java index dd78a4fae8..ae3b1ac194 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/util/AttachmentPointerUtil.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/util/AttachmentPointerUtil.java @@ -28,7 +28,7 @@ public final class AttachmentPointerUtil { pointer.height != null ? pointer.height : 0, pointer.digest != null ? Optional.of(pointer.digest.toByteArray()) : Optional.empty(), pointer.incrementalMac != null ? Optional.of(pointer.incrementalMac.toByteArray()) : Optional.empty(), - pointer.incrementalMacChunkSize != null ? pointer.incrementalMacChunkSize : 0, + pointer.chunkSize != null ? pointer.chunkSize : 0, pointer.fileName != null ? Optional.of(pointer.fileName) : Optional.empty(), ((pointer.flags != null ? pointer.flags : 0) & FlagUtil.toBinaryFlag(AttachmentPointer.Flags.VOICE_MESSAGE.getValue())) != 0, ((pointer.flags != null ? pointer.flags : 0) & FlagUtil.toBinaryFlag(AttachmentPointer.Flags.BORDERLESS.getValue())) != 0, @@ -36,7 +36,7 @@ public final class AttachmentPointerUtil { pointer.caption != null ? Optional.of(pointer.caption) : Optional.empty(), pointer.blurHash != null ? Optional.of(pointer.blurHash) : Optional.empty(), pointer.uploadTimestamp != null ? pointer.uploadTimestamp : 0, - UuidUtil.fromByteStringOrNull(pointer.uuid)); + UuidUtil.fromByteStringOrNull(pointer.clientUuid)); } public static AttachmentPointer createAttachmentPointer(SignalServiceAttachmentPointer attachment) { @@ -53,7 +53,7 @@ public final class AttachmentPointerUtil { } if (attachment.getIncrementalMacChunkSize() > 0) { - builder.incrementalMacChunkSize(attachment.getIncrementalMacChunkSize()); + builder.chunkSize(attachment.getIncrementalMacChunkSize()); } if (attachment.getRemoteId() instanceof SignalServiceAttachmentRemoteId.V2) { @@ -105,7 +105,7 @@ public final class AttachmentPointerUtil { } if (attachment.getUuid() != null) { - builder.uuid(UuidUtil.toByteString(attachment.getUuid())); + builder.clientUuid(UuidUtil.toByteString(attachment.getUuid())); } return builder.build(); diff --git a/libsignal-service/src/main/protowire/SignalService.proto b/libsignal-service/src/main/protowire/SignalService.proto index dc3166c428..843af2d902 100644 --- a/libsignal-service/src/main/protowire/SignalService.proto +++ b/libsignal-service/src/main/protowire/SignalService.proto @@ -1,86 +1,87 @@ -/** - * Copyright (C) 2014-2016 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. +/* + * Copyright 2020-2022 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only */ + syntax = "proto2"; package signalservice; -option java_package = "org.whispersystems.signalservice.internal.push"; +option java_package = "org.whispersystems.signalservice.internal.push"; option java_outer_classname = "SignalServiceProtos"; message Envelope { enum Type { - UNKNOWN = 0; - CIPHERTEXT = 1; - KEY_EXCHANGE = 2; - PREKEY_BUNDLE = 3; - RECEIPT = 5; - UNIDENTIFIED_SENDER = 6; - reserved 7; // SENDERKEY_MESSAGE - PLAINTEXT_CONTENT = 8; + UNKNOWN = 0; + CIPHERTEXT = 1; // content => (version byte | SignalMessage{Content}) + reserved 2; + reserved "KEY_EXCHANGE"; + PREKEY_BUNDLE = 3; // content => (version byte | PreKeySignalMessage{Content}) + SERVER_DELIVERY_RECEIPT = 5; // legacyMessage => [] AND content => [] + UNIDENTIFIED_SENDER = 6; // legacyMessage => [] AND content => ((version byte | UnidentifiedSenderMessage) OR (version byte | Multi-Recipient Sealed Sender Format)) + SENDERKEY_MESSAGE = 7; // legacyMessage => [] AND content => (version byte | SenderKeyMessage) + PLAINTEXT_CONTENT = 8; // legacyMessage => [] AND content => (marker byte | Content) } - optional Type type = 1; - reserved /*sourceE164*/ 2; - optional string sourceServiceId = 11; - optional uint32 sourceDevice = 7; + optional Type type = 1; + reserved 2; // formerly optional string sourceE164 = 2; + optional string sourceServiceId = 11; + optional uint32 sourceDevice = 7; optional string destinationServiceId = 13; - reserved /*relay*/ 3; - optional uint64 timestamp = 5; - reserved /*legacyMessage*/ 6; - optional bytes content = 8; // Contains an encrypted Content - optional string serverGuid = 9; - optional uint64 serverTimestamp = 10; - optional bool urgent = 14 [default = true]; - reserved /*updatedPni*/ 15; // Not used presently, may be used in the future - optional bool story = 16; - optional bytes reportingToken = 17; - reserved 18; // internal server use - // NEXT ID: 19 + reserved 3; // formerly optional string relay = 3; + optional uint64 timestamp = 5; + reserved 6; // formerly optional bytes legacyMessage = 6; // Contains an encrypted DataMessage; this field could have been set historically for type 1 or 3 messages; no longer in use + optional bytes content = 8; // Contains an encrypted Content + optional string serverGuid = 9; + optional uint64 serverTimestamp = 10; + optional bool ephemeral = 12; // indicates that the message should not be persisted if the recipient is offline + optional bool urgent = 14 [default = true]; // indicates that the content is considered timely by the sender; defaults to true so senders have to opt-out to say something isn't time critical + optional string updatedPni = 15; // for number-change synchronization messages, provides the new server-assigned phone number identifier associated with the changed number + optional bool story = 16; // indicates that the content is a story. + optional bytes report_spam_token = 17; // token sent when reporting spam + reserved 18; // internal server use + // next: 19 } message Content { - optional DataMessage dataMessage = 1; - optional SyncMessage syncMessage = 2; - optional CallMessage callMessage = 3; - optional NullMessage nullMessage = 4; - optional ReceiptMessage receiptMessage = 5; - optional TypingMessage typingMessage = 6; - optional bytes senderKeyDistributionMessage = 7; - optional bytes decryptionErrorMessage = 8; - optional StoryMessage storyMessage = 9; - optional PniSignatureMessage pniSignatureMessage = 10; - optional EditMessage editMessage = 11; + optional DataMessage dataMessage = 1; + optional SyncMessage syncMessage = 2; + optional CallMessage callMessage = 3; + optional NullMessage nullMessage = 4; + optional ReceiptMessage receiptMessage = 5; + optional TypingMessage typingMessage = 6; + optional bytes /* SenderKeyDistributionMessage */ senderKeyDistributionMessage = 7; + optional bytes /* DecryptionErrorMessage */ decryptionErrorMessage = 8; + optional StoryMessage storyMessage = 9; + optional PniSignatureMessage pniSignatureMessage = 10; + optional EditMessage editMessage = 11; } message CallMessage { message Offer { enum Type { - OFFER_AUDIO_CALL = 0; - OFFER_VIDEO_CALL = 1; - reserved /* OFFER_NEED_PERMISSION */ 2; // removed + OFFER_AUDIO_CALL = 0; + OFFER_VIDEO_CALL = 1; + reserved /* OFFER_NEED_PERMISSION */ 2; // removed } - - optional uint64 id = 1; - reserved /* sdp */ 2; - optional Type type = 3; - optional bytes opaque = 4; + optional uint64 id = 1; + reserved /* sdp */ 2; + optional Type type = 3; + optional bytes opaque = 4; } message Answer { - optional uint64 id = 1; - reserved /* sdp */ 2; - optional bytes opaque = 3; + optional uint64 id = 1; + reserved /* sdp */ 2; + optional bytes opaque = 3; } message IceUpdate { - optional uint64 id = 1; - reserved /* mid */ 2; - reserved /* line */ 3; - reserved /* sdp */ 4; - optional bytes opaque = 5; + optional uint64 id = 1; + reserved /* mid */ 2; + reserved /* line */ 3; + reserved /* sdp */ 4; + optional bytes opaque = 5; } message Busy { @@ -89,188 +90,50 @@ message CallMessage { message Hangup { enum Type { - HANGUP_NORMAL = 0; - HANGUP_ACCEPTED = 1; - HANGUP_DECLINED = 2; - HANGUP_BUSY = 3; + HANGUP_NORMAL = 0; + HANGUP_ACCEPTED = 1; + HANGUP_DECLINED = 2; + HANGUP_BUSY = 3; HANGUP_NEED_PERMISSION = 4; } - - optional uint64 id = 1; - optional Type type = 2; + optional uint64 id = 1; + optional Type type = 2; optional uint32 deviceId = 3; } message Opaque { enum Urgency { - DROPPABLE = 0; + DROPPABLE = 0; HANDLE_IMMEDIATELY = 1; } - - optional bytes data = 1; - optional Urgency urgency = 2; + optional bytes data = 1; + optional Urgency urgency = 2; // If missing, treat as DROPPABLE. } - optional Offer offer = 1; - optional Answer answer = 2; - repeated IceUpdate iceUpdate = 3; - reserved /* legacyHangup */ 4; - optional Busy busy = 5; - reserved /* profileKey */ 6; - optional Hangup hangup = 7; - reserved /* multiRing */ 8; - optional uint32 destinationDeviceId = 9; - optional Opaque opaque = 10; -} - -message BodyRange { - enum Style { - NONE = 0; - BOLD = 1; - ITALIC = 2; - SPOILER = 3; - STRIKETHROUGH = 4; - MONOSPACE = 5; - } - - optional uint32 start = 1; - optional uint32 length = 2; - - oneof associatedValue { - string mentionAci = 3; - Style style = 4; - } + optional Offer offer = 1; + optional Answer answer = 2; + repeated IceUpdate iceUpdate = 3; + reserved /* legacyHangup */ 4; + optional Busy busy = 5; + reserved /* profileKey */ 6; + optional Hangup hangup = 7; + reserved /* multiRing */ 8; + optional uint32 destinationDeviceId = 9; + optional Opaque opaque = 10; } message DataMessage { enum Flags { - END_SESSION = 1; + END_SESSION = 1; EXPIRATION_TIMER_UPDATE = 2; - PROFILE_KEY_UPDATE = 4; - } - - message Quote { - enum Type { - NORMAL = 0; - GIFT_BADGE = 1; - } - - message QuotedAttachment { - optional string contentType = 1; - optional string fileName = 2; - optional AttachmentPointer thumbnail = 3; - } - - optional uint64 id = 1; - reserved /*authorE164*/ 2; - optional string authorAci = 5; - optional string text = 3; - repeated QuotedAttachment attachments = 4; - repeated BodyRange bodyRanges = 6; - optional Type type = 7; - } - - message Contact { - message Name { - optional string givenName = 1; - optional string familyName = 2; - optional string prefix = 3; - optional string suffix = 4; - optional string middleName = 5; - reserved /*displayName*/ 6; - optional string nickname = 7; - } - - message Phone { - enum Type { - HOME = 1; - MOBILE = 2; - WORK = 3; - CUSTOM = 4; - } - - optional string value = 1; - optional Type type = 2; - optional string label = 3; - } - - message Email { - enum Type { - HOME = 1; - MOBILE = 2; - WORK = 3; - CUSTOM = 4; - } - - optional string value = 1; - optional Type type = 2; - optional string label = 3; - } - - message PostalAddress { - enum Type { - HOME = 1; - WORK = 2; - CUSTOM = 3; - } - - optional Type type = 1; - optional string label = 2; - optional string street = 3; - optional string pobox = 4; - optional string neighborhood = 5; - optional string city = 6; - optional string region = 7; - optional string postcode = 8; - optional string country = 9; - } - - message Avatar { - optional AttachmentPointer avatar = 1; - optional bool isProfile = 2; - } - - optional Name name = 1; - repeated Phone number = 3; - repeated Email email = 4; - repeated PostalAddress address = 5; - optional Avatar avatar = 6; - optional string organization = 7; - } - - message Sticker { - optional bytes packId = 1; - optional bytes packKey = 2; - optional uint32 stickerId = 3; - optional AttachmentPointer data = 4; - optional string emoji = 5; - } - - message Reaction { - optional string emoji = 1; - optional bool remove = 2; - reserved /*targetAuthorE164*/ 3; - optional string targetAuthorAci = 4; - optional uint64 targetSentTimestamp = 5; - } - - message Delete { - optional uint64 targetSentTimestamp = 1; - } - - message GroupCallUpdate { - optional string eraId = 1; - } - - message StoryContext { - optional string authorAci = 1; - optional uint64 sentTimestamp = 2; + PROFILE_KEY_UPDATE = 4; + FORWARD = 8; } message Payment { message Amount { message MobileCoin { - optional uint64 picoMob = 1; + optional uint64 picoMob = 1; // 1,000,000,000,000 picoMob per Mob } oneof Amount { @@ -287,13 +150,14 @@ message DataMessage { MobileCoin mobileCoin = 1; } + // Optional, Refers to the PaymentRequest message, if any. optional string note = 2; reserved /*requestId*/ 1003; } message Activation { enum Type { - REQUEST = 0; + REQUEST = 0; ACTIVATED = 1; } @@ -302,53 +166,172 @@ message DataMessage { oneof Item { Notification notification = 1; - Activation activation = 2; + Activation activation = 2; } - reserved /*request*/ 1002; + reserved /*request*/ 1002; reserved /*cancellation*/ 1003; } + message Quote { + enum Type { + NORMAL = 0; + GIFT_BADGE = 1; + } + + message QuotedAttachment { + optional string contentType = 1; + optional string fileName = 2; + optional AttachmentPointer thumbnail = 3; + } + + optional uint64 id = 1; + reserved /*authorE164*/ 2; + optional string authorAci = 5; + optional string text = 3; + repeated QuotedAttachment attachments = 4; + repeated BodyRange bodyRanges = 6; + optional Type type = 7; + } + + message Contact { + message Name { + optional string givenName = 1; + optional string familyName = 2; + optional string prefix = 3; + optional string suffix = 4; + optional string middleName = 5; + reserved /*displayName*/ 6; + optional string nickname = 7; + } + + message Phone { + enum Type { + HOME = 1; + MOBILE = 2; + WORK = 3; + CUSTOM = 4; + } + + optional string value = 1; + optional Type type = 2; + optional string label = 3; + } + + message Email { + enum Type { + HOME = 1; + MOBILE = 2; + WORK = 3; + CUSTOM = 4; + } + + optional string value = 1; + optional Type type = 2; + optional string label = 3; + } + + message PostalAddress { + enum Type { + HOME = 1; + WORK = 2; + CUSTOM = 3; + } + + optional Type type = 1; + optional string label = 2; + optional string street = 3; + optional string pobox = 4; + optional string neighborhood = 5; + optional string city = 6; + optional string region = 7; + optional string postcode = 8; + optional string country = 9; + } + + message Avatar { + optional AttachmentPointer avatar = 1; + optional bool isProfile = 2; + } + + optional Name name = 1; + repeated Phone number = 3; + repeated Email email = 4; + repeated PostalAddress address = 5; + optional Avatar avatar = 6; + optional string organization = 7; + } + + message Sticker { + optional bytes packId = 1; + optional bytes packKey = 2; + optional uint32 stickerId = 3; + optional AttachmentPointer data = 4; + optional string emoji = 5; + } + + message Reaction { + optional string emoji = 1; + optional bool remove = 2; + reserved /* targetAuthorE164 */ 3; + optional string targetAuthorAci = 4; + optional uint64 targetSentTimestamp = 5; + } + + message Delete { + optional uint64 targetSentTimestamp = 1; + } + + message GroupCallUpdate { + optional string eraId = 1; + } + + message StoryContext { + optional string authorAci = 1; + optional uint64 sentTimestamp = 2; + } + + enum ProtocolVersion { + option allow_alias = true; + + INITIAL = 0; + MESSAGE_TIMERS = 1; + VIEW_ONCE = 2; + VIEW_ONCE_VIDEO = 3; + REACTIONS = 4; + CDN_SELECTOR_ATTACHMENTS = 5; + MENTIONS = 6; + PAYMENTS = 7; + CURRENT = 7; + } + message GiftBadge { optional bytes receiptCredentialPresentation = 1; } - enum ProtocolVersion { - option allow_alias = true; - - INITIAL = 0; - MESSAGE_TIMERS = 1; - VIEW_ONCE = 2; - VIEW_ONCE_VIDEO = 3; - REACTIONS = 4; - CDN_SELECTOR_ATTACHMENTS = 5; - MENTIONS = 6; - PAYMENTS = 7; - CURRENT = 7; - } - - optional string body = 1; - repeated AttachmentPointer attachments = 2; - reserved /*groupV1*/ 3; - optional GroupContextV2 groupV2 = 15; - optional uint32 flags = 4; - optional uint32 expireTimer = 5; - optional uint32 expireTimerVersion = 23; - optional bytes profileKey = 6; - optional uint64 timestamp = 7; - optional Quote quote = 8; - repeated Contact contact = 9; - repeated Preview preview = 10; - optional Sticker sticker = 11; - optional uint32 requiredProtocolVersion = 12; - optional bool isViewOnce = 14; - optional Reaction reaction = 16; - optional Delete delete = 17; - repeated BodyRange bodyRanges = 18; - optional GroupCallUpdate groupCallUpdate = 19; - optional Payment payment = 20; - optional StoryContext storyContext = 21; - optional GiftBadge giftBadge = 22; + optional string body = 1; + repeated AttachmentPointer attachments = 2; + reserved /*groupV1*/ 3; + optional GroupContextV2 groupV2 = 15; + optional uint32 flags = 4; + optional uint32 expireTimer = 5; + optional uint32 expireTimerVersion = 23; + optional bytes profileKey = 6; + optional uint64 timestamp = 7; + optional Quote quote = 8; + repeated Contact contact = 9; + repeated Preview preview = 10; + optional Sticker sticker = 11; + optional uint32 requiredProtocolVersion = 12; + optional bool isViewOnce = 14; + optional Reaction reaction = 16; + optional Delete delete = 17; + repeated BodyRange bodyRanges = 18; + optional GroupCallUpdate groupCallUpdate = 19; + optional Payment payment = 20; + optional StoryContext storyContext = 21; + optional GiftBadge giftBadge = 22; + // NEXT ID: 24 } message NullMessage { @@ -358,185 +341,186 @@ message NullMessage { message ReceiptMessage { enum Type { DELIVERY = 0; - READ = 1; - VIEWED = 2; + READ = 1; + VIEWED = 2; } - optional Type type = 1; + optional Type type = 1; repeated uint64 timestamp = 2; } message TypingMessage { - enum Action { - STARTED = 0; - STOPPED = 1; - } + enum Action { + STARTED = 0; + STOPPED = 1; + } - optional uint64 timestamp = 1; - optional Action action = 2; - optional bytes groupId = 3; + optional uint64 timestamp = 1; + optional Action action = 2; + optional bytes groupId = 3; } message StoryMessage { - optional bytes profileKey = 1; - optional GroupContextV2 group = 2; + optional bytes profileKey = 1; + optional GroupContextV2 group = 2; oneof attachment { AttachmentPointer fileAttachment = 3; - TextAttachment textAttachment = 4; + TextAttachment textAttachment = 4; } - optional bool allowsReplies = 5; - repeated BodyRange bodyRanges = 6; + optional bool allowsReplies = 5; + repeated BodyRange bodyRanges = 6; } message Preview { - optional string url = 1; - optional string title = 2; - optional AttachmentPointer image = 3; - optional string description = 4; - optional uint64 date = 5; + optional string url = 1; + optional string title = 2; + optional AttachmentPointer image = 3; + optional string description = 4; + optional uint64 date = 5; } message TextAttachment { enum Style { - DEFAULT = 0; - REGULAR = 1; - BOLD = 2; - SERIF = 3; - SCRIPT = 4; + DEFAULT = 0; + REGULAR = 1; + BOLD = 2; + SERIF = 3; + SCRIPT = 4; CONDENSED = 5; } message Gradient { optional uint32 startColor = 1; // deprecated: this field will be removed in a future release. - optional uint32 endColor = 2; // deprecated: this field will be removed in a future release. - optional uint32 angle = 3; // degrees - repeated uint32 colors = 4; - repeated float positions = 5; // percent from 0 to 1 + optional uint32 endColor = 2; // deprecated: this field will be removed in a future release. + optional uint32 angle = 3; // degrees + repeated uint32 colors = 4; + repeated float positions = 5; // percent from 0 to 1 } - optional string text = 1; - optional Style textStyle = 2; - optional uint32 textForegroundColor = 3; // integer representation of hex color - optional uint32 textBackgroundColor = 4; - optional Preview preview = 5; + optional string text = 1; + optional Style textStyle = 2; + optional uint32 textForegroundColor = 3; // integer representation of hex color + optional uint32 textBackgroundColor = 4; + optional Preview preview = 5; oneof background { Gradient gradient = 6; - uint32 color = 7; + uint32 color = 7; } } message Verified { enum State { - DEFAULT = 0; - VERIFIED = 1; + DEFAULT = 0; + VERIFIED = 1; UNVERIFIED = 2; } - reserved /*destinationE164*/ 1; - optional string destinationAci = 5; - optional bytes identityKey = 2; - optional State state = 3; - optional bytes nullMessage = 4; + reserved /*destinationE164*/ 1; + optional string destinationAci = 5; + optional bytes identityKey = 2; + optional State state = 3; + optional bytes nullMessage = 4; } message SyncMessage { message Sent { message UnidentifiedDeliveryStatus { - reserved /*destinationE164*/ 1; - optional string destinationServiceId = 3; - optional bool unidentified = 2; - reserved /*destinationPni*/ 4; - optional bytes destinationIdentityKey = 5; + reserved /*destinationE164*/ 1; + optional string destinationServiceId = 3; + optional bool unidentified = 2; + reserved /*destinationPni */ 4; + optional bytes destinationPniIdentityKey = 5; // Only set for PNI destinations } message StoryMessageRecipient { optional string destinationServiceId = 1; - repeated string distributionListIds = 2; - optional bool isAllowedToReply = 3; + repeated string distributionListIds = 2; + optional bool isAllowedToReply = 3; + reserved /*destinationPni */ 4; } - optional string destinationE164 = 1; - optional string destinationServiceId = 7; - optional uint64 timestamp = 2; - optional DataMessage message = 3; - optional uint64 expirationStartTimestamp = 4; - repeated UnidentifiedDeliveryStatus unidentifiedStatus = 5; - optional bool isRecipientUpdate = 6 [default = false]; - optional StoryMessage storyMessage = 8; - repeated StoryMessageRecipient storyMessageRecipients = 9; - optional EditMessage editMessage = 10; - reserved /*destinationPni*/ 11; - // NEXT ID: 12 + optional string destinationE164 = 1; + optional string destinationServiceId = 7; + optional uint64 timestamp = 2; + optional DataMessage message = 3; + optional uint64 expirationStartTimestamp = 4; + repeated UnidentifiedDeliveryStatus unidentifiedStatus = 5; + optional bool isRecipientUpdate = 6 [default = false]; + optional StoryMessage storyMessage = 8; + repeated StoryMessageRecipient storyMessageRecipients = 9; + optional EditMessage editMessage = 10; + reserved /*destinationPni */ 11; + // Next ID: 12 } message Contacts { - optional AttachmentPointer blob = 1; - optional bool complete = 2 [default = false]; + optional AttachmentPointer blob = 1; + optional bool complete = 2 [default = false]; } message Blocked { - repeated string numbers = 1; - repeated string acis = 3; - repeated bytes groupIds = 2; + repeated string numbers = 1; + repeated string acis = 3; + repeated bytes groupIds = 2; } message Request { enum Type { - UNKNOWN = 0; - CONTACTS = 1; -// GROUPS = 2; - BLOCKED = 3; + UNKNOWN = 0; + CONTACTS = 1; + reserved /*GROUPS*/ 2; + BLOCKED = 3; CONFIGURATION = 4; - KEYS = 5; - PNI_IDENTITY = 6; + KEYS = 5; + reserved /*PNI_IDENTITY*/ 6; } optional Type type = 1; } message Read { - reserved /*senderE164*/ 1; - optional string senderAci = 3; - optional uint64 timestamp = 2; + reserved /*senderE164*/ 1; + optional string senderAci = 3; + optional uint64 timestamp = 2; } message Viewed { - reserved /*senderE164*/ 1; - optional string senderAci = 3; - optional uint64 timestamp = 2; + reserved /*senderE164*/ 1; + optional string senderAci = 3; + optional uint64 timestamp = 2; } message Configuration { - optional bool readReceipts = 1; - optional bool unidentifiedDeliveryIndicators = 2; - optional bool typingIndicators = 3; - reserved /* linkPreviews */ 4; - optional uint32 provisioningVersion = 5; - optional bool linkPreviews = 6; + optional bool readReceipts = 1; + optional bool unidentifiedDeliveryIndicators = 2; + optional bool typingIndicators = 3; + reserved /* linkPreviews */ 4; + optional uint32 provisioningVersion = 5; + optional bool linkPreviews = 6; } message StickerPackOperation { enum Type { INSTALL = 0; - REMOVE = 1; + REMOVE = 1; } - optional bytes packId = 1; + optional bytes packId = 1; optional bytes packKey = 2; - optional Type type = 3; + optional Type type = 3; } message ViewOnceOpen { - reserved /*senderE164*/ 1; - optional string senderAci = 3; - optional uint64 timestamp = 2; + reserved /*senderE164*/ 1; + optional string senderAci = 3; + optional uint64 timestamp = 2; } message FetchLatest { enum Type { - UNKNOWN = 0; - LOCAL_PROFILE = 1; - STORAGE_MANIFEST = 2; + UNKNOWN = 0; + LOCAL_PROFILE = 1; + STORAGE_MANIFEST = 2; SUBSCRIPTION_STATUS = 3; } @@ -544,91 +528,95 @@ message SyncMessage { } message Keys { - // @deprecated - optional bytes storageService = 1; - // @deprecated - optional bytes master = 2; + reserved /* storageService */ 1; + optional bytes master = 2; // deprecated: this field will be removed in a future release. optional string accountEntropyPool = 3; optional bytes mediaRootBackupKey = 4; } + message PniIdentity { + optional bytes publicKey = 1; + optional bytes privateKey = 2; + } + message MessageRequestResponse { enum Type { - UNKNOWN = 0; - ACCEPT = 1; - DELETE = 2; - BLOCK = 3; + UNKNOWN = 0; + ACCEPT = 1; + DELETE = 2; + BLOCK = 3; BLOCK_AND_DELETE = 4; - SPAM = 5; - BLOCK_AND_SPAM = 6; + SPAM = 5; + BLOCK_AND_SPAM = 6; } - reserved /*threadE164*/ 1; - optional string threadAci = 2; - optional bytes groupId = 3; - optional Type type = 4; + reserved /*threadE164*/ 1; + optional string threadAci = 2; + optional bytes groupId = 3; + optional Type type = 4; } message OutgoingPayment { message MobileCoin { - optional bytes recipientAddress = 1; - // @required - optional uint64 amountPicoMob = 2; - // @required - optional uint64 feePicoMob = 3; - optional bytes receipt = 4; + optional bytes recipientAddress = 1; + optional uint64 amountPicoMob = 2; + optional uint64 feePicoMob = 3; + optional bytes receipt = 4; optional uint64 ledgerBlockTimestamp = 5; - // @required - optional uint64 ledgerBlockIndex = 6; - repeated bytes spentKeyImages = 7; - repeated bytes outputPublicKeys = 8; + optional uint64 ledgerBlockIndex = 6; + repeated bytes spentKeyImages = 7; + repeated bytes outputPublicKeys = 8; } optional string recipientServiceId = 1; - optional string note = 2; - - oneof paymentDetail { + optional string note = 2; + oneof attachment_identifier { MobileCoin mobileCoin = 3; } } message PniChangeNumber { - optional bytes identityKeyPair = 1; // Serialized libsignal-client IdentityKeyPair - optional bytes signedPreKey = 2; // Serialized libsignal-client SignedPreKeyRecord - optional bytes lastResortKyberPreKey = 5; // Serialized libsignal-client KyberPreKeyRecord - optional uint32 registrationId = 3; - optional string newE164 = 4; // The e164 we have changed our number to + optional bytes identityKeyPair = 1; // Serialized libsignal-client IdentityKeyPair + optional bytes signedPreKey = 2; // Serialized libsignal-client SignedPreKeyRecord + optional bytes lastResortKyberPreKey = 5; // Serialized libsignal-client KyberPreKeyRecord + optional uint32 registrationId = 3; + optional string newE164 = 4; // The e164 we have changed our number to // Next ID: 6 } message CallEvent { enum Type { UNKNOWN_TYPE = 0; - AUDIO_CALL = 1; - VIDEO_CALL = 2; - GROUP_CALL = 3; - AD_HOC_CALL = 4; + AUDIO_CALL = 1; + VIDEO_CALL = 2; + GROUP_CALL = 3; + AD_HOC_CALL = 4; } enum Direction { UNKNOWN_DIRECTION = 0; - INCOMING = 1; - OUTGOING = 2; + INCOMING = 1; + OUTGOING = 2; } enum Event { - UNKNOWN_ACTION = 0; - ACCEPTED = 1; - NOT_ACCEPTED = 2; - DELETE = 3; - OBSERVED = 4; + UNKNOWN_EVENT = 0; + ACCEPTED = 1; + NOT_ACCEPTED = 2; + DELETE = 3; + OBSERVED = 4; } - optional bytes conversationId = 1; - optional uint64 id = 2; - optional uint64 timestamp = 3; - optional Type type = 4; - optional Direction direction = 5; - optional Event event = 6; + /* Data identifying a conversation. The service ID for 1:1, the group ID for + * group, or the room ID for an ad-hoc call. See also + * `CallLogEvent/conversationId`. */ + optional bytes conversationId = 1; + /* An identifier for a call. Generated directly for 1:1, or derived from + * the era ID for group and ad-hoc calls. See also `CallLogEvent/callId`. */ + optional uint64 callId = 2; + optional uint64 timestamp = 3; + optional Type type = 4; + optional Direction direction = 5; + optional Event event = 6; } message CallLinkUpdate { @@ -637,27 +625,28 @@ message SyncMessage { reserved 1; // was DELETE, superseded by storage service } - optional bytes rootKey = 1; - optional bytes adminPassKey = 2; - optional Type type = 3; + optional bytes rootKey = 1; + optional bytes adminPasskey = 2; + optional Type type = 3; // defaults to UPDATE } message CallLogEvent { enum Type { - CLEAR = 0; - MARKED_AS_READ = 1; + CLEAR = 0; + MARKED_AS_READ = 1; MARKED_AS_READ_IN_CONVERSATION = 2; + CLEAR_IN_CONVERSATION = 3; } - optional Type type = 1; - optional uint64 timestamp = 2; + optional Type type = 1; + optional uint64 timestamp = 2; /* Data identifying a conversation. The service ID for 1:1, the group ID for * group, or the room ID for an ad-hoc call. See also * `CallEvent/conversationId`. */ optional bytes conversationId = 3; /* An identifier for a call. Generated directly for 1:1, or derived from * the era ID for group and ad-hoc calls. See also `CallEvent/callId`. */ - optional uint64 callId = 4; + optional uint64 callId = 4; } message DeleteForMe { @@ -685,16 +674,19 @@ message SyncMessage { message AttachmentDelete { optional ConversationIdentifier conversation = 1; optional AddressableMessage targetMessage = 2; - optional bytes uuid = 3; // The `uuid` from the `Attachment`. + // The `clientUuid` from `AttachmentPointer`. + optional bytes clientUuid = 3; + // SHA256 hash of the (encrypted, padded, etc.) attachment blob on the CDN. optional bytes fallbackDigest = 4; + // SHA256 hash of the plaintext content of the attachment. optional bytes fallbackPlaintextHash = 5; } message ConversationDelete { optional ConversationIdentifier conversation = 1; repeated AddressableMessage mostRecentMessages = 2; - repeated AddressableMessage mostRecentNonExpiringMessages = 4; optional bool isFullDelete = 3; + repeated AddressableMessage mostRecentNonExpiringMessages = 4; } message LocalOnlyConversationDelete { @@ -708,163 +700,140 @@ message SyncMessage { } message DeviceNameChange { - reserved /*name*/ 1; + reserved /*name*/ 1; optional uint32 deviceId = 2; } - optional Sent sent = 1; - optional Contacts contacts = 2; - reserved /*groups*/ 3; - optional Request request = 4; - repeated Read read = 5; - optional Blocked blocked = 6; - optional Verified verified = 7; - optional Configuration configuration = 9; - optional bytes padding = 8; - repeated StickerPackOperation stickerPackOperation = 10; - optional ViewOnceOpen viewOnceOpen = 11; - optional FetchLatest fetchLatest = 12; - optional Keys keys = 13; + optional Sent sent = 1; + optional Contacts contacts = 2; + reserved /*groups*/ 3; + optional Request request = 4; + repeated Read read = 5; + optional Blocked blocked = 6; + optional Verified verified = 7; + optional Configuration configuration = 9; + optional bytes padding = 8; + repeated StickerPackOperation stickerPackOperation = 10; + optional ViewOnceOpen viewOnceOpen = 11; + optional FetchLatest fetchLatest = 12; + optional Keys keys = 13; optional MessageRequestResponse messageRequestResponse = 14; - optional OutgoingPayment outgoingPayment = 15; - repeated Viewed viewed = 16; - reserved /*pniIdentity*/ 17; - optional PniChangeNumber pniChangeNumber = 18; - optional CallEvent callEvent = 19; - optional CallLinkUpdate callLinkUpdate = 20; - optional CallLogEvent callLogEvent = 21; - optional DeleteForMe deleteForMe = 22; - optional DeviceNameChange deviceNameChange = 23; + optional OutgoingPayment outgoingPayment = 15; + repeated Viewed viewed = 16; + reserved /*pniIdentity*/ 17; + optional PniChangeNumber pniChangeNumber = 18; + optional CallEvent callEvent = 19; + optional CallLinkUpdate callLinkUpdate = 20; + optional CallLogEvent callLogEvent = 21; + optional DeleteForMe deleteForMe = 22; + optional DeviceNameChange deviceNameChange = 23; } message AttachmentPointer { enum Flags { VOICE_MESSAGE = 1; - BORDERLESS = 2; - reserved 3; - GIF = 4; + BORDERLESS = 2; + reserved 4; + GIF = 8; } oneof attachment_identifier { - fixed64 cdnId = 1; - string cdnKey = 15; + fixed64 cdnId = 1; + string cdnKey = 15; } - optional string contentType = 2; - optional bytes key = 3; - optional uint32 size = 4; - optional bytes thumbnail = 5; - optional bytes digest = 6; - reserved 16; - reserved 18; - optional bytes incrementalMac = 19; - optional uint32 incrementalMacChunkSize = 17; - optional string fileName = 7; - optional uint32 flags = 8; - optional uint32 width = 9; - optional uint32 height = 10; - optional string caption = 11; - optional string blurHash = 12; - optional uint64 uploadTimestamp = 13; - optional uint32 cdnNumber = 14; - optional bytes uuid = 20; + // Cross-client identifier for this attachment among all attachments on the + // owning message. + optional bytes clientUuid = 20; + optional string contentType = 2; + optional bytes key = 3; + optional uint32 size = 4; + optional bytes thumbnail = 5; + optional bytes digest = 6; + reserved /* incrementalMac with implicit chunk sizing */ 16; + reserved /* incrementalMac for all attachment types */ 18; + optional bytes incrementalMac = 19; + optional uint32 chunkSize = 17; + optional string fileName = 7; + optional uint32 flags = 8; + optional uint32 width = 9; + optional uint32 height = 10; + optional string caption = 11; + optional string blurHash = 12; + optional uint64 uploadTimestamp = 13; + optional uint32 cdnNumber = 14; // Next ID: 21 } -message GroupContext { - enum Type { - UNKNOWN = 0; - UPDATE = 1; - DELIVER = 2; - QUIT = 3; - REQUEST_INFO = 4; - } - - message Member { - reserved /* uuid */ 1; // removed - optional string e164 = 2; - } - - optional bytes id = 1; - optional Type type = 2; - optional string name = 3; - repeated string membersE164 = 4; - repeated Member members = 6; - optional AttachmentPointer avatar = 5; -} - message GroupContextV2 { - optional bytes masterKey = 1; - optional uint32 revision = 2; - optional bytes groupChange = 3; + optional bytes masterKey = 1; + optional uint32 revision = 2; + optional bytes groupChange = 3; } message ContactDetails { message Avatar { optional string contentType = 1; - optional uint32 length = 2; + optional uint32 length = 2; } - optional string number = 1; - optional string aci = 9; - optional string name = 2; - optional Avatar avatar = 3; - optional string color = 4; - optional Verified verified = 5; - optional bytes profileKey = 6; - reserved /*blocked*/ 7; - optional uint32 expireTimer = 8; - optional uint32 expireTimerVersion = 12; - optional uint32 inboxPosition = 10; - optional bool archived = 11; -} - -message GroupDetails { - message Avatar { - optional string contentType = 1; - optional uint32 length = 2; - } - - message Member { - reserved /* uuid */ 1; // removed - optional string e164 = 2; - } - - optional bytes id = 1; - optional string name = 2; - repeated string membersE164 = 3; - repeated Member members = 9; - optional Avatar avatar = 4; - optional bool active = 5 [default = true]; - optional uint32 expireTimer = 6; - optional string color = 7; - optional bool blocked = 8; - optional uint32 inboxPosition = 10; - optional bool archived = 11; + optional string number = 1; + optional string aci = 9; + optional string name = 2; + optional Avatar avatar = 3; + reserved /* color */ 4; + reserved /* verified */ 5; + reserved /* profileKey */ 6; + reserved /* blocked */ 7; + optional uint32 expireTimer = 8; + optional uint32 expireTimerVersion = 12; + optional uint32 inboxPosition = 10; + reserved /* archived */ 11; + // NEXT ID: 13 } message PaymentAddress { - oneof Address { - MobileCoinAddress mobileCoinAddress = 1; + message MobileCoin { + optional bytes publicAddress = 1; + optional bytes signature = 2; } - message MobileCoinAddress { - optional bytes address = 1; - optional bytes signature = 2; + oneof Address { + MobileCoin mobileCoin = 1; } } message DecryptionErrorMessage { - optional bytes ratchetKey = 1; - optional uint64 timestamp = 2; - optional uint32 deviceId = 3; + optional bytes ratchetKey = 1; // set to the public ratchet key from the SignalMessage if a 1-1 payload fails to decrypt + optional uint64 timestamp = 2; + optional uint32 deviceId = 3; } message PniSignatureMessage { - optional bytes pni = 1; + optional bytes pni = 1; + // Signature *by* the PNI identity key *of* the ACI identity key optional bytes signature = 2; } message EditMessage { - optional uint64 targetSentTimestamp = 1; - optional DataMessage dataMessage = 2; + optional uint64 targetSentTimestamp = 1; + optional DataMessage dataMessage = 2; +} + +message BodyRange { + enum Style { + NONE = 0; + BOLD = 1; + ITALIC = 2; + SPOILER = 3; + STRIKETHROUGH = 4; + MONOSPACE = 5; + } + + optional uint32 start = 1; // Starting index in UTF-16 code units/raw string representation + optional uint32 length = 2; // Length of range in UTF-16 code units/raw string representation + + oneof associatedValue { + string mentionAci = 3; + Style style = 4; + } } \ No newline at end of file diff --git a/libsignal-service/src/main/protowire/SignalServiceLegacy.proto b/libsignal-service/src/main/protowire/SignalServiceLegacy.proto new file mode 100644 index 0000000000..984387881a --- /dev/null +++ b/libsignal-service/src/main/protowire/SignalServiceLegacy.proto @@ -0,0 +1,40 @@ +/* + * Copyright 2020-2022 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/** + * This file contains protos that were removed from SignalService.proto, but are still needed by our application, + * typically for serialization purposes. + */ + +syntax = "proto2"; + +package signalservice; + +option java_package = "org.whispersystems.signalservice.internal.push"; +option java_outer_classname = "SignalServiceProtos"; + +import SignalService.proto; + +message GroupContext { + enum Type { + UNKNOWN = 0; + UPDATE = 1; + DELIVER = 2; + QUIT = 3; + REQUEST_INFO = 4; + } + + message Member { + reserved /* uuid */ 1; // removed + optional string e164 = 2; + } + + optional bytes id = 1; + optional Type type = 2; + optional string name = 3; + repeated string membersE164 = 4; + repeated Member members = 6; + optional signalservice.AttachmentPointer avatar = 5; +} diff --git a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStreamTest.java b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStreamTest.java index 3a39ddfe4a..e58e428f4a 100644 --- a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStreamTest.java +++ b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStreamTest.java @@ -35,13 +35,9 @@ public class DeviceContactsInputStreamTest { e164First, Optional.of("Teal'c"), Optional.empty(), - Optional.of("ultramarine"), - Optional.of(new VerifiedMessage(new SignalServiceAddress(aciFirst.get(), e164First), generateIdentityKey(), VerifiedMessage.VerifiedState.DEFAULT, System.currentTimeMillis())), - Optional.of(generateProfileKey()), Optional.of(0), Optional.of(0), - Optional.of(0), - false + Optional.of(0) ); DeviceContact second = new DeviceContact( @@ -49,13 +45,9 @@ public class DeviceContactsInputStreamTest { e164Second, Optional.of("Bra'tac"), Optional.empty(), - Optional.of("ultramarine"), - Optional.of(new VerifiedMessage(new SignalServiceAddress(aciSecond.get(), e164Second), generateIdentityKey(), VerifiedMessage.VerifiedState.DEFAULT, System.currentTimeMillis())), - Optional.of(generateProfileKey()), Optional.of(0), Optional.of(0), - Optional.of(0), - false + Optional.of(0) ); output.write(first); @@ -72,24 +64,9 @@ public class DeviceContactsInputStreamTest { assertEquals(first.getAci(), readFirst.getAci()); assertEquals(first.getE164(), readFirst.getE164()); assertEquals(first.getName(), readFirst.getName()); - assertEquals(first.getColor(), readFirst.getColor()); - assertEquals(first.getVerified().get().getIdentityKey(), readFirst.getVerified().get().getIdentityKey()); - assertEquals(first.isArchived(), readFirst.isArchived()); assertEquals(second.getAci(), readSecond.getAci()); assertEquals(second.getE164(), readSecond.getE164()); assertEquals(second.getName(), readSecond.getName()); - assertEquals(second.getColor(), readSecond.getColor()); - assertEquals(second.getVerified().get().getIdentityKey(), readSecond.getVerified().get().getIdentityKey()); - assertEquals(second.isArchived(), readSecond.isArchived()); - } - - private static IdentityKey generateIdentityKey() { - ECKeyPair djbKeyPair = Curve.generateKeyPair(); - return new IdentityKey(djbKeyPair.getPublicKey()); - } - - private static ProfileKey generateProfileKey() throws InvalidInputException { - return new ProfileKey(Util.getSecretBytes(32)); } } \ No newline at end of file