From 9ad0440ffe0f7148628c194b2880caa857cb8a32 Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Fri, 10 Jul 2026 23:35:54 +0200 Subject: [PATCH] only gift wrap to welcomeEvent to keyPackage publisher --- .../database/dao/MarmotKeyPackageDao.kt | 3 + .../repository/DatabaseChatRepository.kt | 114 +++++++++++------- 2 files changed, 75 insertions(+), 42 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotKeyPackageDao.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotKeyPackageDao.kt index 8e5e06f9..4abe5f9b 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotKeyPackageDao.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotKeyPackageDao.kt @@ -12,6 +12,9 @@ interface MarmotKeyPackageDao { @Query("SELECT * FROM MarmotKeyPackage WHERE publicKey = :publicKey ORDER BY createdAt DESC") suspend fun getMarmotKeyPackageForPublicKey(publicKey: HexKey): MarmotKeyPackage? + @Query("SELECT * FROM MarmotKeyPackage WHERE id = :id ORDER BY createdAt DESC") + suspend fun getMarmotKeyPackageById(id: HexKey): MarmotKeyPackage? + @Upsert suspend fun upsert(marmotKeyPackage: MarmotKeyPackage) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/repository/DatabaseChatRepository.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/repository/DatabaseChatRepository.kt index 424bdf75..5a5d98ab 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/repository/DatabaseChatRepository.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/repository/DatabaseChatRepository.kt @@ -20,10 +20,12 @@ import com.vitorpamplona.quartz.nip01Core.core.Kind import com.vitorpamplona.quartz.nip01Core.crypto.EventHasher import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl +import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip17Dm.messages.ChatMessageEvent import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent +import com.vitorpamplona.quartz.nip59Giftwrap.rumors.RumorAssembler import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent import com.vitorpamplona.quartz.nipC7Chats.ChatEvent @@ -256,62 +258,90 @@ class DatabaseChatRepository( nostrSignerSync: NostrSignerSync ) { database.participantDao().findParticipantsByChatRoomId(giftWrapPayload.chatRoomId).forEachIndexed { index, participant -> - if (giftWrapPayload.kind == WelcomeEvent.KIND && nostrSignerSync.pubKey == participant.participantPublicKey) { - logger.w("We shouldn't be gift wrapping welcome event to ourselves (${nostrSignerSync.pubKey}).") - } else { - val wrapperKeyPair = KeyPair() - val wrapperSigner = NostrSignerSync( - keyPair = wrapperKeyPair + if (giftWrapPayload.kind == WelcomeEvent.KIND) { + logger.i("Only giftWrap welcomeEvent payload (${giftWrapPayload.id}) to the participant who published the related keyPackage") + val welcomeEvent = WelcomeEvent( + id = giftWrapPayload.id, + pubKey = nostrSignerSync.pubKey, + tags = giftWrapPayload.tags, + content = giftWrapPayload.content, + createdAt = giftWrapPayload.createdAt.epochSeconds, + sig = "" ) - val giftWrapPayloadEvent = nostrSignerSync.signNormal( + val shouldBeGiftWrapped: Boolean = welcomeEvent.keyPackageEventId()?.let { keyPackageEventId -> + val marmotKeyPackage = database.marmotKeyPackageDao().getMarmotKeyPackageForPublicKey( + keyPackageEventId + ) + + logger.i("MarmoteKeyPackage published by ${marmotKeyPackage?.publicKey}") + + marmotKeyPackage?.publicKey == participant.participantPublicKey + } ?: false + + if (!shouldBeGiftWrapped) { + logger.w("Participant ${participant.participantPublicKey} didn't publish key package for this welcome event") + + return@forEachIndexed + } + } + + val wrapperKeyPair = KeyPair() + val wrapperSigner = NostrSignerSync( + keyPair = wrapperKeyPair + ) + + // TODO: Don't sign the payload... use event template instead... + val giftWrapPayloadRumor = RumorAssembler.assembleRumor( + pubKey = nostrSignerSync.pubKey, + ev = EventTemplate( createdAt = giftWrapPayload.createdAt.epochSeconds, kind = giftWrapPayload.kind, tags = giftWrapPayload.tags, content = giftWrapPayload.content ) - logger.d("GiftWrap Payload Event: ${giftWrapPayloadEvent.toJson()}") + ) + logger.d("GiftWrap Payload Rumor: ${giftWrapPayloadRumor.toJson()}") - logger.d("Seal to $participant") - val payload = giftWrapPayloadEvent.toJson() + logger.d("Seal to $participant") + val payload = giftWrapPayloadRumor.toJson() - val sealedRumorEvent = nostrSignerSync.signNormal( - createdAt = TimeUtils.randomWithTwoDays(), - kind = SealedRumorEvent.KIND, - tags = emptyArray(), - content = nostrSignerSync.nip44Encrypt( - plaintext = payload, - toPublicKey = participant.participantPublicKey - ) + val sealedRumorEvent = nostrSignerSync.signNormal( + createdAt = TimeUtils.randomWithTwoDays(), + kind = SealedRumorEvent.KIND, + tags = emptyArray(), + content = nostrSignerSync.nip44Encrypt( + plaintext = payload, + toPublicKey = participant.participantPublicKey ) - logger.d("SealedRumorEvent: ${sealedRumorEvent.toJson()}") + ) + logger.d("SealedRumorEvent: ${sealedRumorEvent.toJson()}") - val giftWrapEvent = wrapperSigner.signNormal( - createdAt = TimeUtils.randomWithTwoDays(), - kind = GiftWrapEvent.KIND, - tags = arrayOf( - PTag.assemble(participant.participantPublicKey, participant.relayHint?.let { NormalizedRelayUrl(it) }) - ), - content = wrapperSigner.nip44Encrypt( - plaintext = sealedRumorEvent.toJson(), - toPublicKey = participant.participantPublicKey - ) + val giftWrapEvent = wrapperSigner.signNormal( + createdAt = TimeUtils.randomWithTwoDays(), + kind = GiftWrapEvent.KIND, + tags = arrayOf( + PTag.assemble(participant.participantPublicKey, participant.relayHint?.let { NormalizedRelayUrl(it) }) + ), + content = wrapperSigner.nip44Encrypt( + plaintext = sealedRumorEvent.toJson(), + toPublicKey = participant.participantPublicKey ) - logger.d("giftWrapEvent: ${giftWrapEvent.toJson()}") + ) + logger.d("giftWrapEvent: ${giftWrapEvent.toJson()}") - database.nostrNip17Dao().persistAndBroadcastGiftWrap( - giftWrapPayload = Pair( - index, - giftWrapPayload - ), - sealedRumorEvent = sealedRumorEvent, - giftWrapEvent = giftWrapEvent, - receiverPublicKey = PTag( - pubKey = participant.participantPublicKey, - relayHint = participant.relayHint?.let { NormalizedRelayUrl(it) } - ) + database.nostrNip17Dao().persistAndBroadcastGiftWrap( + giftWrapPayload = Pair( + index, + giftWrapPayload + ), + sealedRumorEvent = sealedRumorEvent, + giftWrapEvent = giftWrapEvent, + receiverPublicKey = PTag( + pubKey = participant.participantPublicKey, + relayHint = participant.relayHint?.let { NormalizedRelayUrl(it) } ) - } + ) } }