]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java
Update libsignal-service-java
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / helper / IncomingMessageHandler.java
index 0692a06ec9ba0229988b5dd42119c6fd7ea74131..dd9cb38fa5e9dd431b3216ffc699d87814c8fb85 100644 (file)
@@ -6,7 +6,6 @@ import org.asamk.signal.manager.actions.RefreshPreKeysAction;
 import org.asamk.signal.manager.actions.RenewSessionAction;
 import org.asamk.signal.manager.actions.ResendMessageAction;
 import org.asamk.signal.manager.actions.RetrieveProfileAction;
-import org.asamk.signal.manager.actions.RetrieveStorageDataAction;
 import org.asamk.signal.manager.actions.SendGroupInfoAction;
 import org.asamk.signal.manager.actions.SendGroupInfoRequestAction;
 import org.asamk.signal.manager.actions.SendProfileKeyAction;
@@ -17,12 +16,12 @@ import org.asamk.signal.manager.actions.SendSyncConfigurationAction;
 import org.asamk.signal.manager.actions.SendSyncContactsAction;
 import org.asamk.signal.manager.actions.SendSyncGroupsAction;
 import org.asamk.signal.manager.actions.SendSyncKeysAction;
+import org.asamk.signal.manager.actions.SyncStorageDataAction;
 import org.asamk.signal.manager.actions.UpdateAccountAttributesAction;
 import org.asamk.signal.manager.api.GroupId;
 import org.asamk.signal.manager.api.GroupNotFoundException;
 import org.asamk.signal.manager.api.MessageEnvelope;
 import org.asamk.signal.manager.api.Pair;
-import org.asamk.signal.manager.api.Profile;
 import org.asamk.signal.manager.api.ReceiveConfig;
 import org.asamk.signal.manager.api.StickerPackId;
 import org.asamk.signal.manager.api.TrustLevel;
@@ -32,6 +31,7 @@ import org.asamk.signal.manager.internal.SignalDependencies;
 import org.asamk.signal.manager.jobs.RetrieveStickerPackJob;
 import org.asamk.signal.manager.storage.SignalAccount;
 import org.asamk.signal.manager.storage.groups.GroupInfoV1;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
 import org.asamk.signal.manager.storage.recipients.RecipientId;
 import org.asamk.signal.manager.storage.stickers.StickerPack;
 import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
@@ -40,12 +40,10 @@ import org.signal.libsignal.metadata.ProtocolInvalidMessageException;
 import org.signal.libsignal.metadata.ProtocolNoSessionException;
 import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException;
 import org.signal.libsignal.metadata.SelfSendException;
-import org.signal.libsignal.protocol.IdentityKeyPair;
 import org.signal.libsignal.protocol.InvalidMessageException;
+import org.signal.libsignal.protocol.UsePqRatchet;
 import org.signal.libsignal.protocol.groups.GroupSessionBuilder;
 import org.signal.libsignal.protocol.message.DecryptionErrorMessage;
-import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
-import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
 import org.signal.libsignal.zkgroup.InvalidInputException;
 import org.signal.libsignal.zkgroup.profiles.ProfileKey;
 import org.slf4j.Logger;
@@ -60,21 +58,17 @@ import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
 import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
 import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext;
 import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2;
-import org.whispersystems.signalservice.api.messages.SignalServiceMetadata;
 import org.whispersystems.signalservice.api.messages.SignalServicePniSignatureMessage;
 import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
 import org.whispersystems.signalservice.api.messages.SignalServiceStoryMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
 import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
-import org.whispersystems.signalservice.api.push.ACI;
-import org.whispersystems.signalservice.api.push.PNI;
 import org.whispersystems.signalservice.api.push.ServiceId;
+import org.whispersystems.signalservice.api.push.ServiceId.ACI;
+import org.whispersystems.signalservice.api.push.ServiceIdType;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
-import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
+import org.whispersystems.signalservice.internal.push.Envelope;
 import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException;
