Cleaning up

This commit is contained in:
Kgothatso Ngako
2026-07-06 23:19:47 +02:00
parent 22cc5f2d9d
commit 7e1ef80ef3
5 changed files with 14 additions and 58 deletions

View File

@@ -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
)
)

View File

@@ -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<MarmotRetainedEpochSecret>
@Query("SELECT * FROM MarmotRetainedEpochSecret WHERE chatRoomId = :chatRoomId")
suspend fun getMarmotRetainedEpochSecretForChatRoomId(chatRoomId: HexKey): List<MarmotRetainedEpochSecret>
@Query("SELECT * FROM MarmotRetainedEpochSecret WHERE chatRoomId = :chatRoomId AND epoch < :epochCutOffPoint")
suspend fun getDefenestratableMarmotRetainedEpochSecretForChatRoomId(chatRoomId: HexKey, epochCutOffPoint: Long): List<MarmotRetainedEpochSecret>
@Insert(
onConflict = IGNORE

View File

@@ -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

View File

@@ -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<Event>(
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
)
}
}

View File

@@ -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