From 7e1ef80ef36fad66c42ad9d83cc433735b67b4da Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Mon, 6 Jul 2026 23:19:47 +0200 Subject: [PATCH] Cleaning up --- .../compose/database/dao/MarmotOutboundDao.kt | 6 ++- .../dao/MarmotRetainedEpochSecretDao.kt | 9 +++- .../database/model/MarmotGroupEvent.kt | 7 +-- .../database/model/MarmotInnerEvent.kt | 48 +------------------ .../repository/DatabaseMarmotRepository.kt | 2 - 5 files changed, 14 insertions(+), 58 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotOutboundDao.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotOutboundDao.kt index 79577a5a..39a597e2 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotOutboundDao.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotOutboundDao.kt @@ -158,8 +158,10 @@ abstract class MarmotOutboundDao( ) ) + // Trim retained epochs out of the retention window... val defenestratableMarmotRetainedEpochSecrets = database.marmotRetainedEpochSecretDao() - .defenestratableMarmotRetainedEpochSecret( + .getDefenestratableMarmotRetainedEpochSecretForChatRoomId( + chatRoomId = nostrGroupId, epochCutOffPoint = retainedBefore.epoch - EPOCH_RETENTION_WINDOW.toLong() ) logger.d("Defenestratable Retained Epochs: ${defenestratableMarmotRetainedEpochSecrets.map { it.epoch }}") @@ -383,7 +385,7 @@ abstract class MarmotOutboundDao( encryptedContent = groupEvent.encryptedContent(), chatRoomId = localChatRoom.chatRoom.id, nostrEventId = groupEvent.id, - userPublicKey = nostrSignerSync.pubKey, + userPublicKey = groupEvent.pubKey, publicKey = groupEvent.pubKey ) ) diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotRetainedEpochSecretDao.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotRetainedEpochSecretDao.kt index 3d6459d4..4200131e 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotRetainedEpochSecretDao.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/dao/MarmotRetainedEpochSecretDao.kt @@ -6,11 +6,16 @@ import androidx.room3.Insert import androidx.room3.OnConflictStrategy.Companion.IGNORE import androidx.room3.Query import at.torch.compose.database.model.MarmotRetainedEpochSecret +import com.vitorpamplona.quartz.nip01Core.core.HexKey @Dao interface MarmotRetainedEpochSecretDao { - @Query("SELECT * FROM MarmotRetainedEpochSecret WHERE epoch < :epochCutOffPoint") - suspend fun defenestratableMarmotRetainedEpochSecret(epochCutOffPoint: Long): List + @Query("SELECT * FROM MarmotRetainedEpochSecret WHERE chatRoomId = :chatRoomId") + suspend fun getMarmotRetainedEpochSecretForChatRoomId(chatRoomId: HexKey): List + + + @Query("SELECT * FROM MarmotRetainedEpochSecret WHERE chatRoomId = :chatRoomId AND epoch < :epochCutOffPoint") + suspend fun getDefenestratableMarmotRetainedEpochSecretForChatRoomId(chatRoomId: HexKey, epochCutOffPoint: Long): List @Insert( onConflict = IGNORE diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/MarmotGroupEvent.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/MarmotGroupEvent.kt index eb5d9009..bb819265 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/MarmotGroupEvent.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/MarmotGroupEvent.kt @@ -9,6 +9,7 @@ import at.torch.compose.database.model.traits.NostrEventEntity import at.torch.compose.database.model.traits.SoftDeletableEntity import at.torch.compose.database.model.traits.TimestampedEntity import at.torch.compose.exceptions.MarmotMissingRetainedExporterSecretsException +import at.torch.compose.extensions.exporterSecret import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup @@ -97,11 +98,7 @@ data class MarmotGroupEvent( ): ByteArray? { // Try current epoch key first try { - val exporterKey = group.exporterSecret( - "marmot", - "group-event".encodeToByteArray(), - 32, - ) + val exporterKey = group.exporterSecret() return GroupEventEncryption.decrypt(encryptedContent, exporterKey) } catch (e: Exception) { // Current epoch key failed — try retained epoch keys diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/MarmotInnerEvent.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/MarmotInnerEvent.kt index 6f461716..26c43858 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/MarmotInnerEvent.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/model/MarmotInnerEvent.kt @@ -8,6 +8,7 @@ import at.torch.compose.database.model.traits.LocalStoreEntity import at.torch.compose.database.model.traits.SoftDeletableEntity import at.torch.compose.database.model.traits.TimestampedEntity import at.torch.compose.database.model.traits.UserViewableEntity +import at.torch.compose.extensions.exporterSecret import co.touchlab.kermit.Logger import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent @@ -158,51 +159,4 @@ data class MarmotInnerEvent( // TODO: Rename this to GiftWrapPayload... result = 31 * result + logger.hashCode() return result } - - suspend fun toSignedNostrEvent(group: MlsGroup): GroupEvent { - // TODO: Assert group.id == chatRoomId - - val innerEventTemplate = eventTemplate( - kind = kind, - description = content - ) - - val rumorEvent = RumorAssembler.assembleRumor( - publicKey, - innerEventTemplate - ) - - val mlsCiphertext = group.encrypt(rumorEvent.toJson().encodeToByteArray()) - - val exporterKey = group.exporterSecret( - "marmot", - "group-event".encodeToByteArray(), - 32 - ) - val encryptedContent = GroupEventEncryption.encrypt(mlsCiphertext, exporterKey) - - val createdAt = TimeUtils.now() - val expirationTime = disappearingExpiration(group, createdAt) - val template = - GroupEvent.build( - encryptedContentBase64 = encryptedContent, - nostrGroupId = chatRoomId, - createdAt = createdAt, - ) { - if (expirationTime != null) expiration(expirationTime) - } - - // Step 4: Sign with a fresh ephemeral keypair - val ephemeralSigner = NostrSignerInternal(KeyPair()) - val signedEvent: GroupEvent = ephemeralSigner.sign(template) - - return GroupEvent( - id = signedEvent.id, - content = signedEvent.content, - createdAt = signedEvent.createdAt, - tags = signedEvent.tags, - sig = signedEvent.sig, - pubKey = signedEvent.pubKey - ) - } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/at/torch/compose/database/repository/DatabaseMarmotRepository.kt b/composeApp/src/commonMain/kotlin/at/torch/compose/database/repository/DatabaseMarmotRepository.kt index 6502382d..e0f97d0e 100644 --- a/composeApp/src/commonMain/kotlin/at/torch/compose/database/repository/DatabaseMarmotRepository.kt +++ b/composeApp/src/commonMain/kotlin/at/torch/compose/database/repository/DatabaseMarmotRepository.kt @@ -27,9 +27,7 @@ import com.vitorpamplona.quartz.marmot.mls.tree.Lifetime import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.toHexKey import com.vitorpamplona.quartz.nip01Core.crypto.EventHasher -import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync -import com.vitorpamplona.quartz.nip59Giftwrap.rumors.RumorAssembler import com.vitorpamplona.quartz.utils.TimeUtils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow