summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2022-02-08 21:12:08 +0100
committerRoman Smrž <roman.smrz@seznam.cz>2022-02-17 17:18:07 +0100
commit1b9ab11b4bebd73c2419fcf7b430d8be5e6ef14d (patch)
treec817dbd1aa4e01db215388a54bea7255314fce42
parentc51983c7d268d9501f3ff3e0e50f5b0293c6d788 (diff)
IdentityUpdate updates self and requires ACK
-rw-r--r--src/Identity.hs25
-rw-r--r--src/Network.hs21
2 files changed, 28 insertions, 18 deletions
diff --git a/src/Identity.hs b/src/Identity.hs
index 0e3e318..b81228f 100644
--- a/src/Identity.hs
+++ b/src/Identity.hs
@@ -23,6 +23,7 @@ import Control.Monad
import Control.Monad.Except
import qualified Control.Monad.Identity as I
+import Data.Either
import Data.Foldable
import Data.Function
import Data.List
@@ -214,15 +215,23 @@ toComposedIdentity idt = idt { idData_ = toList $ idDataF idt
}
-updateIdentitySets :: Foldable m => [(Stored (Signed IdentityData), Set (Stored (Signed IdentityData)))] -> Identity m -> ComposedIdentity
-updateIdentitySets updates orig@Identity { idData_ = idata } =
- case validateIdentityF $ map update $ toList idata of
- Just updated -> updated { idOwner_ = updateIdentitySets updates <$> idOwner_ updated }
- Nothing -> toComposedIdentity orig
- where update x = foldl (\y (y', set) -> if y `S.member` set then y' else y) x updates
-
updateIdentity :: Foldable m => [Stored (Signed IdentityData)] -> Identity m -> ComposedIdentity
-updateIdentity = updateIdentitySets . map (\u -> (u, ancestors [u]))
+updateIdentity [] orig = toComposedIdentity orig
+updateIdentity updates orig =
+ case validateIdentityF $ filterAncestors (ourUpdates ++ idata) of
+ -- need to filter ancestors here as validateIdentityF currently stores the whole list in idData_
+ Just updated -> updated
+ { idOwner_ = updateIdentity ownerUpdates <$> idOwner_ updated
+ , idUpdates_ = ownerUpdates
+ }
+ Nothing -> toComposedIdentity orig
+ where idata = toList $ idData_ orig
+ ilen = length idata
+ (ourUpdates, ownerUpdates) = partitionEithers $ flip map (filterAncestors $ updates ++ idUpdates_ orig) $
+ -- if an update is related to anything in idData_, use it here, otherwise push to owners
+ \u -> if length (filterAncestors (u : idata)) < ilen + 1
+ then Left u
+ else Right u
updateOwners :: [Stored (Signed IdentityData)] -> Identity m -> Identity m
updateOwners updates orig@Identity { idOwner_ = Just owner, idUpdates_ = cupdates } =
diff --git a/src/Network.hs b/src/Network.hs
index 01caef7..c9a2d8b 100644
--- a/src/Network.hs
+++ b/src/Network.hs
@@ -294,15 +294,16 @@ startServer opt origHead logd' services = do
let announceUpdate identity = do
st <- derivePartialStorage storage
let selfRef = partialRef st $ storedRef $ idData identity
- updateRefs = map (partialRef st . storedRef) $ idUpdates identity
- hitems = AnnounceSelf selfRef : map AnnounceUpdate updateRefs
+ updateRefs = selfRef : map (partialRef st . storedRef) (idUpdates identity)
+ ackedBy = concat [[ Acknowledged r, Rejected r, DataRequest r ] | r <- updateRefs ]
+ hitems = map AnnounceUpdate updateRefs
packet = TransportPacket (TransportHeader $ hitems) []
ps <- readMVar peers
forM_ ps $ \peer -> atomically $ do
((,) <$> readTVar (peerIdentityVar peer) <*> readTVar (peerChannel peer)) >>= \case
(PeerIdentityFull _, ChannelEstablished _) ->
- writeTQueue (peerOutQueue peer) (True, [], packet)
+ writeTQueue (peerOutQueue peer) (True, ackedBy, packet)
_ -> return ()
let shareState self shared peer = do
@@ -591,7 +592,7 @@ handlePacket origHead identity secure peer chanSvc svcs (TransportHeader headers
addHeader $ AnnounceSelf ref
writeTVarP (peerIdentityVar peer) $ PeerIdentityRef wref idwait
liftSTM $ writeTChan (serverChanPeer $ peerServer peer) peer
- _ -> addHeader $ Acknowledged pref
+ _ -> return ()
AnnounceUpdate ref -> do
readTVarP (peerIdentityVar peer) >>= \case
@@ -716,9 +717,9 @@ finalizedChannel peer oh self = do
-- Identity update
do
let selfRef = partialRef ist $ storedRef $ idData $ self
- updateRefs = map (partialRef ist . storedRef) $ idUpdates $ self
- sendToPeerS peer [] $ flip TransportPacket [] $ TransportHeader $
- AnnounceSelf selfRef : map AnnounceUpdate updateRefs
+ updateRefs = selfRef : map (partialRef ist . storedRef) (idUpdates self)
+ ackedBy = concat [[ Acknowledged r, Rejected r, DataRequest r ] | r <- updateRefs ]
+ sendToPeerS peer ackedBy $ flip TransportPacket [] $ TransportHeader $ map AnnounceUpdate updateRefs
-- Shared state
readTVar (peerIdentityVar peer) >>= \case
@@ -741,7 +742,7 @@ handleIdentityAnnounce :: UnifiedIdentity -> Peer -> Ref -> WaitingRefCallback
handleIdentityAnnounce self peer ref = liftIO $ atomically $ do
let validateAndUpdate upds act = case validateIdentity $ wrappedLoad ref of
Just pid' -> do
- let pid = updateOwners upds pid'
+ let pid = fromMaybe pid' $ toUnifiedIdentity (updateIdentity upds pid')
writeTVar (peerIdentityVar peer) $ PeerIdentityFull pid
writeTChan (serverChanPeer $ peerServer peer) peer
act pid
@@ -766,9 +767,9 @@ handleIdentityUpdate :: Peer -> Ref -> WaitingRefCallback
handleIdentityUpdate peer ref = liftIO $ atomically $ do
pidentity <- readTVar (peerIdentityVar peer)
if | PeerIdentityFull pid <- pidentity
+ , Just pid' <- toUnifiedIdentity $ updateIdentity [wrappedLoad ref] pid
-> do
- writeTVar (peerIdentityVar peer) $ PeerIdentityFull $
- updateOwners [wrappedLoad ref] pid
+ writeTVar (peerIdentityVar peer) $ PeerIdentityFull pid'
writeTChan (serverChanPeer $ peerServer peer) peer
| otherwise -> return ()