on master help sign in
Fix four bugs: AckMessages federation ack deduplication, VerifyAuth challenge clearing, session cap global eviction, and offline timestamp clamping
commit918fbd276fb5a27b8fb4b10a59546625c907f9f9 authoriko <mail@iko.soy> dateSat 4 Apr 2026, 19:54 (7 months ago) parent05d753c
7 files changed+52−36
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfo.fs+1−1 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfoInputs.cache+1−1 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.dll client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.pdb client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.sourcelink.json+1−1 client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/refint/Skrepka.dll server.knot+49−33
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfo.fs+1−1
@@ -10,7 +10,7 @@ open System.Reflection
1010[<assembly: System.Reflection.AssemblyCompanyAttribute("Skrepka")>]
1111[<assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")>]
1212[<assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")>]
13−[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+fa9d38a3fad244670e1576c664bf6ba789d0168e")>]
13+[<assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0+05d753cd7e475295c60dc1d484026b2cf2292eff")>]
1414[<assembly: System.Reflection.AssemblyProductAttribute("Skrepka")>]
1515[<assembly: System.Reflection.AssemblyTitleAttribute("Skrepka")>]
1616[<assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")>]
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.AssemblyInfoInputs.cache+1−1
@@ -1 +1 @@
1−284a452a2358d44d43d128fc8940476c0b2aae618df88f49906b03be966d2822
1+5fa18b9a113df0de25b42d81980e7a84a6dacf854b07a6a4c25f18ad0f366df2
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.dll

Binary file not shown.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.pdb

Binary file not shown.

client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/Skrepka.sourcelink.json+1−1
@@ -1 +1 @@
1−{"documents":{"/Users/iko/Developer/skrepka/*":"https://raw.githubusercontent.com/ilyakooo0/skrepka/fa9d38a3fad244670e1576c664bf6ba789d0168e/*"}}
1+{"documents":{"/Users/iko/Developer/skrepka/*":"https://raw.githubusercontent.com/ilyakooo0/skrepka/05d753cd7e475295c60dc1d484026b2cf2292eff/*"}}
client/obj/Debug/net10.0-maccatalyst/maccatalyst-arm64/refint/Skrepka.dll

Binary file not shown.

server.knot+49−33
@@ -506,7 +506,11 @@ sendAcksAndClean = \pendingAcks servers ->
506506 originServer: server, fromServer: serverHostN})
507507 atomic do
508508 ackedIds <- *ackedIds
509− set *ackedIds = diff ackedIds serverAcks) (\err ->
509+ let ackMsgIds = do a <- serverAcks; yield a.messageId
510+ set *ackedIds = do
511+ a <- ackedIds
512+ where not (a.originServer == server && count (do mid <- ackMsgIds; where mid == a.messageId; yield mid) > 0)
513+ yield a) (\err ->
510514 println ("federation: error sending ack to " ++ server ++ ": " ++ show err))
511515 sendAcksAndClean pendingAcks rest
512516
@@ -635,12 +639,14 @@ serve = \req -> case req of
635639 else if not (isValidHex pubkey) || not (isValidHex signature)
636640 then False {}
637641 else verify (bytesFromHex pubkey) (textToBytes challenge) (bytesFromHex signature)
638− set *challenges = case matched of
639− Just {value: _} -> do
640− c <- challenges
641− where not (c.pubkey == pubkey && c.challenge == challenge)
642− yield c
643− Nothing {} -> challenges
642+ set *challenges = if sigValid
643+ then (case matched of
644+ Just {value: _} -> do
645+ c <- challenges
646+ where not (c.pubkey == pubkey && c.challenge == challenge)
647+ yield c
648+ Nothing {} -> challenges)
649+ else challenges
644650 let existingForKey = do
645651 s <- sessions
646652 where s.pubkey == pubkey
@@ -654,15 +660,16 @@ serve = \req -> case req of
654660 let sessionsCapped = if count existingForKey >= maxSessionsPerKey && oldestExpiry >= 0
655661 then cappedFold.sessions
656662 else sessions
657− let globalOldestSessionExpiry = if count sessionsCapped >= maxSessions
658− then fold (\acc s -> if acc == -1 || s.expiresAt < acc then s.expiresAt else acc) -1 sessionsCapped
663+ let activeSessionsCapped = do s <- sessionsCapped; where s.expiresAt > t; yield s
664+ let globalOldestSessionExpiry = if count activeSessionsCapped >= maxSessions
665+ then fold (\acc s -> if acc == -1 || s.expiresAt < acc then s.expiresAt else acc) -1 activeSessionsCapped
659666 else -1
660667 let globalSessionsCapped = if globalOldestSessionExpiry >= 0
661668 then (fold (\acc s ->
662669 if not acc.removed && s.expiresAt == globalOldestSessionExpiry
663670 then {removed: True {}, items: acc.items}
664− else {removed: acc.removed, items: union acc.items [s]}) {removed: False {}, items: []} sessionsCapped).items
665− else sessionsCapped
671+ else {removed: acc.removed, items: union acc.items [s]}) {removed: False {}, items: []} activeSessionsCapped).items
672+ else activeSessionsCapped
666673 set *sessions = if sigValid
667674 then union globalSessionsCapped [{token: token, pubkey: pubkey, expiresAt: expiry}]
668675 else sessions
@@ -829,18 +836,11 @@ serve = \req -> case req of
829836 yield {messageId: m.messageId, toKey: m.toKey, ackedAt: t, originServer: m.originServer}
830837 ackedIds <- *ackedIds
831838 let combinedAckedIds = union ackedIds ackedFederated
832− let excessCount = count combinedAckedIds - maxAckedIds
833− let afterEviction = if excessCount <= 0
834− then combinedAckedIds
835− else evictOldestAckedIds combinedAckedIds excessCount
836− let evictedEntries = if excessCount <= 0
837− then []
838− else diff combinedAckedIds afterEviction
839− set *ackedIds = afterEviction
839+ set *ackedIds = combinedAckedIds
840840 let ok = case session of
841841 Nothing {} -> False {}
842842 _ -> True {}
843− yield {ok: ok, ackedMessages: ackedMessages, expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, evictedEntries: evictedEntries}
843+ yield {ok: ok, ackedMessages: ackedMessages, expiredLocal: pr.expiredLocal, peerServers: pr.peerServers}
844844 let fedMessages = do
845845 m <- result.ackedMessages
846846 where not (m.originServer == "")
@@ -857,8 +857,18 @@ serve = \req -> case req of
857857 yield {messageId: m.messageId, toKey: m.toKey, ackedAt: t, originServer: m.originServer}
858858 sendAcksAndClean pendingAcks originServers
859859 else yield {}
860+ evictedEntries <- atomic do
861+ ackedIds <- *ackedIds
862+ let excessCount = count ackedIds - maxAckedIds
863+ if excessCount <= 0
864+ then yield []
865+ else do
866+ let afterEviction = evictOldestAckedIds ackedIds excessCount
867+ let evicted = diff ackedIds afterEviction
868+ set *ackedIds = afterEviction
869+ yield evicted
860870 let evictedToRetry = do
861− a <- result.evictedEntries
871+ a <- evictedEntries
862872 where count (do m <- fedMessages; where m.messageId == a.messageId; where m.toKey == a.toKey; yield m) == 0
863873 yield a
864874 if count evictedToRetry > 0 && not (federationSecret == "")
@@ -1031,7 +1041,7 @@ serve = \req -> case req of
10311041 o <- trustedOffline
10321042 where o.pubkey == k.pubkey
10331043 where o.server == k.server
1034− where o.timestamp > p.timestamp
1044+ where (if o.timestamp > t then t else o.timestamp) > p.timestamp
10351045 yield o) > 0
10361046 yield p) > 0
10371047 yield {pubkey: k.pubkey, server: k.server}
@@ -1044,7 +1054,7 @@ serve = \req -> case req of
10441054 o <- trustedOffline
10451055 where o.pubkey == k.pubkey
10461056 where o.server == k.server
1047− where o.timestamp > p.timestamp
1057+ where (if o.timestamp > t then t else o.timestamp) > p.timestamp
10481058 yield o) > 0
10491059 yield p)
10501060 let withinCapacity = count afterOffline <= maxPresenceEntries
@@ -1075,7 +1085,7 @@ serve = \req -> case req of
10751085 o <- trustedOffline
10761086 where o.pubkey == k.pubkey
10771087 where o.server == k.server
1078− where o.timestamp > p.timestamp
1088+ where (if o.timestamp > t then t else o.timestamp) > p.timestamp
10791089 yield o) > 0
10801090 yield p)
10811091 let reclaimCapacity = if withinCapacity then 0 else maxPresenceEntries - count updatesOnlyAfterOffline
@@ -1259,17 +1269,20 @@ serve = \req -> case req of
12591269 yield a
12601270 yield {expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, pendingForwards: pendingForwards, pendingAcks: pendingAcks}
12611271 respond {ok: True {}}
1262− broadcastOfflineGossip t result.peerServers result.expiredLocal
1263− if not (federationSecret == "") && count result.pendingForwards > 0
1272+ catch (broadcastOfflineGossip t result.peerServers result.expiredLocal) (\err ->
1273+ println ("prune: gossip failed: " ++ show err))
1274+ catch (if not (federationSecret == "") && count result.pendingForwards > 0
12641275 then retryPendingForwards result.pendingForwards
1265− else yield {}
1266− if not (federationSecret == "") && count result.pendingAcks > 0
1276+ else yield {}) (\err ->
1277+ println ("prune: forward retry failed: " ++ show err))
1278+ catch (if not (federationSecret == "") && count result.pendingAcks > 0
12671279 then do
12681280 let ackOriginServers = fold (\acc a ->
12691281 if count (do s <- acc; where s == a.originServer; yield s) > 0 then acc
12701282 else union acc [a.originServer]) [] result.pendingAcks
12711283 sendAcksAndClean result.pendingAcks ackOriginServers
1272− else yield {}
1284+ else yield {}) (\err ->
1285+ println ("prune: ack send failed: " ++ show err))
12731286 else respond {ok: False {}}
12741287
12751288-- ============================================
@@ -1294,17 +1307,20 @@ backgroundPrune = do
12941307 where not (a.originServer == serverHostN)
12951308 yield a
12961309 yield {expiredLocal: pr.expiredLocal, peerServers: pr.peerServers, pendingForwards: pendingForwards, pendingAcks: pendingAcks}
1297− broadcastOfflineGossip t result.peerServers result.expiredLocal
1298− if not (federationSecret == "") && count result.pendingForwards > 0
1310+ catch (broadcastOfflineGossip t result.peerServers result.expiredLocal) (\err ->
1311+ println ("background prune: gossip failed: " ++ show err))
1312+ catch (if not (federationSecret == "") && count result.pendingForwards > 0
12991313 then retryPendingForwards result.pendingForwards
1300− else yield {}
1301− if not (federationSecret == "") && count result.pendingAcks > 0
1314+ else yield {}) (\err ->
1315+ println ("background prune: forward retry failed: " ++ show err))
1316+ catch (if not (federationSecret == "") && count result.pendingAcks > 0
13021317 then do
13031318 let ackOriginServers = fold (\acc a ->
13041319 if count (do s <- acc; where s == a.originServer; yield s) > 0 then acc
13051320 else union acc [a.originServer]) [] result.pendingAcks
13061321 sendAcksAndClean result.pendingAcks ackOriginServers
13071322 else yield {}) (\err ->
1323+ println ("background prune: ack send failed: " ++ show err))) (\err ->
13081324 println ("background prune: " ++ show err))
13091325 backgroundPrune
13101326