+ (a) a slot with the message, and (b) a request to the server. The queue can only be expanded, never contracted; attempting to decrease the size of the queue will cause future clients to throw an error.\r
+\r
+\subsection{Server Algorithm}\r
+$s \in SN$ is a sequence number\\\r
+$sv \in SV$ is a slot's value\\\r
+$slot_s = \tuple{s, sv} \in SL \subseteq SN \times SV$ \\ \\\r
+\textbf{State} \\\r
+\textit{SL = set of live slots on server} \\\r
+\textit{max = maximum number of slots (input only for resize message)} \\\r
+\textit{n = number of slots} \\ \\\r
+\textbf{Helper Function} \\\r
+$MaxSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv}\r
+\in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \geq s_s$ \\\r
+$MinSlot(SL_s)= \tuple{s, sv} \mid \tuple{s, sv} \r
+\in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \leq s_s$ \\\r
+$SeqN(slot_s = \tuple{s, sv})=s$ \\\r
+$SlotVal(slot_s = \tuple{s, sv})=sv$ \\\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetSlot}{$s_g$}\r
+\State \Return{$\{\tuple{s, sv} \in SL \mid s \geq s_g\}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{PutSlot}{$s_p,sv_p,max'$}\r
+\If{$(max' \neq \emptyset)$} \Comment{Resize}\r
+\State $max \gets max'$\r
+\EndIf\r
+\State $\tuple{s_n,sv_n} \gets MaxSlot(SL)$\Comment{Last sv}\r
+%\State $s_n \gets SeqN(\tuple{s_n,sv_n})$\r
+\If{$(s_p = s_n + 1)$}\r
+ \If{$n = max$}\r
+ \State $\tuple{s_m,sv_m} \gets MinSlot(SL)$\Comment{First sv}\r
+ \State $SL \gets SL - \{\tuple{s_m,sv_m}\}$\r
+ \Else \Comment{$n < max$}\r
+ \State $n \gets n + 1$\r
+ \EndIf\r
+ \State $SL \gets SL \cup \{\tuple{s_p,sv_p}\}$\r
+ \State \Return{$(true,\emptyset)$}\r
+\Else\r
+ \State \Return{$(false,\{\tuple{s,sv}\in SL \mid \r
+ s \geq s_p\})$}\r
+\EndIf\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\subsection{Client Algorithm}\r
+\subsubsection{Reading Slots}\r
+\textbf{Data Entry} \\\r
+$de$ is a data entry \\\r
+$k$ is key of entry \\\r
+$v$ is value of entry \\\r
+$kv$ is a key-value entry $\tuple{k,v}$, $kv \in DE$ \\\r
+$ss$ is a slot sequence entry $\tuple{id,s_{last}}$, \r
+id + last s of a machine, $ss \in DE$ \\\r
+$qs$ is a queue state entry (contains $max$ size of queue), $qs \in DE$ \\\r
+$cr$ is a collision resolution entry $\tuple{s_{col},id_{col}}$, \r
+s + id of a machine that wins a collision, $cr \in DE$ \\\r
+$DE$ is a set of all data entries, possibly of different types, in a single message \\\r
+$s \in SN$ is a sequence number \\\r
+$id$ is a machine ID\\\r
+$hmac_p$ is the HMAC value of the previous slot \\\r
+$hmac_c$ is the HMAC value of the current slot \\\r
+$Dat_s = \tuple{s,id,hmac_p,DE,hmac_c}$ \\\r
+$slot_s = \tuple{s, E(Dat_s)} = \r
+\tuple{s, E(\tuple{s,id,hmac_p,DE,hmac_c})}$ \\ \\\r
+\textbf{States} \\\r
+\textit{$d$ = delta between the last $s$ recorded and the first $s$ received} \\\r
+\textit{$id_{self}$ = machine Id of this client} \\\r
+\textit{$max_g$ = maximum number of slots (initially $max_g > 0$)} \\\r
+\textit{m = number of slots stored on client (initially $m = 0$)} \\\r
+\textit{$sl_{last}$ = info of last slot in queue = \r
+ $\tuple{s_{last},sv_{last},id_{last}}$ (initially $\emptyset$)} \\\r
+\textit{DT = set of $\tuple{k,v}$ on client} \\\r
+\textit{MS = associative array of $\tuple{id, s_{last}}$ of all clients on client \r
+(initially empty)} \\\r
+\textit{$LV$ = live set of $kv$ entries on client, contains \r
+ $\tuple{kv,s}$ entries} \\\r
+\textit{$SS_{live}$ = live set of $ss$ entries on client} \\\r
+\textit{$CR_{live}$ = live set of $cr$ entries on client} \\\r
+\textit{$MS_g$ = set MS to save all $\tuple{id, s_{last}}$ pairs while\r
+traversing DT after a request to server (initially empty)} \\\r
+\textit{SK = Secret Key} \\\r
+\textit{$SM$ = associative array of $\tuple{s, id}$ of all slots in previous reads\r
+(initially empty)} \\ \\\r
+\textbf{Helper Functions} \\\r
+$MaxSlot(SL_s)= \tuple{s, sv}$ \textit{such that} $\tuple{s, sv}\r
+ \in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \geq s_s$ \\\r
+$MinSlot(SL_s)= \tuple{s, sv}$ \textit{such that} $\tuple{s, sv} \r
+ \in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s \leq s_s$ \\\r
+$Slot(SL_s,s_s)= \tuple{s, sv}$ \textit{such that} $\tuple{s, sv} \r
+ \in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s = s_s$ \\\r
+$SeqN(\tuple{s, sv})=s$ \\\r
+$SlotVal(\tuple{s, sv})=sv$ \\\r
+$CreateLastSL(s,sv,id)=\tuple{s,sv,id}=sl_{last}$ \\\r
+$CreateEntLV(kv_s,s_s)=\tuple{kv_s,s_s}$ \\\r
+$Decrypt(SK_s,sv_s)=Dat_s=\tuple{s,id,hmac_p,DE,hmac_c}$ \\\r
+$GetSeqN(Dat_s = \tuple{s,id,hmac_p,DE,hmac_c})=s$ \\\r
+$GetMacId(Dat_s = \tuple{s,id,hmac_p,DE,hmac_c})=id$ \\\r
+$GetPrevHmac(Dat_s = \tuple{s,id,hmac_p,DE,hmac_c})=hmac_p$ \\\r
+$GetCurrHmac(Dat_s = \tuple{s,id,hmac_p,DE,hmac_c})=hmac_c$ \\\r
+$GetDatEnt(Dat_s = \tuple{s,id,hmac_p,DE,hmac_c})=DE$ \\\r
+$GetLiveSS(SS_{live},ss_s)= ss$ \textit{such that} $ss \in SS_{live} \r
+ \wedge \forall ss_s \in SS_{live}, ss = ss_s$ \\\r
+$GetLiveCR(CR_{live},cr_s)= cr$ \textit{such that} $cr \in CR_{live} \r
+ \wedge \forall cr_s \in CR_{live}, cr = cr_s$ \\\r
+$GetLivEntLastS(LV_s,kv_s)= s$ \textit{such that} $\tuple{kv, s} \in LV_s \r
+ \wedge \forall \tuple{kv_s, s_s} \in LV_s, kv_s = kv$ \\\r
+$GetKV($key-value data entry$)=\tuple{k_s,v_s} = kv_s$ \\\r
+$GetSS($slot-sequence data entry$)=\tuple{id_s,s_{s_{last}}} = ss_s$ \\\r
+$GetQS($queue-state data entry$)=qs_s$ \\\r
+$GetCR($collision-resolution data entry$)=\tuple{s_s,id_s} = cr_s$ \\\r
+$GetKey(kv = \tuple{k, v})=k$ \\\r
+$GetVal(kv = \tuple{k, v})=v$ \\\r
+$GetId(ss = \tuple{id, s_{last}})=id$ \\\r
+$GetSLast(ss = \tuple{id, s_{last}})=s_{last}$ \\\r
+$GetS(cr = \tuple{s, id})=s$ \\\r
+$GetId(cr = \tuple{s, id})=id$ \\\r
+$GetKeyVal(DT_s,k_s)= \tuple{k, v}$ \textit{such that} $\tuple{k, v} \r
+ \in DT_s \wedge \forall \tuple{k_s, v_s} \in DT_s, k = k_s$ \\\r
+$MaxLastSeqN(MS_s)= s_{last}$ \textit{such that} $\tuple{id, s_{last}} \in MS_s \r
+ \wedge \forall \tuple{id_s, s_{s_{last}}} \in MS_s, s_{last} \geq s_{s_{last}}$ \\\r
+$MinLastSeqN(MS_s)= s_{last}$ \textit{such that} $\tuple{id, s_{last}} \in MS_s \r
+ \wedge \forall \tuple{id_s, s_{s_{last}}} \in MS_s, s_{last} \leq s_{s_{last}}$ \\\r
+$MinCRSeqN(CR_s)= s$ \textit{such that} $\tuple{s, id} \in CR_s \r
+ \wedge \forall \tuple{s_s, id_s} \in CR_s, s \leq s_s$ \\\r
+$MaxSMSeqN(SM_s)= s$ \textit{such that} $\tuple{s, id} \in SM_s \r
+ \wedge \forall \tuple{s_s, id_s} \in SM_s, s \geq s_s$ \\\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{Error}{$msg$}\r
+\State $Print(msg)$\r
+\State $Halt()$\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetQueSta}{$DE_s$}\r
+\State $de_{qs} \gets ss$ \textit{such that} $ss \in DE_s, \r
+ de_s \in D \land type(de_s) = "qs"$\r
+\If{$de_{qs} \neq \emptyset$}\r
+ \State $qs_{ret} \gets GetQS(de_{qs})$\r
+\Else\r
+ \State $qs_{ret} \gets \emptyset$\r
+\EndIf\r
+\State \Return{$qs_{ret}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetSlotSeq}{$DE_s$}\r
+\State $DE_{ss} \gets \{de | de \in DE_s \land type(de) = "ss"\}$\r
+\State \Return{$DE_{ss}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetColRes}{$DE_s$}\r
+\State $DE_{cr} \gets \{de | de \in DE_s \land type(de) = "cr"\}$\r
+\State \Return{$DE_{cr}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{UpdateLastSeqN}{$id_s,s_s,MS_s$}\r
+\State $s_t \gets MS_s[id_s]$\r
+\If{$s_t = \emptyset$}\r
+ \State $MS_s[id_s] = s_s$ \Comment{First occurrence}\r
+\Else\r
+ \State $MS_S[id_s] \gets max(s_t, s_s)$\r
+\EndIf\r
+\State \Return{$MS_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{UpdateKVLivEnt}{$LV_s,kv_s,s_s$}\r
+\State $s_t \gets GetLivEntLastS(LV_s,kv_s)$\r
+\If{$s_t = \emptyset$}\r
+ \State $LV_s \gets LV_s \cup \{\tuple{kv_s,s_s}\}$\Comment{First occurrence}\r
+\Else\r
+ \If{$s_s > s_t$}\Comment{Update entry with a later s}\r
+ \State $LV_s \gets (LV_s - \{\tuple{kv_s,s_t}\}) \cup \r
+ \{\tuple{kv_s,s_s}\}$\r
+ \EndIf\r
+\EndIf\r
+\State \Return{$LV_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{AddSSLivEnt}{$SS_{s_{live}},de_s$}\r
+\State $ss_s \gets GetSS(de_s)$\r
+\State $ss_t \gets GetLiveSS(SS_{s_{live}},ss_s)$\r
+\If{$ss_t = \emptyset$}\r
+ \State $SS_{s_{live}} \gets SS_{s_{live}} \cup \{ss_s\}$\Comment{First occurrence}\r
+\EndIf\r
+\State \Return{$SS_{s_{live}}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{AddCRLivEnt}{$CR_{s_{live}},cr_s$}\r
+\State $cr_t \gets GetLiveCR(CR_{s_{live}},cr_s)$\r
+\If{$cr_t = \emptyset$}\r
+ \State $CR_{s_{live}} \gets CR_{s_{live}} \cup \{cr_s\}$\Comment{First occurrence}\r
+\EndIf\r
+\State \Return{$CR_{s_{live}}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{UpdateSSLivEnt}{$SS_{s_{live}},MS_s$}\r
+\State $s_{s_{min}} \gets MinLastSeqN(MS_s)$\r
+\ForAll{$ss_s \in SS_{s_{live}}$}\r
+ \State $s_{s_{last}} \gets GetSLast(ss_s)$\r
+ \If{$s_{s_{min}} > s_{s_{last}}$}\Comment{Remove if dead}\r
+ \State $SS_{s_{live}} \gets SS_{s_{live}} - \{ss_s\}$ \r
+ \EndIf\r
+\EndFor\r
+\State \Return{$SS_{s_{live}}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{UpdateCRLivEnt}{$CR_{s_{live}},MS_s$}\r
+\State $s_{s_{min}} \gets MinLastSeqN(MS_s)$\r
+\ForAll{$cr_s \in CR_{s_{live}}$}\r
+ \State $s_s \gets GetS(cr_s)$\r
+ \If{$s_{s_{min}} > s_s$}\Comment{Remove if dead}\r
+ \State $CR_{s_{live}} \gets CR_{s_{live}} - \{cr_s\}$ \r
+ \EndIf\r
+\EndFor\r
+\State \Return{$CR_{s_{live}}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{UpdateSM}{$SM_s,CR_s$}\Comment{Remove if dead}\r
+\State $s_{cr_{min}} \gets MinCRSeqN(CR_s)$\r
+ \State $SM_s \gets SM_s - \{\tuple{s_s,id_s} \mid \tuple{s_s,id_s}\r
+ \in SM_s \wedge s_s < s_{cr_{min}}\}$\r
+\State \Return{$CR_{s_{live}}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{CheckLastSeqN}{$MS_s,MS_t,d$}\r
+\For {$\tuple{id, s_t}$ in $MS_t$}\Comment{Check $MS_t$ based on the newer $MS_s$}\r
+ \State $s_s \gets MS_s[id]$\r
+ \If{$d \land s_s = \emptyset$}\r
+ \State \Call{Error}{'Missing $s$ for machine $id$'}\r
+ \ElsIf{$id = id_{self}$ and $s_s \neq s_t$}\r
+ \State \Call{Error}{'Invalid last $s$ for this machine'}\r
+ \ElsIf{$id \neq id_{self}$ and $s_{s_{last}} < s_{t_{last}}$}\r
+ \State \Call{Error}{'Invalid last $s$ for machine $id$'}\r
+ \Else\r
+ \State $MS_t[id] \gets s_s$\r
+ \EndIf\r
+\EndFor\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{CheckCollision}{$MS_s,SM_s,cr_s$}\r
+\If{$cr_s \neq \emptyset$}\r
+ \State $s_s \gets GetS(cr_s)$\r
+ \State $id_s \gets GetId(cr_s)$\r
+ \State $s_{s_{last}} \gets GetLastSeqN(MS_s,id_s)$\r
+ \If{$s_{s_{last}} < s_s$}\r
+ \State $id_t \gets SM_s[s_s]$\r
+ \If{$id_s \neq id_t$}\r
+ \State \Call{Error}{'Invalid $id$ for this slot update'}\r
+ \EndIf\r
+ \EndIf\r
+\EndIf\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{ValidSlotsRange}{$|SL_s|,s_{s_{min}},s_{s_{max}}$}\r
+\State $sz_{SL} \gets s_{s_{max}} - s_{s_{min}} + 1$\r
+\If{$sz_{SL} \neq |SL_s|$}\r
+ \State \Call{Error}{'Sequence numbers range does not match actual set'}\r
+\EndIf\r
+\State $s_{s_{last}} \gets MaxSMSeqN(SM)$\r
+\If{$s_{s_{min}} \leq s_{s_{last}}$}\r
+ \State \Call{Error}{'Server sent old slots'}\r
+\EndIf\r
+\State \Return{$s_{s_{min}} > s_{s_{last}} + 1$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{CheckSlotsRange}{$|SL_s|$}\r
+\State $s_{s_{max}} \gets MaxLastSeqN(MS)$\r
+\State $s_{self} \gets MS[id_{self}]$\r
+\State $sz_{expected} \gets s_{s_{max}} - s_{self} + 1$\r
+\If{$|SL_s| \neq sz_{expected}$}\r
+ \State \Call{Error}{'Actual number of slots does not match expected'}\r
+\EndIf\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{StoreLastSlot}{$MS_s,sl_l,s_s,sv_s,id_s$}\r
+\State $s_{min} \gets MinLastSeqN(MS_s)$\r
+\If{$s_{min} \neq \emptyset \land s_{min} = s_s$}\Comment{$MS$ initially empty}\r
+ \State $sl_l \gets CreateLastSL(s_s,sv_s,id_s)$\r
+\EndIf\r
+\State \Return{$sl_l$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{UpdateDT}{$DT_s,DE_s,LV_s,s_s$}\r
+\State $DE_{s_{kv}} \gets \{de_s | de_s \in DE_s, type(de_s) = "kv"\}$\r
+\ForAll{$de_s \in DE_s$}\r
+ \State $kv_s \gets GetKV(de_s)$\r
+ \State $LV_s \gets \Call{UpdateKVLivEnt}{LV_s,kv_s,s_s}$\r
+ \State $k_s \gets GetKey(kv_s)$\r
+ \State $\tuple{k_s,v_t} \gets GetKeyVal(DT_s,k_s)$\r
+ \If{$\tuple{k_s,v_t} = \emptyset$}\r
+ \State $DT_s \gets DT_s \cup \{\tuple{k_s,v_s}\}$\r
+ \Else\r
+ \State $DT_s \gets (DT_s - \{\tuple{k_s,v_t}\}) \cup \r
+ \{\tuple{k_s,v_s}\}$\r
+ \EndIf\r
+\EndFor\r
+\State \Return{$DT_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{ProcessSL}{$SL_g$}\r
+\State $MS_g \gets \emptyset$\r
+\State $\tuple{s_{g_{min}},sv_{g_{min}}} \gets MinSlot(SL_g)$\r
+\State $\tuple{s_{g_{max}},sv_{g_{max}}} \gets MaxSlot(SL_g)$\r
+\State $d \gets \Call{ValidSlotsRange}{|SL_g|,s_{g_{min}},s_{g_{max}}}$\r
+\For{$s_g \gets s_{g_{min}}$ \textbf{to} $s_{g_{max}}$}\Comment{Process slots \r
+ in $SL_g$ in order}\r
+ \State $\tuple{s_g,sv_g} \gets Slot(SL_g,s_g)$\r
+ \State $Dat_g \gets Decrypt(SK,sv_g)$\r
+ \State $id_g \gets GetMacId(Dat_g)$\r
+ \State $SM \gets SM \cup \{\tuple{s_g,id_g}\}$\r
+ \State $s_{g_{in}} \gets GetSeqN(Dat_g)$\r
+ \If{$s_g \neq s_{g_{in}}$}\r
+ \State \Call{Error}{'Invalid sequence number'}\r
+ \EndIf\r
+ \State $DE_g \gets GetDatEnt(Dat_g)$\r
+ \State $hmac_{p_{stored}} \gets GetPrevHmac(Dat_g)$\r
+ \If {$ \neg(s_g = 0 \land hmac_{p_g} = 0) \land hmac_{p_{stored}} \neq hmac_{p_g}$}\r
+ \State \Call{Error}{'Invalid previous HMAC value'}\r
+ \EndIf\r
+ \If{$\Call{Hmac}{DE_g,SK} \neq GetCurrHmac(Dat_g)$ }\r
+ \State \Call{Error}{'Invalid current HMAC value'}\r
+ \EndIf\r
+ \State $hmac_{p_g} \gets Hmac(DE_g,SK)$\Comment{Update $hmac_{p_g}$ for next check}\r
+ \State $qs_g \gets \Call{GetQueSta}{DE_g}$\Comment{Handle qs}\r
+ \If{$qs_g \neq \emptyset \land qs_g > max_g$}\r
+ \State $max_g \gets qs_g$\r
+ \EndIf\r
+ %Check for last s in Dat\r
+ \State $id_g \gets GetMacId(Dat_g)$\Comment{Handle last s}\r
+ \State $MS_g \gets \Call{UpdateLastSeqN}{id_g,s_g,MS_g}$\r
+ %Check for last s in DE in Dat\r
+ \State $DE_{g_{ss}} \gets \Call{GetSlotSeq}{DE_g}$\Comment{Handle ss}\r
+ \If{$DE_{g_{ss}} \neq \emptyset$}\r
+ \ForAll{$de_{g_{ss}} \in DE_{g_{ss}}$}\r
+ \State $\tuple{id_d,s_{d_{last}}} \gets GetSS(de_{g_{ss}})$\r
+ \State $MS_g \gets \Call{UpdateLastSeqN}{id_d,s_{d_{last}},MS_g}$\r
+ \State $SS_{live} \gets \Call{AddSSLivEnt}{SS_{live},de_{g_{ss}}}$\r
+ \EndFor\r
+ \EndIf\r
+ \State $DE_{g_{cr}} \gets \Call{GetColRes}{DE_g}$\Comment{Handle cr}\r
+ \If{$DE_{g_{cr}} \neq \emptyset$}\r
+ \ForAll{$de_{g_{cr}} \in DE_{g_{cr}}$}\r
+ \State $cr_g \gets GetCR(de_{g_{cr}})$\r
+ \State $\Call{CheckCollision}{MS,SM,cr_g}$\r
+ \State $CR_{live} \gets \Call{AddCRLivEnt}{CR_{live},cr_g}$\r
+ \EndFor\r
+ \EndIf\r
+ \State $sl_{last} \gets \Call{StoreLastSlot}{MS,sl_{last},s_g,sv_g,id_g}$\r
+ \State $DT \gets \Call{UpdateDT}{DT,DE_g,LV,s_g}$\r
+\EndFor\r
+\If{$m + |SL_g| \leq max_g$}\Comment{Check actual size against $max_g$}\r
+ \State $m \gets m + |SL_g|$\r
+\Else\r
+ \State \Call{Error}{'Actual $SL$ size on server exceeds $max_g$'}\r
+\EndIf\r
+\State $\Call{CheckLastSeqN}{MS_g,MS,d}$\r
+\State $\Call{CheckSlotsRange}{|SL_g|}$\r
+\State $\Call{UpdateSSLivEnt}{SS_{live},MS}$\r
+\State $\Call{UpdateCRLivEnt}{CR_{live},MS}$\r
+\State $\Call{UpdateSM}{SM,CR_{live}}$\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{GetKVPairs}{}\r
+\State $s_g \gets GetLastSeqN(MS,id_{self}) + 1$\r
+\State $SL_c \gets \Call{GetSlot}{s_g}$\r
+\State $\Call{ProcessSL}{SL_c}$\Comment{Process slots and update DT}\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{Get}{$k_g$} \Comment{Interface function to get a value}\r
+\State $\tuple{k_s,v_s} \gets \tuple{k,v}$ \textit{such that} $\tuple{k,v} \r
+ \in DT \land k = k_g$\r
+\State \Return{$v_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\subsubsection{Writing Slots}\r
+\textbf{States} \\\r
+\textit{$cp$ = data entry $DE$ maximum size/capacity} \\\r
+\textit{$ck_p$ = counter of $kv \in KV$ for putting pairs (initially 0)} \\\r
+\textit{$ck_g$ = counter of $kv \in KV$ for getting pairs (initially 0)} \\\r
+\textit{$cs_p$ = counter of $ss \in SS$ for putting pairs (initially 0)} \\\r
+\textit{$cs_g$ = counter of $ss \in SS$ for getting pairs (initially 0)} \\\r
+\textit{$cc_p$ = counter of $cr \in CR$ for putting pairs (initially 0)} \\\r
+\textit{$cc_g$ = counter of $cr \in CR$ for getting pairs (initially 0)} \\\r
+\textit{$hmac_{c_p}$ = the HMAC value of the current slot} \\\r
+\textit{$hmac_{p_p}$ = the HMAC value of the previous slot \r
+($hmac_{p_p} = \emptyset$ for the first slot)} \\\r
+\textit{$id_{self}$ = machine Id of this client} \\\r
+\textit{$sl_{last}$ = info of last slot in queue = \r
+ $\tuple{s_{last},sv_{last},id_{last}}$ (initially $\emptyset$)} \\\r
+\textit{$th_p$ = threshold number of dead slots for a resize to happen} \\\r
+\textit{$m'_p$ = offset added to $max$ for resize} \\\r
+\textit{$reinsert_{qs}$ = boolean to decide $qs$($max_g$) reinsertion} \\\r
+\textit{$KV$ = set of $\tuple{ck, \tuple{k,v}}$ of kv entries on client} \\\r
+\textit{$SS$ = set of $\tuple{cs, \tuple{id,s_{last}}}$ of ss entries on client} \\\r
+\textit{$CR$ = set of $\tuple{cc, \tuple{s_{col},id_{col}}}$ of cr entries on client} \\\r
+\textit{$SL_p$ = set of returned slots on client} \\\r
+\textit{SK = Secret Key} \\ \\\r
+\textbf{Helper Functions} \\\r
+$CreateDat(s,id,hmac_p,DE,hmac_c)=Dat_s=\tuple{s,id,hmac_p,DE,hmac_c}$ \\\r
+$CreateSS(id_s,s_{s_{last}})=\tuple{id_s,s_{s_{last}}} = ss_s$ \\\r
+$CreateQS(max'_s)=qs_s$ \\\r
+$CreateCR(s_s,id_s)=\tuple{s_s,id_s} = cr_s$ \\\r
+$Encrypt(Dat_s,SK_s)=sv_s$ \\\r
+$GetLastS(sl = \tuple{s,sv,id})=s$ \\\r
+$GetSV(sl = \tuple{s,sv,id})=sv$ \\\r
+$GetID(sl = \tuple{s,sv,id})=id$ \\\r
+$GetColSeqN(SL_s,s_s)= \tuple{s, sv}$ \textit{such that} $\tuple{s, sv}\r
+\in SL_s \wedge \forall \tuple{s_s, sv_s} \in SL_s, s = s_s$ \\\r
+$GetKVPair(KV_s,k_s)= \tuple{ck,\tuple{k, v}}$ \textit{such that} \r
+$\tuple{ck,\tuple{k, v}} \in KV_s \wedge\r
+\forall \tuple{ck_s,\tuple{k_s, v_s}} \in KV_s, k = k_s$ \\\r
+\r
+\begin{algorithmic}[1]\r
+\Function{Put}{$KV_s,\tuple{k_s,v_s}$} \Comment{Interface function to update a key-value pair}\r
+\State $\tuple{ck_s,\tuple{k_s,v_t}} \gets GetKVPair(KV_s,k_s)$\r
+\If{$\tuple{ck_s,\tuple{k_s,v_t}} = \emptyset$}\r
+ \State $KV_s \gets KV_s \cup \{\tuple{ck_p, \tuple{k_s,v_s}}\}$\r
+ \State $ck_p \gets ck_p + 1$\r
+\Else\r
+ \State $KV_s \gets (KV_s - \{\tuple{ck_s, \tuple{k_s,v_t}}\}) \cup \r
+ \{\tuple{ck_s, \tuple{k_s,v_s}}\}$\r
+\EndIf\r
+\State \Return{$KV_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{PutSSPair}{$SS_s,\tuple{id_s,s_{s_{last}}}$}\Comment{Insert a set of $ss$ entries}\r
+\State $SS_s \gets SS_s \cup \{\tuple{cs_p, \tuple{id_s,s_{s_{last}}}}\}$\r
+\State $cs_p \gets cs_p + 1$\r
+\State \Return{$SS_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{PutCRPair}{$CR_s,\tuple{s_s,id_s}$}\Comment{Insert a set of $cr$ entries}\r
+\State $CR_s \gets CR_s \cup \{\tuple{cc_p, \tuple{s_s,id_s}}\}$\r
+\State $cc_p \gets cc_p + 1$\r
+\State \Return{$CR_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{CheckResize}{$MS_s,th_s,max_t,m'_s$}\r
+\State $s_{last_{min}} \gets MinLastSeqN(MS_s)$\r
+\State $s_{last_{max}} \gets MaxLastSeqN(MS_s)$\r
+\State $n_{live} \gets s_{last_{max}} - s_{last_{min}} + 1$\Comment{Number of live slots}\r
+\State $n_{dead} \gets max_t - n_{live}$\r
+\If{$n_{dead} \leq th_s$}\r
+ \State $max'_s \gets max_t + m'_s$\r
+\Else\r
+ \State $max'_s \gets \emptyset$\r
+\EndIf\r
+\State \Return{$max'_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{CheckSLFull}{$MS_s,max_t$}\Comment{Check if $ss$ is needed}\r
+\State $s_{last_{min}} \gets MinLastSeqN(MS_s)$\r
+\State $s_{last_{max}} \gets MaxLastSeqN(MS_s)$\r
+\State $n_{live} \gets s_{last_{max}} - s_{last_{min}}$\Comment{Number of live slots}\r
+\State $n_{dead} \gets max_t - n_{live}$\r
+\State \Return {$n_{dead} = 0$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{HandleCollision}{$SL_s,s_s$}\r
+\If{$SL_s = \emptyset$}\r
+ \State \Call{Error}{'No slots received from server'}\r
+\EndIf\r
+\State $\tuple{s_{col},sv_{col}} \gets GetColSeqN(SL_s,s_s)$\r
+\State $Dat_{col} \gets Decrypt(SK,sv_{col})$\r
+\State $id_{col} \gets GetMacId(Dat_{col})$\r
+\State $cr_s \gets CreateCR(s_{col},id_{col})$\r
+\State $\Call{ProcessSL}{SL_s}$\r
+\State \Return{$cr_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{CheckLastSlot}{$sl_{s_{last}}$}\r
+\State $s_s \gets GetLastS(sl_{s_{last}})$\r
+\State $sv_s \gets GetSV(sl_{s_{last}})$\r
+\State $Dat_s \gets Decrypt(SK,sv_s)$\r
+\State $DE_s \gets GetDatEnt(Dat_s)$\r
+\ForAll{$de_s \in DE_s$}\r
+ \State $live \gets \Call{CheckLiveness}{s_s,de_s}$\r
+ \If{$live$}\r
+ \If{$de_s = kv$}\r
+ \State $\tuple{k_s,v_s} \gets GetKV(de_s)$\r
+ \State $KV \gets \Call{PutKVPair}{KV,\tuple{k_s,v_s}}$\r
+ \ElsIf{$de_s = ss$}\r
+ \State $\tuple{id_s,s_{s_{last}}} \gets GetSS(de_s)$\r
+ \State $SS \gets \Call{PutSSPair}{SS,\tuple{id_s,s_{s_{last}}}}$\r
+ \ElsIf{$de_s = cr$}\r
+ \State $\tuple{s_s,id_s} \gets GetCR(de_s)$\r
+ \State $CR \gets \Call{PutCRPair}{CR,\tuple{s_s,id_s}}$\r
+ \ElsIf{$de_s = qs$}\r
+ \State $reinsert_{qs} \gets true$\r
+ \EndIf\r
+ \EndIf\r
+\EndFor\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{CheckLiveness}{$s_s,de_s$}\r
+\State $live \gets true$\r
+\If{$de_s = kv$}\r
+ \State $s_l \gets GetLivEntLastS(LV,de_s)$\r
+ \If{$s_l = \emptyset \lor s_s < s_l$}\r
+ \State $live \gets false$\r
+ \EndIf\r
+\ElsIf{$de_s = ss$}\r
+ \State $ss_s \gets GetSS(de_s)$\r
+ \State $ss_l \gets GetLiveSS(SS_{live},ss_s)$\r
+ \If{$ss_l = \emptyset$}\r
+ \State $live \gets false$\r
+ \EndIf\r
+\ElsIf{$de_s = cr$}\r
+ \State $cr_s \gets GetCR(de_s)$\r
+ \State $cr_l \gets GetLiveCR(CR_{live},cr_s)$\r
+ \If{$cr_l = \emptyset$}\r
+ \State $live \gets false$\r
+ \EndIf\r
+\ElsIf{$de_s = qs$}\r
+ \State $qs_s \gets GetQS(de_s)$\r
+ \If{$qs_s \neq max_g$}\r
+ \State $live \gets false$\r
+ \EndIf\r
+\Else\r
+ \State \Call{Error}{'Unrecognized $de$ type'}\r
+\EndIf\r
+\State \Return{$live$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{CreateSlotSeq}{$sl_s$}\r
+\State $id_s \gets GetID(sl_s)$\r
+\State $s_{s_{last}} \gets GetLastS(sl_s)$\r
+\State $ss_s \gets CreateSS(id_s,s_{s_{last}})$\r
+\State \Return{$\tuple{ss_s}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{AddQueSta}{$DE_s,max'_s,cp_s$}\Comment{Insert a $qs$}\r
+\State $DE_{ret} \gets \emptyset$\r
+\State $qs_s \gets max'_s$\r
+\State $DE_{ret} \gets DE_s \cup \{qs_s\}$\r
+\State $cp_s \gets cp_s - 1$\r
+\State \Return{$\tuple{DE_{ret},cp_s}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetKVPairs}{$DE_s,KV_s,cp_s$}\r
+\State $DE_{ret} \gets \emptyset$\r
+\If{$|KV_s| \leq cp_s$}\Comment{$KV$ set can span multiple slots}\r
+ \State $DE_{ret} \gets DE_s \cup\r
+ \{\tuple{k_s,v_s} \mid \tuple{ck_s,\tuple{k_s,v_s}} \in KV_s\}$\r
+\Else\r
+ \State $DE_{ret} \gets DE_s \cup\r
+ \{\tuple{k_s,v_s} \mid \tuple{ck_s,\tuple{k_s,v_s}} \in KV_s,\r
+ ck_g \leq ck_s < ck_g + cp_s\}$\r
+\EndIf\r
+\State \Return{$\tuple{DE_{ret}}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetSSPairs}{$DE_s,SS_s,cp_s$}\r
+\State $DE_{ret} \gets \emptyset$\r
+\If{$|SS_s| \leq cp_s$}\Comment{$SS$ set can span multiple slots}\r
+ \State $DE_{ret} \gets DE_s \cup\r
+ \{\tuple{id_s,s_{s_{last}}} \mid \tuple{cs_s,\tuple{id_s,s_{s_{last}}}} \in SS_s\}$\r
+ \State $cp_s \gets cp_s - |SS_s|$\r
+\Else\r
+ \State $DE_{ret} \gets DE_s \cup\r
+ \{\tuple{id_s,s_{s_{last}}} \mid \tuple{cs_s,\tuple{id_s,s_{s_{last}}}} \in SS_s,\r
+ cs_g \leq cs_s < cs_g + cp_s\}$\r
+ \State $cp_s \gets 0$\r
+\EndIf\r
+\State \Return{$\tuple{DE_{ret},cp_s}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetCRPairs}{$DE_s,CR_s,cp_s$}\r
+\State $DE_{ret} \gets \emptyset$\r
+\If{$|CR_s| \leq cp_s$}\Comment{$CR$ set can span multiple slots}\r
+ \State $DE_{ret} \gets DE_s \cup\r
+ \{\tuple{s_s,id_s} \mid \tuple{cc_s,\tuple{s_s,id_s}} \in CR_s\}$\r
+ \State $cp_s \gets cp_s - |CR_s|$\r
+\Else\r
+ \State $DE_{ret} \gets DE_s \cup\r
+ \{\tuple{s_s,id_s} \mid \tuple{cc_s,\tuple{s_s,id_s}} \in CR_s,\r
+ cc_g \leq cc_s < cc_g + cp_s\}$\r
+ \State $cp_s \gets 0$\r
+\EndIf\r
+\State \Return{$\tuple{DE_{ret},cp_s}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{PutDataEntries}{$th_p,m'_p$}\r
+\State $success_p \gets false$\r
+\State $CR_p \gets \emptyset$\r
+\While{$\neg success_p$}\r
+ \State $DE_p \gets \emptyset$\r
+ \State $s_p \gets MaxLastSeqN(MS)$\r
+ \State $cp_p \gets cp$\r
+ \State $max'_p \gets \Call{CheckResize}{MS,th_p,max_g,m'_p}$\r
+ \If{$max'_p \neq \emptyset$}\Comment{Add a qs entry}\r
+ \State $\tuple{DE_p,cp_p} \gets \Call{AddQueSta}{DE_p,max'_p,cp_p}$\r
+ \State $reinsert_{qs} \gets false$\r
+ \Else\Comment{Check if there is $qs$ reinsertion}\r
+ \If{$reinsert_{qs}$}\r
+ \State $\tuple{DE_p,cp_p} \gets \Call{AddQueSta}{DE_p,max_g,cp_p}$\r
+ \State $reinsert_{qs} \gets false$\r
+ \EndIf\r
+ \EndIf\r
+ \If{$SS \neq \emptyset$}\Comment{Add $ss$ entries}\r
+ \State $\tuple{DE_p,cp_p} \gets \Call{GetSSPairs}{DE_p,SS,cp_p}$\r
+ \EndIf\r
+ \If{$CR \neq \emptyset$}\Comment{Add $cr$ entries}\r
+ \State $\tuple{DE_p,cp_p} \gets \Call{GetCRPairs}{DE_p,CR,cp_p}$\r
+ \EndIf\r
+ \State $\tuple{DE_p,cp_p} \gets \Call{GetKVPairs}{DE_p,KV,cp_p}$\Comment{Add $kv$ entries}\r
+ \State $hmac_{c_p} \gets Hmac(DE_p,SK)$\r
+ \State $Dat_p \gets CreateDat(s_p,id_{self},hmac_{p_p},DE_p,hmac_{c_p})$\r
+ \State $hmac_{p_p} \gets hmac_{c_p}$\r
+ \State $sv_p \gets Encrypt(Dat_p,SK)$\r
+ \State $\tuple{success_p,SL_p} \gets \Call{PutSlot}{s_p,sv_p,max'_p}$\r
+ \If{$\neg success_p$}\r
+ \State $cr_p \gets \Call{HandleCollision}{SL_p,s_p}$\r
+ \State $\tuple{s_{p_{col}},id_{p_{col}}} \gets GetCR(cr_p)$\r
+ \State $CR \gets \Call{PutCRPair}{CR,\tuple{s_{p_{col}},id_{p_{col}}}}$\r
+ \EndIf\r
+\EndWhile\r
+\State $MS \gets \Call{UpdateLastSeqN}{id_{self},s_p,MS}$\r
+\If{$|DE_p| = cp$}\Comment{Update set counters}\r
+ \State $ck_g \gets ck_g + cp_p$\Comment{Middle of set}\r
+ \State $cs_g \gets cs_g + |SS|$\r
+ \State $cc_g \gets cc_g + |CR|$\r
+\Else\Comment{End of set}\r
+ \State $ck_g \gets 0$\r
+ \State $cs_g \gets 0$\r
+ \State $cc_g \gets 0$\r
+\EndIf\r
+\State $need_p \gets \Call{CheckSLFull}{MS,max_g}$\r
+\If{$need_p$}\Comment{SL on server is full}\r
+ \State $\Call{CheckLastSlot}{sl_{last}}$\Comment{Salvage entries from expunged slot}\r
+ \State $ss_p \gets \Call{CreateSlotSeq}{sl_{last}}$\r
+ \State $\tuple{id_p,s_{p_{last}}} \gets GetSS(ss_p)$\r
+ \State $SS \gets \Call{PutSSPair}{SS,\tuple{id_p,s_{p_{last}}}}$\Comment{Add ss}\r
+\EndIf\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+%\note{Lots of problems with PutDataEntries: (1) What happens if lose network connectivity after adding the key value pair, but before reinserting the last slot? You probably need to create space first and then insert your data entry... (2) What if reinsertlastslot kicks something else important out? What if the server rejects our update because it is out of date? At the very least, any putdataentries function w/o a loop is wrong!}\r
+\r
+%\note{General comments... Work on structuring things to improve readability... This include names of functions/variables, how things are partitioned into functions, adding useful comments,...}\r
+ \r
+%\note{Also Missing liveness state definition in algorithm...}\r
+\r