Skip to content

Commit effc4f5

Browse files
nplastererElise Alix
and
Elise Alix
authored
Improve sharedSecret performance backed by Rust (#75)
* add api client with grpc kotlin * add bench marking for performance debugging * is it a macOS issue * add a integration test instead * identified the performance spot * back by rust * remove unused imports * remove the test * fix up the linter * fix api level * move tests around to work with jna * remove unused imports * add back stream tests * add back test * fix linter issue * update attachmentTest * add the so files * add the correct SO files * remove perf test --------- Co-authored-by: Elise Alix <elise@xmtp.com>
1 parent 6e16bfe commit effc4f5

20 files changed

+841
-163
lines changed

library/build.gradle

+3-2
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,13 @@ dependencies {
7878
implementation 'io.grpc:grpc-protobuf-lite:1.51.0'
7979
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
8080
implementation 'org.web3j:crypto:5.0.0'
81+
implementation "net.java.dev.jna:jna:5.13.0@aar"
8182
api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3'
8283
api 'org.xmtp:proto-kotlin:3.23.2'
8384

84-
testImplementation 'app.cash.turbine:turbine:0.12.1'
8585
testImplementation 'junit:junit:4.13.2'
86-
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4'
86+
androidTestImplementation 'app.cash.turbine:turbine:0.12.1'
87+
androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4'
8788
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
8889
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
8990
}

library/proguard-rules.pro

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@
1818

1919
# If you keep the line number information, uncomment this to
2020
# hide the original source file name.
21-
#-renamesourcefileattribute SourceFile
21+
#-renamesourcefileattribute SourceFile
22+
23+
-dontwarn java.awt.*
24+
-keep class com.sun.jna.* { *; }
25+
-keepclassmembers class * extends com.sun.jna.* { public *; }

library/src/test/java/org/xmtp/android/library/AttachmentTest.kt library/src/androidTest/java/org/xmtp/android/library/AttachmentTest.kt

+3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package org.xmtp.android.library
22

3+
import androidx.test.ext.junit.runners.AndroidJUnit4
34
import com.google.protobuf.kotlin.toByteStringUtf8
45
import org.junit.Assert.assertEquals
56
import org.junit.Test
7+
import org.junit.runner.RunWith
68
import org.xmtp.android.library.codecs.Attachment
79
import org.xmtp.android.library.codecs.AttachmentCodec
810
import org.xmtp.android.library.codecs.ContentTypeAttachment
911
import org.xmtp.android.library.messages.walletAddress
1012

13+
@RunWith(AndroidJUnit4::class)
1114
class AttachmentTest {
1215
@Test
1316
fun testCanUseAttachmentCodec() {

library/src/test/java/org/xmtp/android/library/CodecTest.kt library/src/androidTest/java/org/xmtp/android/library/CodecTest.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package org.xmtp.android.library
22

3+
import androidx.test.ext.junit.runners.AndroidJUnit4
34
import com.google.protobuf.kotlin.toByteStringUtf8
45
import org.junit.Assert.assertEquals
56
import org.junit.Test
7+
import org.junit.runner.RunWith
68
import org.xmtp.android.library.codecs.CompositeCodec
79
import org.xmtp.android.library.codecs.ContentCodec
810
import org.xmtp.android.library.codecs.ContentTypeId
@@ -35,7 +37,7 @@ data class NumberCodec(
3537
override fun decode(content: EncodedContent): Double =
3638
content.content.toStringUtf8().filter { it.isDigit() || it == '.' }.toDouble()
3739
}
38-
40+
@RunWith(AndroidJUnit4::class)
3941
class CodecTest {
4042

4143
@Test

library/src/test/java/org/xmtp/android/library/ConversationTest.kt library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt

+45-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package org.xmtp.android.library
22

3+
import androidx.test.ext.junit.runners.AndroidJUnit4
34
import app.cash.turbine.test
5+
import com.google.protobuf.kotlin.toByteString
46
import kotlinx.coroutines.ExperimentalCoroutinesApi
5-
import kotlinx.coroutines.test.runTest
7+
import org.junit.Assert
68
import org.junit.Assert.assertEquals
79
import org.junit.Assert.assertThrows
810
import org.junit.Before
911
import org.junit.Test
12+
import org.junit.runner.RunWith
1013
import org.web3j.crypto.Hash
1114
import org.xmtp.android.library.codecs.TextCodec
1215
import org.xmtp.android.library.messages.EnvelopeBuilder
@@ -37,6 +40,7 @@ import java.nio.charset.StandardCharsets
3740
import java.util.Date
3841

3942
@OptIn(ExperimentalCoroutinesApi::class)
43+
@RunWith(AndroidJUnit4::class)
4044
class ConversationTest {
4145
lateinit var fakeApiClient: FakeApiClient
4246
lateinit var aliceWallet: PrivateKeyBuilder
@@ -439,7 +443,7 @@ class ConversationTest {
439443
}
440444

441445
@Test
442-
fun testCanStreamConversationsV2() = runTest {
446+
fun testCanStreamConversationsV2() = kotlinx.coroutines.test.runTest {
443447
bobClient.conversations.stream().test {
444448
val conversation = bobClient.conversations.newConversation(alice.walletAddress)
445449
conversation.send(content = "hi")
@@ -449,7 +453,7 @@ class ConversationTest {
449453
}
450454

451455
@Test
452-
fun testStreamingMessagesFromV1Conversation() = runTest {
456+
fun testStreamingMessagesFromV1Conversation() = kotlinx.coroutines.test.runTest {
453457
// Overwrite contact as legacy
454458
fixtures.publishLegacyContact(client = bobClient)
455459
fixtures.publishLegacyContact(client = aliceClient)
@@ -478,7 +482,7 @@ class ConversationTest {
478482
}
479483

480484
@Test
481-
fun testStreamingMessagesFromV2Conversations() = runTest {
485+
fun testStreamingMessagesFromV2Conversations() = kotlinx.coroutines.test.runTest {
482486
val conversation = aliceClient.conversations.newConversation(bob.walletAddress)
483487
conversation.streamMessages().test {
484488
val encoder = TextCodec()
@@ -504,7 +508,7 @@ class ConversationTest {
504508
}
505509

506510
@Test
507-
fun testStreamAllMessagesGetsMessageFromKnownConversation() = runTest {
511+
fun testStreamAllMessagesGetsMessageFromKnownConversation() = kotlinx.coroutines.test.runTest {
508512
val fixtures = fixtures()
509513
val client = fixtures.aliceClient
510514
val bobConversation = fixtures.bobClient.conversations.newConversation(client.address)
@@ -568,4 +572,40 @@ class ConversationTest {
568572
assertEquals("hi", message.body)
569573
assertEquals(message.id, messageID)
570574
}
575+
576+
@Test
577+
fun testFetchConversation() {
578+
// Generated from JS script
579+
val ints = arrayOf(
580+
31, 116, 198, 193, 189, 122, 19, 254, 191, 189, 211, 215, 255, 131,
581+
171, 239, 243, 33, 4, 62, 143, 86, 18, 195, 251, 61, 128, 90, 34, 126, 219, 236
582+
)
583+
val bytes =
584+
ints.foldIndexed(ByteArray(ints.size)) { i, a, v -> a.apply { set(i, v.toByte()) } }
585+
586+
val key = PrivateKey.newBuilder().also {
587+
it.secp256K1 = it.secp256K1.toBuilder().also { builder ->
588+
builder.bytes = bytes.toByteString()
589+
}.build()
590+
it.publicKey = it.publicKey.toBuilder().also { builder ->
591+
builder.secp256K1Uncompressed =
592+
builder.secp256K1Uncompressed.toBuilder().also { keyBuilder ->
593+
keyBuilder.bytes =
594+
KeyUtil.addUncompressedByte(KeyUtil.getPublicKey(bytes)).toByteString()
595+
}.build()
596+
}.build()
597+
}.build()
598+
599+
val client = Client().create(account = PrivateKeyBuilder(key))
600+
Assert.assertEquals(client.apiClient.environment, XMTPEnvironment.DEV)
601+
val conversations = client.conversations.list()
602+
Assert.assertEquals(1, conversations.size)
603+
val topic = conversations[0].topic
604+
val conversation = client.fetchConversation(topic)
605+
Assert.assertEquals(conversations[0].topic, conversation?.topic)
606+
Assert.assertEquals(conversations[0].peerAddress, conversation?.peerAddress)
607+
608+
val noConversation = client.fetchConversation("invalid_topic")
609+
Assert.assertEquals(null, noConversation)
610+
}
571611
}

library/src/test/java/org/xmtp/android/library/ConversationsTest.kt library/src/androidTest/java/org/xmtp/android/library/ConversationsTest.kt

+3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.xmtp.android.library
22

3+
import androidx.test.ext.junit.runners.AndroidJUnit4
34
import org.junit.Assert.assertEquals
45
import org.junit.Test
6+
import org.junit.runner.RunWith
57
import org.xmtp.android.library.codecs.TextCodec
68
import org.xmtp.android.library.messages.EnvelopeBuilder
79
import org.xmtp.android.library.messages.InvitationV1
@@ -16,6 +18,7 @@ import org.xmtp.android.library.messages.toPublicKeyBundle
1618
import org.xmtp.android.library.messages.walletAddress
1719
import java.util.Date
1820

21+
@RunWith(AndroidJUnit4::class)
1922
class ConversationsTest {
2023

2124
@Test

library/src/test/java/org/xmtp/android/library/InvitationTest.kt library/src/androidTest/java/org/xmtp/android/library/InvitationTest.kt

+35
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
package org.xmtp.android.library
22

3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import com.google.protobuf.kotlin.toByteString
5+
import org.junit.Assert
36
import org.junit.Assert.assertEquals
47
import org.junit.Test
8+
import org.junit.runner.RunWith
59
import org.xmtp.android.library.messages.InvitationV1
10+
import org.xmtp.android.library.messages.PrivateKey
11+
import org.xmtp.android.library.messages.PrivateKeyBuilder
612
import org.xmtp.android.library.messages.PrivateKeyBundleV1
713
import org.xmtp.android.library.messages.SealedInvitation
814
import org.xmtp.android.library.messages.SealedInvitationBuilder
@@ -14,8 +20,37 @@ import org.xmtp.android.library.messages.header
1420
import org.xmtp.android.library.messages.toV2
1521
import java.util.Date
1622

23+
@RunWith(AndroidJUnit4::class)
1724
class InvitationTest {
25+
@Test
26+
fun testExistingWallet() {
27+
// Generated from JS script
28+
val ints = arrayOf(
29+
31, 116, 198, 193, 189, 122, 19, 254, 191, 189, 211, 215, 255, 131,
30+
171, 239, 243, 33, 4, 62, 143, 86, 18, 195, 251, 61, 128, 90, 34, 126, 219, 236
31+
)
32+
val bytes =
33+
ints.foldIndexed(ByteArray(ints.size)) { i, a, v -> a.apply { set(i, v.toByte()) } }
34+
val key = PrivateKey.newBuilder().also {
35+
it.secp256K1 =
36+
it.secp256K1.toBuilder().also { builder -> builder.bytes = bytes.toByteString() }
37+
.build()
38+
it.publicKey = it.publicKey.toBuilder().also { builder ->
39+
builder.secp256K1Uncompressed =
40+
builder.secp256K1Uncompressed.toBuilder().also { keyBuilder ->
41+
keyBuilder.bytes =
42+
KeyUtil.addUncompressedByte(KeyUtil.getPublicKey(bytes)).toByteString()
43+
}.build()
44+
}.build()
45+
}.build()
1846

47+
val client = Client().create(account = PrivateKeyBuilder(key))
48+
Assert.assertEquals(client.apiClient.environment, XMTPEnvironment.DEV)
49+
val conversations = client.conversations.list()
50+
Assert.assertEquals(1, conversations.size)
51+
val message = conversations[0].messages().firstOrNull()
52+
Assert.assertEquals(message?.body, "hello")
53+
}
1954
@Test
2055
fun testGenerateSealedInvitation() {
2156
val aliceWallet = FakeWallet.generate()

library/src/androidTest/java/org/xmtp/android/library/InstrumentedTest.kt library/src/androidTest/java/org/xmtp/android/library/LocalInstrumentedTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import org.xmtp.proto.message.contents.PrivateKeyOuterClass
2525
import java.util.Date
2626

2727
@RunWith(AndroidJUnit4::class)
28-
class InstrumentedTest {
28+
class LocalInstrumentedTest {
2929
@Test
3030
fun testPublishingAndFetchingContactBundlesWithWhileGeneratingKeys() {
3131
val aliceWallet = PrivateKeyBuilder()

0 commit comments

Comments
 (0)