on master help sign in
Fix bug #10: dedupe inbound federated forwards in handleForwardMessage

A peer whose success response was lost (proxy timeout, dropped connection) re-sends the same (toKey, encryptedBlob) via retryPendingForwards; the recipient previously appended it again under a fresh receivedAt, delivering the ciphertext twice. Treat an already-stored pair as success without a second append.

commit8ab1465a2ddad464046fc4e5628e3691cc4e2a3a authoriko <mail@iko.soy> dateThu 11 Jun 2026, 13:52 (4 months ago) parent02894c9
1 file changed+5−1
server.knot+5−1
server.knot+5−1
@@ -850,6 +850,9 @@ handleRecvGossip = \events fromServer -> do
850850-- A → B forward based on stale gossip about R could land on B with no
851851-- actively-polling client and get stuck. If B refuses, A retries via
852852-- `retryPendingForwards` against the next presence target.
853+-- Re-delivery of an already-stored (toKey, blob) pair is treated as success
854+-- without a second append, so a sender whose success response was lost can
855+-- retry without duplicating the message in the recipient's mailbox.
853856handleForwardMessage : PubkeyHex -> BlobHex -> IO {rw *messages, r *presence, rw *seqCounter, clock} (Result HttpError {})
854857handleForwardMessage = \toKey encryptedBlob -> do
855858 t <- now
@@ -858,7 +861,8 @@ handleForwardMessage = \toKey encryptedBlob -> do
858861 if not hasLocalPresence pres toKey t
859862 then yield (Err {error: {status: 404, message: "no_presence"}})
860863 else do
861− appendMessage toKey encryptedBlob t
864+ msgs <- *messages
865+ when (not any (\m -> m.toKey == toKey && m.encryptedBlob == encryptedBlob) msgs) (appendMessage toKey encryptedBlob t)
862866 yield (Ok {value: {}}))
863867
864868-- ============================================