-import org.whispersystems.signalservice.internal.serialize.SignalServiceAddressProtobufSerializer;
-import org.whispersystems.signalservice.internal.serialize.SignalServiceMetadataProtobufSerializer;
-import org.whispersystems.signalservice.internal.serialize.protos.SignalServiceContentProto;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -83,7 +77,7 @@ import java.util.stream.Collectors;
 
 public final class IncomingMessageHandler {
 
-    private final static Logger logger = LoggerFactory.getLogger(IncomingMessageHandler.class);
+    private static final Logger logger = LoggerFactory.getLogger(IncomingMessageHandler.class);
 
     private final SignalAccount account;
     private final SignalDependencies dependencies;
@@ -108,9 +102,11 @@ public final class IncomingMessageHandler {
         SignalServiceContent content = null;
         if (!envelope.isReceipt()) {
             account.getIdentityKeyStore().setRetryingDecryption(true);
+            final var destination = getDestination(envelope).serviceId();
             try {
-                final var cipherResult = dependencies.getCipher()
-                        .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp());
+                final var cipherResult = dependencies.getCipher(destination == null
+                                || destination.equals(account.getAci()) ? ServiceIdType.ACI : ServiceIdType.PNI)
+                        .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp(), UsePqRatchet.NO);
                 content = validate(envelope.getProto(), cipherResult, envelope.getServerDeliveredTimestamp());
                 if (content == null) {
                     return new Pair<>(List.of(), null);
@@ -137,17 +133,18 @@ public final class IncomingMessageHandler {
             final Manager.ReceiveMessageHandler handler
     ) {
         final var actions = new ArrayList<HandleAction>();
-        if (envelope.hasSourceUuid()) {
-            // Store uuid if we don't have it already
-            // address/uuid in envelope is sent by server
-            account.getRecipientTrustedResolver().resolveRecipientTrusted(envelope.getSourceAddress());
-        }
         SignalServiceContent content = null;
         Exception exception = null;
+        envelope.getSourceServiceId().map(ServiceId::parseOrNull)
+                // Store uuid if we don't have it already
+                // uuid in envelope is sent by server
+                .ifPresent(serviceId -> account.getRecipientResolver().resolveRecipient(serviceId));
         if (!envelope.isReceipt()) {
+            final var destination = getDestination(envelope).serviceId();
             try {
-                final var cipherResult = dependencies.getCipher()
-                        .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp());
+                final var cipherResult = dependencies.getCipher(destination == null
+                                || destination.equals(account.getAci()) ? ServiceIdType.ACI : ServiceIdType.PNI)
+                        .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp(), UsePqRatchet.NO);
                 content = validate(envelope.getProto(), cipherResult, envelope.getServerDeliveredTimestamp());
                 if (content == null) {
                     return new Pair<>(List.of(), null);
@@ -161,34 +158,22 @@ public final class IncomingMessageHandler {
             } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException |
                      ProtocolInvalidMessageException e) {
                 logger.debug("Failed to decrypt incoming message", e);
+                if (e instanceof ProtocolInvalidKeyIdException) {
+                    actions.add(RefreshPreKeysAction.create());
+                }
                 final var sender = account.getRecipientResolver().resolveRecipient(e.getSender());
                 if (context.getContactHelper().isContactBlocked(sender)) {
                     logger.debug("Received invalid message from blocked contact, ignoring.");
                 } else {
-                    final var senderProfile = context.getProfileHelper().getRecipientProfile(sender);
-                    final var selfProfile = context.getProfileHelper().getSelfProfile();
                     var serviceId = ServiceId.parseOrNull(e.getSender());
-                    if (serviceId == null) {
-                        // Workaround for libsignal-client issue #492
-                        serviceId = account.getRecipientAddressResolver()
-                                .resolveRecipientAddress(sender)
-                                .serviceId()
-                                .orElse(null);
-                    }
                     if (serviceId != null) {
                         final var isSelf = sender.equals(account.getSelfRecipientId())
                                 && e.getSenderDevice() == account.getDeviceId();
-                        final var isSenderSenderKeyCapable = senderProfile != null && senderProfile.getCapabilities()
-                                .contains(Profile.Capability.senderKey);
-                        final var isSelfSenderKeyCapable = selfProfile != null && selfProfile.getCapabilities()
-                                .contains(Profile.Capability.senderKey);
-                        final var destination = getDestination(envelope).serviceId();
-                        if (!isSelf && isSenderSenderKeyCapable && isSelfSenderKeyCapable) {
+                        logger.debug("Received invalid message, queuing renew session action.");
+                        actions.add(new RenewSessionAction(sender, serviceId, destination));
+                        if (!isSelf) {
                             logger.debug("Received invalid message, requesting message resend.");
-                            actions.add(new SendRetryMessageRequestAction(sender, serviceId, e, envelope, destination));
-                        } else {
-                            logger.debug("Received invalid message, queuing renew session action.");
-                            actions.add(new RenewSessionAction(sender, serviceId, destination));
+                            actions.add(new SendRetryMessageRequestAction(sender, e, envelope));
                         }
                     } else {
                         logger.debug("Received invalid message from invalid sender: {}", e.getSender());
@@ -209,11 +194,13 @@ public final class IncomingMessageHandler {
     }
 
     private SignalServiceContent validate(
-            SignalServiceProtos.Envelope envelope, SignalServiceCipherResult cipherResult, long serverDeliveredTimestamp
+            Envelope envelope,
+            SignalServiceCipherResult cipherResult,
+            long serverDeliveredTimestamp
     ) throws ProtocolInvalidKeyException, ProtocolInvalidMessageException, UnsupportedDataMessageException, InvalidMessageStructureException {
         final var content = cipherResult.getContent();
         final var envelopeMetadata = cipherResult.getMetadata();
-        final var validationResult = EnvelopeContentValidator.INSTANCE.validate(envelope, content);
+        final var validationResult = EnvelopeContentValidator.INSTANCE.validate(envelope, content, account.getAci());
 
         if (validationResult instanceof EnvelopeContentValidator.Result.Invalid v) {
             logger.warn("Invalid content! {}", v.getReason(), v.getThrowable());
@@ -227,26 +214,11 @@ public final class IncomingMessageHandler {
             return null;
         }
 
-        final var localAddress = new SignalServiceAddress(envelopeMetadata.getDestinationServiceId(),
-                Optional.ofNullable(account.getNumber()));
-        final var metadata = new SignalServiceMetadata(new SignalServiceAddress(envelopeMetadata.getSourceServiceId(),
-                Optional.ofNullable(envelopeMetadata.getSourceE164())),
-                envelopeMetadata.getSourceDeviceId(),
-                envelope.getTimestamp(),
-                envelope.getServerTimestamp(),
-                serverDeliveredTimestamp,
-                envelopeMetadata.getSealedSender(),
-                envelope.getServerGuid(),
-                Optional.ofNullable(envelopeMetadata.getGroupId()),
-                envelopeMetadata.getDestinationServiceId().toString());
-
-        final var contentProto = SignalServiceContentProto.newBuilder()
-                .setLocalAddress(SignalServiceAddressProtobufSerializer.toProtobuf(localAddress))
-                .setMetadata(SignalServiceMetadataProtobufSerializer.toProtobuf(metadata))
-                .setContent(content)
-                .build();
-
-        return SignalServiceContent.createFromProto(contentProto);
+        return SignalServiceContent.Companion.createFrom(account.getNumber(),
+                envelope,
+                envelopeMetadata,
+                content,
+                serverDeliveredTimestamp);
     }
 
     private List<HandleAction> checkAndHandleMessage(
@@ -314,7 +286,9 @@ public final class IncomingMessageHandler {
     }
 
     public List<HandleAction> handleMessage(
-            SignalServiceEnvelope envelope, SignalServiceContent content, ReceiveConfig receiveConfig
+            SignalServiceEnvelope envelope,
+            SignalServiceContent content,
+            ReceiveConfig receiveConfig
     ) {
         var actions = new ArrayList<HandleAction>();
         final var senderDeviceAddress = getSender(envelope, content);
@@ -323,6 +297,12 @@ public final class IncomingMessageHandler {
         final var senderDeviceId = senderDeviceAddress.deviceId();
         final var destination = getDestination(envelope);
 
+        if (account.getPni().equals(destination.serviceId)) {
+            account.getRecipientStore().markNeedsPniSignature(destination.recipientId, true);
+        } else if (account.getAci().equals(destination.serviceId)) {
+            account.getRecipientStore().markNeedsPniSignature(destination.recipientId, false);
+        }
+
         if (content.getReceiptMessage().isPresent()) {
             final var message = content.getReceiptMessage().get();
             if (message.isDeliveryReceipt()) {
@@ -359,8 +339,10 @@ public final class IncomingMessageHandler {
             }
         }
 
-        if (content.getDataMessage().isPresent()) {
-            var message = content.getDataMessage().get();
+        if (content.getDataMessage().isPresent() || content.getEditMessage().isPresent()) {
+            var message = content.getDataMessage().isPresent()
+                    ? content.getDataMessage().get()
+                    : content.getEditMessage().get().getDataMessage();
 
             if (content.isNeedsReceipt()) {
                 actions.add(new SendReceiptAction(sender,
@@ -407,9 +389,10 @@ public final class IncomingMessageHandler {
     }
 
     private boolean handlePniSignatureMessage(
-            final SignalServicePniSignatureMessage message, final SignalServiceAddress senderAddress
+            final SignalServicePniSignatureMessage message,
+            final SignalServiceAddress senderAddress
     ) {
-        final var aci = ACI.from(senderAddress.getServiceId());
+        final var aci = senderAddress.getServiceId();
         final var aciIdentity = account.getIdentityKeyStore().getIdentityInfo(aci);
         final var pni = message.getPni();
         final var pniIdentity = account.getIdentityKeyStore().getIdentityInfo(pni);
@@ -428,7 +411,9 @@ public final class IncomingMessageHandler {
 
         logger.debug("Verified association of ACI {} with PNI {}", aci, pni);
         account.getRecipientTrustedResolver()
-                .resolveRecipientTrusted(Optional.of(aci), Optional.of(pni), senderAddress.getNumber());
+                .resolveRecipientTrusted(Optional.of(ACI.from(aci.getRawUuid())),
+                        Optional.of(pni),
+                        senderAddress.getNumber());
         return true;
     }
 
@@ -503,7 +488,7 @@ public final class IncomingMessageHandler {
                         sender,
                         destination == null
                                 ? null
-                                : new DeviceAddress(context.getRecipientHelper().resolveRecipient(destination),
+                                : new DeviceAddress(account.getRecipientResolver().resolveRecipient(destination),
                                         destination.getServiceId(),
                                         0),
                         ignoreAttachments));
@@ -531,6 +516,7 @@ public final class IncomingMessageHandler {
             if (rm.isConfigurationRequest()) {
                 actions.add(SendSyncConfigurationAction.create());
             }
+            actions.add(SyncStorageDataAction.create());
         }
         if (syncMessage.getGroups().isPresent()) {
             try {
@@ -543,12 +529,12 @@ public final class IncomingMessageHandler {
         }
         if (syncMessage.getBlockedList().isPresent()) {
             final var blockedListMessage = syncMessage.getBlockedList().get();
-            for (var address : blockedListMessage.getAddresses()) {
-                context.getContactHelper()
-                        .setContactBlocked(context.getRecipientHelper().resolveRecipient(address), true);
+            for (var individual : blockedListMessage.individuals) {
+                final var address = new RecipientAddress(individual.getAci(), individual.getE164());
+                final var recipientId = account.getRecipientResolver().resolveRecipient(address);
+                context.getContactHelper().setContactBlocked(recipientId, true);
             }
-            for (var groupId : blockedListMessage.getGroupIds()
-                    .stream()
+            for (var groupId : blockedListMessage.groupIds.stream()
                     .map(GroupId::unknownVersion)
                     .collect(Collectors.toSet())) {
                 try {
@@ -583,38 +569,43 @@ public final class IncomingMessageHandler {
                     continue;
                 }
                 final var stickerPackId = StickerPackId.deserialize(m.getPackId().get());
+                final var stickerPackKey = m.getPackKey().orElse(null);
                 final var installed = m.getType().isEmpty()
                         || m.getType().get() == StickerPackOperationMessage.Type.INSTALL;
 
-                var sticker = account.getStickerStore().getStickerPack(stickerPackId);
-                if (m.getPackKey().isPresent()) {
-                    if (sticker == null) {
-                        sticker = new StickerPack(-1, stickerPackId, m.getPackKey().get(), installed);
-                        account.getStickerStore().addStickerPack(sticker);
-                    }
-                    if (installed) {
-                        context.getJobExecutor()
-                                .enqueueJob(new RetrieveStickerPackJob(stickerPackId, m.getPackKey().get()));
-                    }
-                }
+                final var sticker = context.getStickerHelper()
+                        .addOrUpdateStickerPack(stickerPackId, stickerPackKey, installed);
 
-                if (sticker != null && sticker.isInstalled() != installed) {
-                    account.getStickerStore().updateStickerPackInstalled(sticker.packId(), installed);
+                if (sticker != null && installed) {
+                    context.getJobExecutor().enqueueJob(new RetrieveStickerPackJob(stickerPackId, sticker.packKey()));
                 }
             }
         }
         if (syncMessage.getFetchType().isPresent()) {
             switch (syncMessage.getFetchType().get()) {
                 case LOCAL_PROFILE -> actions.add(new RetrieveProfileAction(account.getSelfRecipientId()));
-                case STORAGE_MANIFEST -> actions.add(RetrieveStorageDataAction.create());
+                case STORAGE_MANIFEST -> actions.add(SyncStorageDataAction.create());
             }
         }
         if (syncMessage.getKeys().isPresent()) {
             final var keysMessage = syncMessage.getKeys().get();
-            if (keysMessage.getStorageService().isPresent()) {
-                final var storageKey = keysMessage.getStorageService().get();
+            if (keysMessage.getAccountEntropyPool() != null) {
+                final var aep = keysMessage.getAccountEntropyPool();
+                account.setAccountEntropyPool(aep);
+                actions.add(SyncStorageDataAction.create());
+            } else if (keysMessage.getMaster() != null) {
+                final var masterKey = keysMessage.getMaster();
+                account.setMasterKey(masterKey);
+                actions.add(SyncStorageDataAction.create());
+            } else if (keysMessage.getStorageService() != null) {
+                final var storageKey = keysMessage.getStorageService();
                 account.setStorageKey(storageKey);
-                actions.add(RetrieveStorageDataAction.create());
+                actions.add(SyncStorageDataAction.create());
+            }
+            if (keysMessage.getMediaRootBackupKey() != null) {
+                final var mrb = keysMessage.getMediaRootBackupKey();
+                account.setMediaRootBackupKey(mrb);
+                actions.add(SyncStorageDataAction.create());
             }
         }
         if (syncMessage.getConfiguration().isPresent()) {
@@ -637,26 +628,10 @@ public final class IncomingMessageHandler {
         if (syncMessage.getPniChangeNumber().isPresent()) {
             final var pniChangeNumber = syncMessage.getPniChangeNumber().get();
             logger.debug("Received PNI change number sync message, applying.");
-            if (pniChangeNumber.hasIdentityKeyPair()
-                    && pniChangeNumber.hasRegistrationId()
-                    && pniChangeNumber.hasSignedPreKey()
-                    && !envelope.getUpdatedPni().isEmpty()) {
-                logger.debug("New PNI: {}", envelope.getUpdatedPni());
-                try {
-                    final var updatedPni = PNI.parseOrThrow(envelope.getUpdatedPni());
-                    context.getAccountHelper()
-                            .setPni(updatedPni,
-                                    new IdentityKeyPair(pniChangeNumber.getIdentityKeyPair().toByteArray()),
-                                    pniChangeNumber.hasNewE164() ? pniChangeNumber.getNewE164() : null,
-                                    pniChangeNumber.getRegistrationId(),
-                                    new SignedPreKeyRecord(pniChangeNumber.getSignedPreKey().toByteArray()),
-                                    pniChangeNumber.hasLastResortKyberPreKey()
-                                            ? new KyberPreKeyRecord(pniChangeNumber.getLastResortKyberPreKey()
-                                            .toByteArray())
-                                            : null);
-                } catch (Exception e) {
-                    logger.warn("Failed to handle change number message", e);
-                }
+            final var updatedPniString = envelope.getUpdatedPni();
+            if (updatedPniString != null && !updatedPniString.isEmpty()) {
+                final var updatedPni = ServiceId.PNI.parseOrThrow(updatedPniString);
+                context.getAccountHelper().handlePniChangeNumberMessage(pniChangeNumber, updatedPni);
             }
         }
         return actions;
@@ -693,7 +668,7 @@ public final class IncomingMessageHandler {
         if (source == null) {
             return false;
         }
-        final var recipientId = context.getRecipientHelper().resolveRecipient(source);
+        final var recipientId = account.getRecipientResolver().resolveRecipient(source);
         if (context.getContactHelper().isContactBlocked(recipientId)) {
             return true;
         }
@@ -733,7 +708,7 @@ public final class IncomingMessageHandler {
 
         final var message = content.getDataMessage().orElse(null);
 
-        final var recipientId = context.getRecipientHelper().resolveRecipient(source);
+        final var recipientId = account.getRecipientResolver().resolveRecipient(source);
         if (!group.isMember(recipientId) && !(
                 group.isPendingMember(recipientId) && message != null && message.isGroupV2Update()
         )) {
@@ -784,10 +759,11 @@ public final class IncomingMessageHandler {
                             }
 
                             if (groupInfo.getMembers().isPresent()) {
+                                final var recipientResolver = account.getRecipientResolver();
                                 groupV1.addMembers(groupInfo.getMembers()
                                         .get()
                                         .stream()
-                                        .map(context.getRecipientHelper()::resolveRecipient)
+                                        .map(recipientResolver::resolveRecipient)
                                         .collect(Collectors.toSet()));
                             }
 
@@ -843,7 +819,9 @@ public final class IncomingMessageHandler {
                 }
             } else if (conversationPartnerAddress != null) {
                 context.getContactHelper()
-                        .setExpirationTimer(conversationPartnerAddress.recipientId(), message.getExpiresInSeconds());
+                        .setExpirationTimer(conversationPartnerAddress.recipientId(),
+                                message.getExpiresInSeconds(),
+                                message.getExpireTimerVersion());
             }
         }
         if (!ignoreAttachments) {
@@ -904,7 +882,9 @@ public final class IncomingMessageHandler {
     }
 
     private List<HandleAction> handleSignalServiceStoryMessage(
-            SignalServiceStoryMessage message, RecipientId source, boolean ignoreAttachments
+            SignalServiceStoryMessage message,
+            RecipientId source,
+            boolean ignoreAttachments
     ) {
         var actions = new ArrayList<HandleAction>();
         if (message.getGroupContext().isPresent()) {
@@ -960,8 +940,9 @@ public final class IncomingMessageHandler {
     }
 
     private SignalServiceAddress getSenderAddress(SignalServiceEnvelope envelope, SignalServiceContent content) {
-        if (!envelope.isUnidentifiedSender() && envelope.hasSourceUuid()) {
-            return envelope.getSourceAddress();
+        final var serviceId = envelope.getSourceServiceId().map(ServiceId::parseOrNull).orElse(null);
+        if (!envelope.isUnidentifiedSender() && serviceId != null) {
+            return new SignalServiceAddress(serviceId);
         } else if (content != null) {
             return content.getSender();
         } else {
@@ -970,28 +951,25 @@ public final class IncomingMessageHandler {
     }
 
     private DeviceAddress getSender(SignalServiceEnvelope envelope, SignalServiceContent content) {
-        if (!envelope.isUnidentifiedSender() && envelope.hasSourceUuid()) {
-            return new DeviceAddress(context.getRecipientHelper().resolveRecipient(envelope.getSourceAddress()),
-                    envelope.getSourceAddress().getServiceId(),
+        final var serviceId = envelope.getSourceServiceId().map(ServiceId::parseOrNull).orElse(null);
+        if (!envelope.isUnidentifiedSender() && serviceId != null) {
+            return new DeviceAddress(account.getRecipientResolver().resolveRecipient(serviceId),
+                    serviceId,
                     envelope.getSourceDevice());
         } else {
-            return new DeviceAddress(context.getRecipientHelper().resolveRecipient(content.getSender()),
+            return new DeviceAddress(account.getRecipientResolver().resolveRecipient(content.getSender()),
                     content.getSender().getServiceId(),
                     content.getSenderDevice());
         }
     }
 
     private DeviceAddress getDestination(SignalServiceEnvelope envelope) {
-        if (!envelope.hasDestinationUuid()) {
-            return new DeviceAddress(account.getSelfRecipientId(), account.getAci(), account.getDeviceId());
-        }
-        final var addressOptional = SignalServiceAddress.fromRaw(envelope.getDestinationUuid(), null);
-        if (addressOptional.isEmpty()) {
+        final var destination = envelope.getDestinationServiceId();
+        if (destination == null || destination.isUnknown()) {
             return new DeviceAddress(account.getSelfRecipientId(), account.getAci(), account.getDeviceId());
         }
-        final var address = addressOptional.get();
-        return new DeviceAddress(context.getRecipientHelper().resolveRecipient(address),
-                address.getServiceId(),
+        return new DeviceAddress(account.getRecipientResolver().resolveRecipient(destination),
+                destination,
                 account.getDeviceId());
     }