Fix opening chat rooms with users that don't have a valid public key.

This commit is contained in:
Kgothatso Ngako
2026-06-02 21:55:35 +02:00
parent 711d72b09e
commit 9a0e4c77fc
4 changed files with 58 additions and 51 deletions

View File

@@ -352,11 +352,10 @@ abstract class NostrDao(
giftWrapPayload
)
val musig2AggregatedPublicKey = giftWrapPayload.aggregateParticipantsPublicKeys()
if (musig2AggregatedPublicKey != null) {
val chatRoomId = musig2AggregatedPublicKey.publicKey.toHex()
val chatRoomId = giftWrapPayload.aggregatedParticipantsPublicKey()
logger.d("ChatRoomId: $chatRoomId")
logger.d("ChatRoomId: $chatRoomId")
if (chatRoomId != null) {
// Find or create chatRoom
val localChatRoom = database.chatRoomDao().findChatRoomById(
chatRoomId

View File

@@ -8,11 +8,8 @@ import ac.cord.auxiliary.compose.managers.SeedManager
import androidx.room3.Dao
import androidx.room3.Transaction
import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import fr.acinq.bitcoin.PublicKey
import fr.acinq.bitcoin.crypto.musig2.Musig2
import kotlin.math.log
@Dao
abstract class NostrNip17Dao(
@@ -26,38 +23,19 @@ abstract class NostrNip17Dao(
val activePublicKey = SeedManager.activePublicKey().toHexKey()
val hexKeys = listOf(
val hexKeys = setOf(
activePublicKey,
publicKey
).sorted()
logger.d("hexKeys: $hexKeys")
val publicKeys = hexKeys.map {
val publicKey = PublicKey(
PublicKey.compress(it.hexToByteArray())
)
if (publicKey.isValid().not()) {
logger.w("$it is an invalid pubkey: $publicKey")
}
publicKey
}
logger.d("PublicKeys: $publicKeys")
val chatRoomXOnlyPublicKey = Musig2.aggregateKeys(
publicKeys
)
logger.d("ChatRoomXOnly: $chatRoomXOnlyPublicKey")
val chatRoomId = chatRoomXOnlyPublicKey.publicKey.value.toHex()
val chatRoomId = ChatRoom.deriveChatRoomId(hexKeys)
logger.d("chatRoomId: $chatRoomId")
val localChatRoom = database.chatRoomDao().findChatRoomById(chatRoomId)
if (localChatRoom != null) {
return localChatRoom
} else {
val profiles = database.profileDao().getProfileByPublicKeys(hexKeys)
val profiles = database.profileDao().getProfileByPublicKeys(hexKeys.toList())
if (profiles.isNotEmpty()) {
// Create new chatRoom

View File

@@ -6,8 +6,14 @@ import ac.cord.auxiliary.compose.database.model.traits.TimestampedEntity
import ac.cord.auxiliary.compose.database.model.traits.UserViewableEntity
import androidx.room3.Entity
import androidx.room3.ForeignKey
import androidx.room3.Ignore
import androidx.room3.PrimaryKey
import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import fr.acinq.bitcoin.PrivateKey
import fr.acinq.bitcoin.PublicKey
import fr.acinq.bitcoin.crypto.musig2.Musig2
import kotlin.time.Clock
import kotlin.time.Instant
@@ -72,4 +78,45 @@ data class ChatRoom(
override val deletedAt: Instant? = null,
): TimestampedEntity, LocalStoreEntity, UserViewableEntity, SoftDeletableEntity {
companion object {
const val TAG = "ChatRoom"
@Ignore
val logger = Logger.withTag(TAG)
fun deriveChatRoomId(hexKeySet: Set<String>): String {
val hexKeys = hexKeySet.sorted()
logger.d("hexKeys: $hexKeys")
val publicKeys = hexKeys.map {
val publicKey = PublicKey(
PublicKey.compress(it.hexToByteArray())
)
if (publicKey.isValid().not()) {
logger.w("$it is an invalid pubkey (not representing a point on the secp256k1 curve): $publicKey")
// Using it to derive a publicKey
val derivedPublicKey = PrivateKey(
publicKey.xOnly().value
).publicKey()
logger.w("Derived $derivedPublicKey: ${derivedPublicKey.isValid()}")
derivedPublicKey
} else {
publicKey
}
}
logger.d("PublicKeys: $publicKeys")
val chatRoomXOnlyPublicKey = Musig2.aggregateKeys(
publicKeys
)
logger.d("ChatRoomXOnly: $chatRoomXOnlyPublicKey")
return chatRoomXOnlyPublicKey.publicKey.toHex()
}
}
}

View File

@@ -15,7 +15,6 @@ import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
import com.vitorpamplona.quartz.nip14Subject.subject
import fr.acinq.bitcoin.PublicKey
import fr.acinq.bitcoin.XonlyPublicKey
import fr.acinq.bitcoin.crypto.musig2.Musig2
import kotlin.time.Clock
import kotlin.time.Instant
@@ -82,29 +81,12 @@ data class GiftWrapPayload( // TODO: Rename this to GiftWrapPayload...
@Ignore
private val logger = Logger.withTag(TAG)
fun aggregateParticipantsPublicKeys(): XonlyPublicKey? = try {
fun aggregatedParticipantsPublicKey(): String? = try {
logger.d("aggregateParticipantsPublicKeys")
val hexKeys = participantPubKeys()
val hexKeySet = participantPubKeys()
logger.d("HexKeys: $hexKeys")
val publicKeys = hexKeys.map {
val publicKey = PublicKey(
PublicKey.compress(it.hexToByteArray())
)
logger.d("$publicKey: ${publicKey.isValid()}")
publicKey
}
logger.d("PublicKeys: $publicKeys")
val chatRoomXOnlyPublicKey = Musig2.aggregateKeys(
publicKeys
)
logger.d("ChatRoomXOnly: $chatRoomXOnlyPublicKey")
return chatRoomXOnlyPublicKey
return ChatRoom.deriveChatRoomId(hexKeySet)
} catch (e: Throwable) {
logger.e("Failed to aggregate participants publicKeys", e)
return null
@@ -122,6 +104,7 @@ data class GiftWrapPayload( // TODO: Rename this to GiftWrapPayload...
return hexKeys
} catch (e: Throwable) {
logger.e("Failed to get participant public keys", e)
return emptySet()
}