Skip to content

Commit

Permalink
hmac key updates
Browse files Browse the repository at this point in the history
  • Loading branch information
nplasterer committed Dec 20, 2024
1 parent f06a0cd commit 49969e8
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.xmtp.android.library.messages.PrivateKey
import org.xmtp.android.library.messages.PrivateKeyBuilder
import org.xmtp.android.library.messages.walletAddress
import java.time.Instant

@RunWith(AndroidJUnit4::class)
class ConversationsTest {
Expand Down Expand Up @@ -186,4 +188,24 @@ class ConversationsTest {
assertEquals(2, allMessages.size)
job.cancel()
}

@Test
fun testReturnsAllHMACKeys() {
val conversations = mutableListOf<Conversation>()
repeat(5) {
val account = PrivateKeyBuilder()
val client = runBlocking { Client().create(account, fixtures.clientOptions) }
runBlocking {
conversations.add(
alixClient.conversations.newConversation(client.address)
)
}
}
val hmacKeys = alixClient.conversations.getHmacKeys()

val topics = hmacKeys.hmacKeysMap.keys
conversations.forEach { convo ->
assertTrue(topics.contains(convo.topic))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ class HistorySyncTest {
assertEquals(state.installations.size, 2)

runBlocking {
alixClient2.preferences.syncConsent()
Thread.sleep(2000)
alixClient.conversations.syncAllConversations()
Thread.sleep(2000)
alixClient2.conversations.syncAllConversations()
Expand Down Expand Up @@ -125,8 +123,7 @@ class HistorySyncTest {
runBlocking {
alix2Group.send("A message")
alix2Group.send("A second message")
alixClient3.requestMessageHistorySync()
Thread.sleep(1000)
Thread.sleep(2000)
alixClient.conversations.syncAllConversations()
Thread.sleep(2000)
alixClient2.conversations.syncAllConversations()
Expand Down
4 changes: 0 additions & 4 deletions library/src/main/java/org/xmtp/android/library/Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -386,10 +386,6 @@ class Client() {
ffiClient.dbReconnect()
}

suspend fun requestMessageHistorySync() {
ffiClient.sendSyncRequest(FfiDeviceSyncKind.MESSAGES)
}

suspend fun inboxStatesForInboxIds(
refreshFromNetwork: Boolean,
inboxIds: List<String>,
Expand Down
39 changes: 37 additions & 2 deletions library/src/main/java/org/xmtp/android/library/Conversations.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.xmtp.android.library

import android.util.Log
import com.google.protobuf.kotlin.toByteString
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.launch
import org.xmtp.android.library.libxmtp.Message
import org.xmtp.android.library.messages.Topic
import org.xmtp.proto.keystore.api.v1.Keystore
import uniffi.xmtpv3.FfiConversation
import uniffi.xmtpv3.FfiConversationCallback
import uniffi.xmtpv3.FfiConversationType
Expand All @@ -20,6 +23,7 @@ import uniffi.xmtpv3.FfiMessage
import uniffi.xmtpv3.FfiMessageCallback
import uniffi.xmtpv3.FfiPermissionPolicySet
import uniffi.xmtpv3.FfiSubscribeException
import uniffi.xmtpv3.FfiXmtpClient
import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.GroupPermissionPreconfiguration
import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.PermissionPolicySet
import java.util.Date
Expand Down Expand Up @@ -131,7 +135,11 @@ data class Conversations(

// Sync all new and existing conversations data from the network
suspend fun syncAllConversations(consentState: ConsentState? = null): UInt {
return ffiConversations.syncAllConversations(consentState?.let { ConsentState.toFfiConsentState(it) })
return ffiConversations.syncAllConversations(consentState?.let {
ConsentState.toFfiConsentState(
it
)
})
}

suspend fun newConversation(peerAddress: String): Conversation {
Expand Down Expand Up @@ -264,7 +272,15 @@ data class Conversations(
override fun onConversation(conversation: FfiConversation) {
launch(Dispatchers.IO) {
when (conversation.conversationType()) {
FfiConversationType.DM -> trySend(Conversation.Dm(Dm(client, conversation)))
FfiConversationType.DM -> trySend(
Conversation.Dm(
Dm(
client,
conversation
)
)
)

else -> trySend(Conversation.Group(Group(client, conversation)))
}
}
Expand Down Expand Up @@ -305,4 +321,23 @@ data class Conversations(

awaitClose { stream.end() }
}

fun getHmacKeys(): Keystore.GetConversationHmacKeysResponse {
val hmacKeysResponse = Keystore.GetConversationHmacKeysResponse.newBuilder()
val conversations = ffiConversations.getHmacKeys()
conversations.iterator().forEach {
val hmacKeys = Keystore.GetConversationHmacKeysResponse.HmacKeys.newBuilder()
it.value.forEach { key ->
val hmacKeyData = Keystore.GetConversationHmacKeysResponse.HmacKeyData.newBuilder()
hmacKeyData.hmacKey = key.key.toByteString()
hmacKeyData.thirtyDayPeriodsSinceEpoch = key.epoch.toInt()
hmacKeys.addValues(hmacKeyData)
}
hmacKeysResponse.putHmacKeys(
Topic.groupMessage(it.key.toHex()).description,
hmacKeys.build()
)
}
return hmacKeysResponse.build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,6 @@ data class PrivatePreferences(
var client: Client,
private val ffiClient: FfiXmtpClient,
) {
suspend fun syncConsent() {
ffiClient.sendSyncRequest(FfiDeviceSyncKind.CONSENT)
}

suspend fun streamConsent(): Flow<ConsentRecord> = callbackFlow {
val consentCallback = object : FfiConsentCallback {
override fun onConsentUpdate(consent: List<FfiConsent>) {
Expand Down
90 changes: 64 additions & 26 deletions library/src/main/java/xmtpv3.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,10 @@ internal interface UniffiLib : Library {
`ptr`: Pointer, `accountAddresses`: RustBuffer.ByValue, `opts`: RustBuffer.ByValue,
): Long

fun uniffi_xmtpv3_fn_method_fficonversations_get_hmac_keys(
`ptr`: Pointer, uniffi_out_err: UniffiRustCallStatus,
): RustBuffer.ByValue

fun uniffi_xmtpv3_fn_method_fficonversations_get_sync_group(
`ptr`: Pointer, uniffi_out_err: UniffiRustCallStatus,
): Pointer
Expand Down Expand Up @@ -1511,10 +1515,6 @@ internal interface UniffiLib : Library {
`ptr`: Pointer, `entityType`: RustBuffer.ByValue, `entity`: RustBuffer.ByValue,
): Long

fun uniffi_xmtpv3_fn_method_ffixmtpclient_get_hmac_keys(
`ptr`: Pointer, uniffi_out_err: UniffiRustCallStatus,
): RustBuffer.ByValue

fun uniffi_xmtpv3_fn_method_ffixmtpclient_get_latest_inbox_state(
`ptr`: Pointer, `inboxId`: RustBuffer.ByValue,
): Long
Expand Down Expand Up @@ -2103,6 +2103,9 @@ internal interface UniffiLib : Library {
fun uniffi_xmtpv3_checksum_method_fficonversations_create_group(
): Short

fun uniffi_xmtpv3_checksum_method_fficonversations_get_hmac_keys(
): Short

fun uniffi_xmtpv3_checksum_method_fficonversations_get_sync_group(
): Short

Expand Down Expand Up @@ -2256,9 +2259,6 @@ internal interface UniffiLib : Library {
fun uniffi_xmtpv3_checksum_method_ffixmtpclient_get_consent_state(
): Short

fun uniffi_xmtpv3_checksum_method_ffixmtpclient_get_hmac_keys(
): Short

fun uniffi_xmtpv3_checksum_method_ffixmtpclient_get_latest_inbox_state(
): Short

Expand Down Expand Up @@ -2519,6 +2519,9 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
if (lib.uniffi_xmtpv3_checksum_method_fficonversations_create_group() != 7282.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_xmtpv3_checksum_method_fficonversations_get_hmac_keys() != 44064.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_xmtpv3_checksum_method_fficonversations_get_sync_group() != 42973.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
Expand Down Expand Up @@ -2672,9 +2675,6 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_get_consent_state() != 58208.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_get_hmac_keys() != 36015.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_xmtpv3_checksum_method_ffixmtpclient_get_latest_inbox_state() != 3165.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
Expand Down Expand Up @@ -5330,6 +5330,8 @@ public interface FfiConversationsInterface {
`opts`: FfiCreateGroupOptions,
): FfiConversation

fun `getHmacKeys`(): Map<kotlin.ByteArray, List<FfiHmacKey>>

fun `getSyncGroup`(): FfiConversation

suspend fun `list`(`opts`: FfiListConversationsOptions): List<FfiConversation>
Expand Down Expand Up @@ -5526,6 +5528,20 @@ open class FfiConversations : Disposable, AutoCloseable, FfiConversationsInterfa
}


@Throws(GenericException::class)
override fun `getHmacKeys`(): Map<kotlin.ByteArray, List<FfiHmacKey>> {
return FfiConverterMapByteArraySequenceTypeFfiHmacKey.lift(
callWithPointer {
uniffiRustCallWithError(GenericException) { _status ->
UniffiLib.INSTANCE.uniffi_xmtpv3_fn_method_fficonversations_get_hmac_keys(
it, _status
)
}
}
)
}


@Throws(GenericException::class)
override fun `getSyncGroup`(): FfiConversation {
return FfiConverterTypeFfiConversation.lift(
Expand Down Expand Up @@ -8783,8 +8799,6 @@ public interface FfiXmtpClientInterface {
`entity`: kotlin.String,
): FfiConsentState

fun `getHmacKeys`(): List<FfiHmacKey>

suspend fun `getLatestInboxState`(`inboxId`: kotlin.String): FfiInboxState

fun `inboxId`(): kotlin.String
Expand Down Expand Up @@ -9203,20 +9217,6 @@ open class FfiXmtpClient : Disposable, AutoCloseable, FfiXmtpClientInterface {
}


@Throws(GenericException::class)
override fun `getHmacKeys`(): List<FfiHmacKey> {
return FfiConverterSequenceTypeFfiHmacKey.lift(
callWithPointer {
uniffiRustCallWithError(GenericException) { _status ->
UniffiLib.INSTANCE.uniffi_xmtpv3_fn_method_ffixmtpclient_get_hmac_keys(
it, _status
)
}
}
)
}


@Throws(GenericException::class)
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
override suspend fun `getLatestInboxState`(`inboxId`: kotlin.String): FfiInboxState {
Expand Down Expand Up @@ -12078,6 +12078,44 @@ public object FfiConverterMapStringBoolean :
}


/**
* @suppress
*/
public object FfiConverterMapByteArraySequenceTypeFfiHmacKey :
FfiConverterRustBuffer<Map<kotlin.ByteArray, List<FfiHmacKey>>> {
override fun read(buf: ByteBuffer): Map<kotlin.ByteArray, List<FfiHmacKey>> {
val len = buf.getInt()
return buildMap<kotlin.ByteArray, List<FfiHmacKey>>(len) {
repeat(len) {
val k = FfiConverterByteArray.read(buf)
val v = FfiConverterSequenceTypeFfiHmacKey.read(buf)
this[k] = v
}
}
}

override fun allocationSize(value: Map<kotlin.ByteArray, List<FfiHmacKey>>): ULong {
val spaceForMapSize = 4UL
val spaceForChildren = value.map { (k, v) ->
FfiConverterByteArray.allocationSize(k) +
FfiConverterSequenceTypeFfiHmacKey.allocationSize(v)
}.sum()
return spaceForMapSize + spaceForChildren
}

override fun write(value: Map<kotlin.ByteArray, List<FfiHmacKey>>, buf: ByteBuffer) {
buf.putInt(value.size)
// The parens on `(k, v)` here ensure we're calling the right method,
// which is important for compatibility with older android devices.
// Ref https://blog.danlew.net/2017/03/16/kotlin-puzzler-whose-line-is-it-anyways/
value.forEach { (k, v) ->
FfiConverterByteArray.write(k, buf)
FfiConverterSequenceTypeFfiHmacKey.write(v, buf)
}
}
}


@Throws(GenericException::class)
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
suspend fun `connectToBackend`(`host`: kotlin.String, `isSecure`: kotlin.Boolean): XmtpApiClient {
Expand Down

0 comments on commit 49969e8

Please sign in to comment.