diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/push/MessageSender.java b/service/src/main/java/org/whispersystems/textsecuregcm/push/MessageSender.java index f6ba204b8..081f16670 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/push/MessageSender.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/push/MessageSender.java @@ -70,7 +70,7 @@ public void sendMessage(final Account account, final Device device, final Envelo if (clientPresent) { messagesManager.insert(account.getUuid(), device.getId(), message.toBuilder().setEphemeral(true).build()); } else { - messagesManager.removeRecipientViewFromMrmData(account.getUuid(), device.getId(), message); + messagesManager.removeRecipientViewFromMrmData(device.getId(), message); } } else { messagesManager.insert(account.getUuid(), device.getId(), message); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesCache.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesCache.java index 40e0327cc..9cfa4ee90 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesCache.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesCache.java @@ -48,7 +48,6 @@ import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicMessagesConfiguration; import org.whispersystems.textsecuregcm.entities.MessageProtos; import org.whispersystems.textsecuregcm.experiment.Experiment; -import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.metrics.MetricsUtil; import org.whispersystems.textsecuregcm.redis.FaultTolerantPubSubConnection; @@ -296,21 +295,25 @@ public CompletableFuture> remove(final UUID destinationUuid .thenApplyAsync(serialized -> { final List removedMessages = new ArrayList<>(serialized.size()); - final List sharedMrmKeysToUpdate = new ArrayList<>(); + final Map> serviceIdentifierToMrmKeys = new HashMap<>(); for (final byte[] bytes : serialized) { try { final MessageProtos.Envelope envelope = MessageProtos.Envelope.parseFrom(bytes); removedMessages.add(RemovedMessage.fromEnvelope(envelope)); if (envelope.hasSharedMrmKey()) { - sharedMrmKeysToUpdate.add(envelope.getSharedMrmKey().toByteArray()); + serviceIdentifierToMrmKeys.computeIfAbsent( + ServiceIdentifier.valueOf(envelope.getDestinationServiceId()), ignored -> new ArrayList<>()) + .add(envelope.getSharedMrmKey().toByteArray()); } } catch (final InvalidProtocolBufferException e) { logger.warn("Failed to parse envelope", e); } } - removeRecipientViewFromMrmData(sharedMrmKeysToUpdate, destinationUuid, destinationDevice); + serviceIdentifierToMrmKeys.forEach( + (serviceId, keysToUpdate) -> removeRecipientViewFromMrmData(keysToUpdate, serviceId, destinationDevice)); + return removedMessages; }, messageDeletionExecutorService).whenComplete((ignored, throwable) -> sample.stop(removeByGuidTimer)); @@ -472,7 +475,8 @@ private Mono maybeRunMrmViewExperiment(final MessageProtos.Envelope mrmMessag /** * Makes a best-effort attempt at asynchronously updating (and removing when empty) the MRM data structure */ - void removeRecipientViewFromMrmData(final List sharedMrmKeys, final UUID accountUuid, final byte deviceId) { + void removeRecipientViewFromMrmData(final List sharedMrmKeys, final ServiceIdentifier serviceIdentifier, + final byte deviceId) { if (sharedMrmKeys.isEmpty()) { return; @@ -483,7 +487,7 @@ void removeRecipientViewFromMrmData(final List sharedMrmKeys, final UUID .collectMultimap(SlotHash::getSlot) .flatMapMany(slotsAndKeys -> Flux.fromIterable(slotsAndKeys.values())) .flatMap( - keys -> removeRecipientViewFromMrmDataScript.execute(keys, new AciServiceIdentifier(accountUuid), deviceId), + keys -> removeRecipientViewFromMrmDataScript.execute(keys, serviceIdentifier, deviceId), REMOVE_MRM_RECIPIENT_VIEW_CONCURRENCY) .doOnNext(sharedMrmDataKeyRemovedCounter::increment) .onErrorResume(e -> { @@ -575,7 +579,7 @@ public CompletableFuture clear(final UUID destinationUuid, final byte devi return Mono.empty(); } - final List mrmKeys = new ArrayList<>(messagesToProcess.size()); + final Map> serviceIdentifierToMrmKeys = new HashMap<>(); final List processedMessages = new ArrayList<>(messagesToProcess.size()); for (byte[] serialized : messagesToProcess) { try { @@ -584,14 +588,17 @@ public CompletableFuture clear(final UUID destinationUuid, final byte devi processedMessages.add(message.getServerGuid()); if (message.hasSharedMrmKey()) { - mrmKeys.add(message.getSharedMrmKey().toByteArray()); + serviceIdentifierToMrmKeys.computeIfAbsent(ServiceIdentifier.valueOf(message.getDestinationServiceId()), + ignored -> new ArrayList<>()) + .add(message.getSharedMrmKey().toByteArray()); } } catch (final InvalidProtocolBufferException e) { logger.warn("Failed to parse envelope", e); } } - removeRecipientViewFromMrmData(mrmKeys, destinationUuid, deviceId); + serviceIdentifierToMrmKeys.forEach((serviceId, keysToUpdate) -> + removeRecipientViewFromMrmData(keysToUpdate, serviceId, deviceId)); return removeQueueScript.execute(destinationUuid, deviceId, processedMessages); }) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesCacheRemoveRecipientViewFromMrmDataScript.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesCacheRemoveRecipientViewFromMrmDataScript.java index ada2b651c..7307916a9 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesCacheRemoveRecipientViewFromMrmDataScript.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesCacheRemoveRecipientViewFromMrmDataScript.java @@ -10,7 +10,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; +import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.redis.ClusterLuaScript; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster; import reactor.core.publisher.Mono; @@ -30,8 +30,9 @@ class MessagesCacheRemoveRecipientViewFromMrmDataScript { "lua/remove_recipient_view_from_mrm_data.lua", ScriptOutputType.INTEGER); } - Mono execute(final Collection keysCollection, final AciServiceIdentifier serviceIdentifier, + Mono execute(final Collection keysCollection, final ServiceIdentifier serviceIdentifier, final byte deviceId) { + final List keys = keysCollection instanceof List ? (List) keysCollection : new ArrayList<>(keysCollection); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesManager.java index fa25a270f..c56e824b7 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesManager.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/MessagesManager.java @@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.entities.MessageProtos; import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope; +import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.metrics.MetricsUtil; import org.whispersystems.textsecuregcm.util.Pair; import reactor.core.observability.micrometer.Micrometer; @@ -214,10 +215,10 @@ public byte[] insertSharedMultiRecipientMessagePayload( /** * Removes the recipient's view from shared MRM data if necessary */ - public void removeRecipientViewFromMrmData(final UUID destinationUuid, final byte destinationDeviceId, - final Envelope message) { + public void removeRecipientViewFromMrmData(final byte destinationDeviceId, final Envelope message) { if (message.hasSharedMrmKey()) { - messagesCache.removeRecipientViewFromMrmData(List.of(message.getSharedMrmKey().toByteArray()), destinationUuid, + messagesCache.removeRecipientViewFromMrmData(List.of(message.getSharedMrmKey().toByteArray()), + ServiceIdentifier.valueOf(message.getDestinationServiceId()), destinationDeviceId); } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/push/MessageSenderTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/push/MessageSenderTest.java index ea7174384..257ffd7bc 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/push/MessageSenderTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/push/MessageSenderTest.java @@ -73,8 +73,7 @@ void testSendOnlineMessageClientPresent() throws Exception { MessageProtos.Envelope.class); verify(messagesManager).insert(any(), anyByte(), envelopeArgumentCaptor.capture()); - verify(messagesManager, never()).removeRecipientViewFromMrmData(any(), anyByte(), - any(MessageProtos.Envelope.class)); + verify(messagesManager, never()).removeRecipientViewFromMrmData(anyByte(), any(MessageProtos.Envelope.class)); assertTrue(envelopeArgumentCaptor.getValue().getEphemeral()); @@ -96,7 +95,7 @@ void testSendOnlineMessageClientNotPresent(final boolean hasSharedMrmKey) throws } verify(messagesManager, never()).insert(any(), anyByte(), any()); - verify(messagesManager).removeRecipientViewFromMrmData(any(), anyByte(), any(MessageProtos.Envelope.class)); + verify(messagesManager).removeRecipientViewFromMrmData(anyByte(), any(MessageProtos.Envelope.class)); verifyNoInteractions(pushNotificationManager); } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScriptTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScriptTest.java index c5f61e8c6..fb5a9b8d9 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScriptTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScriptTest.java @@ -8,6 +8,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import io.lettuce.core.RedisCommandExecutionException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -15,13 +16,13 @@ import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.IntStream; -import io.lettuce.core.RedisCommandExecutionException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; +import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.redis.RedisClusterExtension; import org.whispersystems.textsecuregcm.util.Pair; @@ -32,7 +33,7 @@ class MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScriptTest { @ParameterizedTest @MethodSource - void testInsert(final int count, final Map> destinations) throws Exception { + void testInsert(final int count, final Map> destinations) throws Exception { final MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScript insertMrmScript = new MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScript( REDIS_CLUSTER_EXTENSION.getRedisCluster()); @@ -49,7 +50,7 @@ void testInsert(final int count, final Map> des } public static List testInsert() { - final Map> singleAccount = Map.of( + final Map> singleAccount = Map.of( new AciServiceIdentifier(UUID.randomUUID()), List.of((byte) 1, (byte) 2)); final List testCases = new ArrayList<>(); @@ -58,7 +59,7 @@ public static List testInsert() { for (int j = 1000; j <= 30000; j += 1000) { final Map> deviceLists = new HashMap<>(); - final Map> manyAccounts = IntStream.range(0, j) + final Map> manyAccounts = IntStream.range(0, j) .mapToObj(i -> { final int deviceCount = 1 + i % 5; final List devices = deviceLists.computeIfAbsent(deviceCount, count -> IntStream.rangeClosed(1, count) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheRemoveRecipientViewFromMrmDataScriptTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheRemoveRecipientViewFromMrmDataScriptTest.java index 8f623abdd..af3c823c3 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheRemoveRecipientViewFromMrmDataScriptTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheRemoveRecipientViewFromMrmDataScriptTest.java @@ -22,6 +22,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; +import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.redis.RedisClusterExtension; import org.whispersystems.textsecuregcm.util.Pair; import reactor.core.publisher.Flux; @@ -34,7 +35,7 @@ class MessagesCacheRemoveRecipientViewFromMrmDataScriptTest { @ParameterizedTest @MethodSource - void testUpdateSingleKey(final Map> destinations) throws Exception { + void testUpdateSingleKey(final Map> destinations) throws Exception { final MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScript insertMrmScript = new MessagesCacheInsertSharedMultiRecipientPayloadAndViewsScript( REDIS_CLUSTER_EXTENSION.getRedisCluster()); @@ -48,8 +49,8 @@ void testUpdateSingleKey(final Map> destination final long keysRemoved = Objects.requireNonNull(Flux.fromIterable(destinations.entrySet()) .flatMap(e -> Flux.fromStream(e.getValue().stream().map(deviceId -> Tuples.of(e.getKey(), deviceId)))) - .flatMap(aciServiceIdentifierByteTuple -> removeRecipientViewFromMrmDataScript.execute(List.of(sharedMrmKey), - aciServiceIdentifierByteTuple.getT1(), aciServiceIdentifierByteTuple.getT2())) + .flatMap(serviceIdentifierByteTuple -> removeRecipientViewFromMrmDataScript.execute(List.of(sharedMrmKey), + serviceIdentifierByteTuple.getT1(), serviceIdentifierByteTuple.getT2())) .reduce(Long::sum) .block(Duration.ofSeconds(35))); @@ -60,18 +61,18 @@ void testUpdateSingleKey(final Map> destination assertEquals(0, keyExists); } - public static List>> testUpdateSingleKey() { - final Map> singleAccount = Map.of( + public static List>> testUpdateSingleKey() { + final Map> singleAccount = Map.of( new AciServiceIdentifier(UUID.randomUUID()), List.of((byte) 1, (byte) 2)); - final List>> testCases = new ArrayList<>(); + final List>> testCases = new ArrayList<>(); testCases.add(singleAccount); // Generate a more, from smallish to very large for (int j = 1000; j <= 81000; j *= 3) { final Map> deviceLists = new HashMap<>(); - final Map> manyAccounts = IntStream.range(0, j) + final Map> manyAccounts = IntStream.range(0, j) .mapToObj(i -> { final int deviceCount = 1 + i % 5; final List devices = deviceLists.computeIfAbsent(deviceCount, count -> IntStream.rangeClosed(1, count) @@ -93,7 +94,7 @@ public static List>> testUpdateSingleKey() void testUpdateManyKeys(int keyCount) throws Exception { final List sharedMrmKeys = new ArrayList<>(keyCount); - final AciServiceIdentifier aciServiceIdentifier = new AciServiceIdentifier(UUID.randomUUID()); + final ServiceIdentifier serviceIdentifier = new AciServiceIdentifier(UUID.randomUUID()); final byte deviceId = 1; for (int i = 0; i < keyCount; i++) { @@ -103,7 +104,7 @@ void testUpdateManyKeys(int keyCount) throws Exception { final byte[] sharedMrmKey = MessagesCache.getSharedMrmKey(UUID.randomUUID()); insertMrmScript.execute(sharedMrmKey, - MessagesCacheTest.generateRandomMrmMessage(aciServiceIdentifier, deviceId)); + MessagesCacheTest.generateRandomMrmMessage(serviceIdentifier, deviceId)); sharedMrmKeys.add(sharedMrmKey); } @@ -114,7 +115,7 @@ void testUpdateManyKeys(int keyCount) throws Exception { final long keysRemoved = Objects.requireNonNull(Flux.fromIterable(sharedMrmKeys) .collectMultimap(SlotHash::getSlot) .flatMapMany(slotsAndKeys -> Flux.fromIterable(slotsAndKeys.values())) - .flatMap(keys -> removeRecipientViewFromMrmDataScript.execute(keys, aciServiceIdentifier, deviceId)) + .flatMap(keys -> removeRecipientViewFromMrmDataScript.execute(keys, serviceIdentifier, deviceId)) .reduce(Long::sum) .block(Duration.ofSeconds(5))); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheTest.java index 700b16a8c..c5fd61bd0 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/MessagesCacheTest.java @@ -71,6 +71,7 @@ import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicMessagesConfiguration; import org.whispersystems.textsecuregcm.entities.MessageProtos; import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; +import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster; import org.whispersystems.textsecuregcm.redis.RedisClusterExtension; import org.whispersystems.textsecuregcm.tests.util.RedisClusterHelper; @@ -565,11 +566,10 @@ void testAvailabilityListenerResponses() { @ParameterizedTest @ValueSource(booleans = {true, false}) void testMultiRecipientMessage(final boolean sharedMrmKeyPresent) throws Exception { - final UUID destinationUuid = UUID.randomUUID(); + final ServiceIdentifier destinationServiceId = new AciServiceIdentifier(UUID.randomUUID()); final byte deviceId = 1; - final SealedSenderMultiRecipientMessage mrm = generateRandomMrmMessage( - new AciServiceIdentifier(destinationUuid), deviceId); + final SealedSenderMultiRecipientMessage mrm = generateRandomMrmMessage(destinationServiceId, deviceId); final byte[] sharedMrmDataKey; if (sharedMrmKeyPresent) { @@ -579,35 +579,35 @@ void testMultiRecipientMessage(final boolean sharedMrmKeyPresent) throws Excepti } final UUID guid = UUID.randomUUID(); - final MessageProtos.Envelope message = generateRandomMessage(guid, true) + final MessageProtos.Envelope message = generateRandomMessage(guid, destinationServiceId, true) .toBuilder() // clear some things added by the helper .clearServerGuid() // mrm views phase 1: messages have content .setContent( - ByteString.copyFrom(mrm.messageForRecipient(mrm.getRecipients().get(new ServiceId.Aci(destinationUuid))))) + ByteString.copyFrom(mrm.messageForRecipient(mrm.getRecipients().get(destinationServiceId.toLibsignal())))) .setSharedMrmKey(ByteString.copyFrom(sharedMrmDataKey)) .build(); - messagesCache.insert(guid, destinationUuid, deviceId, message); + messagesCache.insert(guid, destinationServiceId.uuid(), deviceId, message); assertEquals(sharedMrmKeyPresent ? 1 : 0, (long) REDIS_CLUSTER_EXTENSION.getRedisCluster() .withBinaryCluster(conn -> conn.sync().exists(sharedMrmDataKey))); - final List messages = get(destinationUuid, deviceId, 1); + final List messages = get(destinationServiceId.uuid(), deviceId, 1); assertEquals(1, messages.size()); assertEquals(guid, UUID.fromString(messages.getFirst().getServerGuid())); assertFalse(messages.getFirst().hasSharedMrmKey()); final SealedSenderMultiRecipientMessage.Recipient recipient = mrm.getRecipients() - .get(new ServiceId.Aci(destinationUuid)); + .get(destinationServiceId.toLibsignal()); assertArrayEquals(mrm.messageForRecipient(recipient), messages.getFirst().getContent().toByteArray()); - final Optional removedMessage = messagesCache.remove(destinationUuid, deviceId, guid) + final Optional removedMessage = messagesCache.remove(destinationServiceId.uuid(), deviceId, guid) .join(); assertTrue(removedMessage.isPresent()); assertEquals(guid, UUID.fromString(removedMessage.get().serverGuid().toString())); - assertTrue(get(destinationUuid, deviceId, 1).isEmpty()); + assertTrue(get(destinationServiceId.uuid(), deviceId, 1).isEmpty()); // updating the shared MRM data is purely async, so we just wait for it assertTimeoutPreemptively(Duration.ofSeconds(1), () -> { @@ -874,10 +874,17 @@ private List generateStaleEphemeralPage() { } private MessageProtos.Envelope generateRandomMessage(final UUID messageGuid, final boolean sealedSender) { - return generateRandomMessage(messageGuid, sealedSender, serialTimestamp++); + return generateRandomMessage(messageGuid, new AciServiceIdentifier(UUID.randomUUID()), sealedSender, + serialTimestamp++); } - private MessageProtos.Envelope generateRandomMessage(final UUID messageGuid, final boolean sealedSender, + private MessageProtos.Envelope generateRandomMessage(final UUID messageGuid, + final ServiceIdentifier destinationServiceId, final boolean sealedSender) { + return generateRandomMessage(messageGuid, destinationServiceId, sealedSender, serialTimestamp++); + } + + private MessageProtos.Envelope generateRandomMessage(final UUID messageGuid, + final ServiceIdentifier destinationServiceId, final boolean sealedSender, final long timestamp) { final MessageProtos.Envelope.Builder envelopeBuilder = MessageProtos.Envelope.newBuilder() .setClientTimestamp(timestamp) @@ -885,7 +892,7 @@ private MessageProtos.Envelope generateRandomMessage(final UUID messageGuid, fin .setContent(ByteString.copyFromUtf8(RandomStringUtils.randomAlphanumeric(256))) .setType(MessageProtos.Envelope.Type.CIPHERTEXT) .setServerGuid(messageGuid.toString()) - .setDestinationServiceId(UUID.randomUUID().toString()); + .setDestinationServiceId(destinationServiceId.toServiceIdentifierString()); if (!sealedSender) { envelopeBuilder.setSourceDevice(random.nextInt(Device.MAXIMUM_DEVICE_ID) + 1) @@ -896,8 +903,7 @@ private MessageProtos.Envelope generateRandomMessage(final UUID messageGuid, fin } static SealedSenderMultiRecipientMessage generateRandomMrmMessage( - Map> destinations) { - + Map> destinations) { try { final ByteBuffer prefix = ByteBuffer.allocate(7); @@ -907,10 +913,10 @@ static SealedSenderMultiRecipientMessage generateRandomMrmMessage( List recipients = new ArrayList<>(destinations.size()); - for (Map.Entry> aciServiceIdentifierAndDeviceIds : destinations.entrySet()) { + for (Map.Entry> serviceIdentifierAndDeviceIds : destinations.entrySet()) { - final AciServiceIdentifier destination = aciServiceIdentifierAndDeviceIds.getKey(); - final List deviceIds = aciServiceIdentifierAndDeviceIds.getValue(); + final ServiceIdentifier destination = serviceIdentifierAndDeviceIds.getKey(); + final List deviceIds = serviceIdentifierAndDeviceIds.getValue(); assert deviceIds.size() < 255; @@ -946,10 +952,10 @@ static SealedSenderMultiRecipientMessage generateRandomMrmMessage( } } - static SealedSenderMultiRecipientMessage generateRandomMrmMessage(AciServiceIdentifier destination, + static SealedSenderMultiRecipientMessage generateRandomMrmMessage(ServiceIdentifier destination, byte... deviceIds) { - final Map> destinations = new HashMap<>(); + final Map> destinations = new HashMap<>(); destinations.put(destination, Arrays.asList(ArrayUtils.toObject(deviceIds))); return generateRandomMrmMessage(destinations); }