Added simple diagram for lemma in proof
[iotcloud.git] / doc / iotcloud.tex
index b55f16fb4d237c35305b47fdc8afa43978235d33..250ddcf165b0c7eb011febd3268f9f88d5126b41 100644 (file)
@@ -3,8 +3,13 @@
 \usepackage{color}\r
 \usepackage{amsthm}\r
 \usepackage{amsmath}\r
+\usepackage{graphicx}\r
+\usepackage{mathrsfs}\r
 \usepackage{algpseudocode}% http://ctan.org/pkg/algorithmicx\r
+\usepackage[all]{xy}\r
 \newtheorem{theorem}{Theorem}\r
+\newtheorem{prop}{Proposition}\r
+\newtheorem{lem}{Lemma}\r
 \newtheorem{defn}{Definition}\r
 \newcommand{\note}[1]{{\color{red} \bf [[#1]]}}\r
 \newcommand{\push}[1][1]{\hskip\dimexpr #1\algorithmicindent\relax}\r
@@ -52,11 +57,15 @@ client's last entry from the queue. This is kept in the slot until
 the entry owner inserts a newer update into the queue.}\r
 \item Queue state entry: Includes queue size \newline {The purpose \r
 of this is for the client to tell if the server lies about the number \r
-of slots in the queue, e.g. if there are 2 queue state entries in the queue, \r
+of slots in the queue, e.g. if there are 2 queue state entry in the queue, \r
 e.g. 50 and 70, the client knows that when it sees 50, it should expect \r
 at most 50 slots in the queue and after it sees 70, it should expect \r
 50 slots before that queue state entry slot 50 and at most 70 slots. \r
 The queue state entry slot 70 is counted as slot number 51 in the queue.}\r
+\item Collision resolution entry: message identifier + machine id of a\r
+collision winner\r
+\newline {The purpose of this is to keep keep track of the winner of \r
+all the collisions until all clients have seen the particular entry.}\r
 \end{enumerate}\r
 \r
 \subsection{Live status}\r
@@ -72,6 +81,9 @@ or user-level data) is dead if there is a newer slot from the same machine.
 {In the case of queue state entries 50 and 70, this means that queue state \r
 entry 50 is dead and 70 is live. However, not until the number of slots reaches \r
 70 that queue state entry 50 will be expunged from the queue.}\r
+\r
+\item Collision resolution entry is dead if this entry has been seen\r
+by all clients after a collision happens.\r
 \end{enumerate}\r
 \r
 When data is at the end of the queue ready to expunge, if:\r
@@ -107,8 +119,7 @@ A list of machines and the corresponding latest sequence numbers.
     (a) check its HMAC, and\r
     (b) check that the previous entry HMAC field matches the previous\r
     entry.\r
-\item Check that the last message version for our machine matches our\r
-last message sent.\r
+\item Check that the last-message entry for our machine matches the stored HMAC of our last message sent.\r
 \item For all other machines, check that the latest sequence number is\r
 at least as large (never goes backwards).\r
 \item That the queue has a current queue state entry.\r
@@ -121,23 +132,21 @@ they are complete.
 \r
 \subsection{Resizing Queue}\r
 Client can make a request to resize the queue. This is done as a write that combines:\r
-  (a) a slot with the message, and\r
-       (b) a request to the server\r
+  (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
+$s \in SN$ is a sequence number set\\\r
 $sv \in SV$ is a slot's value\\\r
-$slot_s = \tuple{s, sv} \in SL \subseteq SN \times SV$ \\\r
-\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')= \tuple{s, sv} \mid \tuple{s, sv}\r
-\in SL' \wedge \forall \tuple{s', sv'} \in SL', s \geq s'$ \\\r
-$MinSlot(SL')= \tuple{s, sv} \mid \tuple{s, sv} \r
-\in SL' \wedge \forall \tuple{s', sv'} \in SL', s \leq s'$ \\\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(\tuple{s, sv})=s$ \\\r
 $SlotVal(\tuple{s, sv})=sv$ \\\r
 \r
@@ -149,7 +158,7 @@ $SlotVal(\tuple{s, sv})=sv$ \\
 \r
 \begin{algorithmic}[1]\r
 \Function{PutSlot}{$s_p,sv_p,max'$}\r
-\If{$(max' \neq \emptyset)$}\Comment{Resize}\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
@@ -171,224 +180,568 @@ $SlotVal(\tuple{s, sv})=sv$ \\
 \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 set \\\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
+$sv_s = \tuple{s, E(Dat_s)} = \r
+\tuple{s, E(\tuple{s,id,hmac_p,DE,hmac_c})}$ \\ \\\r
+\r
+\textbf{States} \\\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{$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 a previous read\r
+(initially empty)} \\ \\\r
+\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
+$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
+$GetKV($key-value data entry$)=\tuple{k_s,v_s}$ \\\r
+$GetSS($slot-sequence data entry$)=\tuple{id,s_{last}}$ \\\r
+$GetQS($queue-state data entry$)=qs_s$ \\\r
+$GetCR($collision-resolution data entry$)=\tuple{s_s,id_s}$ \\\r
+$GetS(\tuple{s, id})=s$ \\\r
+$GetId(\tuple{s, id})=id$ \\\r
+$GetKey(\tuple{k, v})=k$ \\\r
+$GetVal(\tuple{k, v})=v$ \\\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
+\r
 \begin{algorithmic}[1]\r
-\Function{CallClient}{$uid,pw,d,m,max,s,Data*,Result*$}\r
-\textit{\r
-\newline{// uid = user identification}\r
-\newline{// pw = password}\r
-\newline{// d = new data for write}\r
-\newline{// m = client message (read/write/resize)}\r
-\newline{// max = maximum number of slots (input only for resize message)}\r
-\newline{// n = number of slots}\r
-\newline{// s = sequence number for server request}\r
-\newline{// t = sequence numbers of slots on server}\r
-\newline{// mid = machine identification}\r
-\newline{// seq = sequence number inside slot}\r
-\newline{// newSlot = new slot}\r
-\newline{// expSlot = expunged/expired slot}\r
-\newline{// slotSeqE = slot sequence entry}\r
-\newline{// M = list of all machines/devices with their respective latest s on client}\r
-\newline{// Data = array of slots written/read (input only for write)}\r
-\newline{// Result = array of decrypted and valid slots after a read}\r
-\newline{// Slot = one data slot)}\r
-\newline{// DSlot = one decrypted data slot)}\r
-}\r
-\State $SK = Hash(uid + pw)$\r
-\If{$m = read$}\r
-       \State $Data \gets CallServer(m,max,s,Data)$\r
-       \If{$Data = \emptyset$}\r
-               \State $ReportError(\emptyset,read)$\r
-       \Else\r
-               \If{$\neg HasCurrentQueueStateEntry(Data)$}\r
-                       \State $ReportError(DSlot_i,read)$\r
-               \EndIf\r
-               \ForAll{$Slot_i \in Data$}\r
-                       \State $DSlot_i \gets Decrypt(SK,Slot_i)$\Comment{Check s and HMAC}\r
-                       \If{$\neg (ValidSeqN(DSlot_i) \land ValidHmac(DSlot_i) \land $\\\r
-                               \push[1] $ValidPrevHmac(DSlot_i))$}\r
-                               \State $ReportError(DSlot_i,read)$\r
-                       \Else\Comment{Check only live entries}\r
-                               \If{$IsLiveSlotSequenceEntry(DSlot_i)$}\r
-                                       \State $lastS \gets LastSeqN(DSlot_i)$\r
-                                       \State $lastMid \gets LastMachineId(DSlot_i)$\r
-                                       \If{$lastS \neq LastSeqN(lastMid,M)$}\r
-                                               \State $ReportError(DSlot_i,read)$\r
-                                       \EndIf\r
-                               \ElsIf{$IsLiveKeyValueEntry(DSlot_i)$}\r
-                                       \State $mid \gets MachineId(DSlot_i)$\r
-                                       \State $seq \gets SeqN(DSlot_i)$\r
-                                       \If{$IsOwnMid(mid)$}\r
-                                               \If{$IsLastS(mid,seq,Data) \land $\\\r
-                                               \push[1] $(seq \neq LastSeqN(mid,M))$}\r
-                                                       \State $ReportError(DSlot_i,read)$\r
-                                               \EndIf\r
-                                       \Else\Comment{Check s for other machines}\r
-                                               \If{$IsLastS(mid,seq,Data) \land $\\\r
-                                               \push[1] $(seq < LastSeqN(mid,M))$}\r
-                                                       \State $ReportError(DSlot_i,read)$\r
-                                               \EndIf\r
-                                       \EndIf\Comment{Check queue state entry}\r
-                               \ElsIf{$IsLiveQueueStateEntry(DSlot_i)$}\r
-                                       \If{$IsCurrentQueueState(DSlot_i)$}\r
-                                               \If{$Length(Data) > QueueLength(DSlot_i)$}\r
-                                                       \State $ReportError(DSlot_i,read)$\r
-                                               \EndIf\r
-                                       \EndIf\r
-                               \Else\r
-                                       \State $ReportError(DSlot_i,read)$\r
-                               \EndIf\r
-                       \EndIf\r
-                       \State $Result \gets Concat(Result, DSlot_i)$\r
-               \EndFor\r
+\Procedure{Error}{$msg$}\r
+\State $Print(msg)$\r
+\State $Halt()$\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{ValidHmac}{$DE_s,SK_s,hmac_{stored}$}\r
+\State $hmac_{computed} \gets Hmac(DE_s,SK_s)$\r
+\State \Return {$hmac_{stored} = hmac_{computed}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{ValidPrevHmac}{$DE_s,hmac_{p_s},hmac_{p_{sto}}$}\r
+\If{$hmac_{p_s} = \emptyset$}\Comment{First slot - no previous HMAC}\r
+       \State \Return $true$\r
+\Else\r
+       \State \Return {$hmac_{p_{sto}} = hmac_{p_s}$}\r
+\EndIf\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\note{So if a slot has a null previous hmac, everything is fine?  What if it isn't the first slot?}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetQueSta}{$Dat_s$}\r
+\State $DE_s \gets GetDatEnt(DE_s)$\r
+\State $de_{qs} \gets de_s$ \textit{such that} $de_s \in DE_s, \r
+       de_s \in D \land 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}{$Dat_s$}\r
+\State $DE_s \gets GetDatEnt(Dat_s)$\r
+\State $de_{ss} \gets de_s$ \textit{such that} $de_s \in DE_s, \r
+       de_s \in D \land de_s = ss$\r
+\If{$de_{ss} \neq \emptyset$}\r
+       \State $\tuple{id_{ret},s_{last_{ret}}} \gets GetSS(de_{ss})$\r
+\Else\r
+       \State $\tuple{id_{ret},s_{last_{ret}}} \gets \emptyset$\r
+\EndIf\r
+\State \Return{$\tuple{id_{ret},s_{last_{ret}}}$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetColRes}{$Dat_s$}\Comment{At most 2 $cr$ entries in a slot}\r
+\State $DE_s \gets GetDatEnt(Dat_s)$\r
+\State $de_{cr} \gets de_s$ \textit{such that} $de_s \in DE_s, \r
+       de_s \in D \land de_s = cr$\r
+\If{$de_{cr} \neq \emptyset$}\r
+       \State $\tuple{s_{ret},id_{ret}} \gets GetCR(de_{cr})$\r
+\Else\r
+       \State $\tuple{s_{ret},id_{ret}} \r
+       \gets \emptyset$\r
+\EndIf\r
+\State $de_{r_{cr}} \gets de_s$ \textit{such that} $de_s \in DE_s, \r
+       de_s \in D \land de_s = cr \land de_s \neq de_{cr}$\r
+\If{$de_{r_{cr}} \neq \emptyset$}\r
+       \State $\tuple{s_{r_{ret}},id_{r_{ret}}} \gets GetCR(de_{r_{cr}})$\r
+\Else\r
+       \State $\tuple{s_{r_{ret}},id_{r_{ret}}} \r
+       \gets \emptyset$\r
+\EndIf\r
+\State \Return{$\{\tuple{s_{ret},id_{ret}},\tuple{s_{r_{ret}},id_{r_{ret}}}\}$}\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
+\Procedure{CheckLastSeqN}{$MS_s,MS_t$}\Comment{Check $MS_t$ based on the newer $MS_s$}\r
+\For {$\tuple{id, s_t}$ in $MS_t$}\r
+       \State $s_s \gets MS_s[id]$\r
+       \If{$s_s = \emptyset$}\r
+       \Call{Error}{'No $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,\tuple{s_s,id_s}$}\r
+\If{$\tuple{s_s,id_s} \neq \emptyset$}\r
+       \State $s_s \gets GetS(\tuple{s_s,id_s})$\r
+       \State $id_s \gets GetId(\tuple{s_s,id_s})$\r
+       \State $s_{s_{last}} \gets GetLastSeqN(MS_s,id_s)$\r
+       \If{$s_{s_{last}} < s_s$}\r
+               \State $\Call{CheckColRes}{SM_s,\tuple{s_s,id_s}}$\r
+       \EndIf\r
+\EndIf\r
+\EndProcedure\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Procedure{CheckColRes}{$SM_s,\tuple{s_t,id_t}$}\Comment{Check $id_s$ in $SM_s$}\r
+\State $id_s \gets SM_s[s_t]$\r
+\If{$id_s \neq id_t$}\r
+       \State \Call{Error}{'Invalid $id_s$ for this slot update'}\r
+\EndIf\r
+\EndProcedure\r
+\end{algorithmic}\r
 \r
-\ElsIf{$m = write$}\r
-       \State $newSlot \gets CreateSlot(d)$\r
-       \State $Data[1] \gets Encrypt(SK,newSlot)$\r
-       \State $Data \gets CallServer(m,max,s,Data)$\r
-       \If{$Data = \emptyset$}\r
-               \State $ReportError(\emptyset,write)$\r
-       \Else\Comment Check for valid return value from server\r
-               \If{$\neg ValidOldLastEntry(Data[1])$}\r
-                       \State $ReportError(Data[1],write)$\r
-               \Else\Comment{Check if we need slot sequence entry}\r
-                       \If{$Length(Data) = 2$}\r
-                               \State $expSlot \gets Decrypt(SK,Data[2])$\r
-                               \State $mid \gets MachineId(expSlot)$\r
-                               \State $seq \gets SeqN(expSlot)$\r
-                               \If{$seq = LastSeqN(mid,M)$}\Comment{Liveness check}\r
-                                       \State $slotSeqE \gets CreateSlotSeqE(mid,seq)$\r
-                                       \State $Data[1] \gets Encrypt(SK,slotSeqE)$\r
-                                       \State $Data \gets CallServer(m,max,s,Data)$\r
-                               \EndIf\r
-                       \Else\r
-                               \State $ReportError(Data,write)$\r
-                       \EndIf\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,Dat_s$}\r
+\State $DE_s \gets GetDatEnt(Dat_s)$\r
+\ForAll{$de_s \in DE_s$}\r
+       \If{$de_s$ \textit{such that} $de_s \in D \land de_s = kv$}\r
+               \State $\tuple{k_s,v_s} \gets GetKV(de_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
+    \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 $SM_{curr} \gets \emptyset$\r
+\State $\tuple{s_{g_{max}},sv_{g_{max}}} \gets MaxSlot(SL_g)$\r
+\State $s_{g_{max}} \gets SeqN(\tuple{s_{g_{max}},sv_{g_{max}}})$\r
+\State $\tuple{s_{g_{min}},sv_{g_{min}}} \gets MinSlot(SL_g)$\r
+\State $s_{g_{min}} \gets SeqN(\tuple{s_{g_{min}},sv_{g_{min}}})$\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 $SM_{curr} \gets SM_{curr} \cup \{\tuple{s_g,sv_g}\}$\r
+       \State $Dat_g \gets Decrypt(SK,sv_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 \Call{ValidPrevHmac}{DE_g,hmac_{p_g},hmac_{p_{stored}}}$}\r
+               \State \Call{Error}{'Invalid previous HMAC value'}\r
+       \EndIf\r
+       \State $hmac_{c_g} \gets GetCurrHmac(Dat_g)$\r
+       \If{$\neg \Call{ValidHmac}{DE_g,SK,hmac_{c_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}{Dat_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 $\tuple{id_d,s_{d_{last}}} \gets \Call{GetSlotSeq}{Dat_g}$\Comment{Handle ss}\r
+       \If{$\tuple{id_d,s_{d_{last}}} \neq \emptyset$}\r
+       \State $MS_g \gets \Call{UpdateLastSeqN}{id_d,s_{d_{last}},MS_g}$\r
+       \EndIf\r
+       \State $\{\tuple{s_e,id_e},\tuple{s_f,id_f}\} \gets \r
+       \Call{GetColRes}{Dat_g}$\Comment{Handle cr}\r
+       \State $\Call{CheckCollision}{MS,SM,\tuple{s_e,id_e}}$\Comment{From normal slot}\r
+       \State $\Call{CheckCollision}{MS,SM,\tuple{s_f,id_f}}$\Comment{From reinsertion}\r
+       \State $sl_{last} \gets \Call{StoreLastSlot}{MS,sl_{last},s_g,sv_g,id_g}$\r
+       \State $DT \gets \Call{UpdateDT}{DT,Dat_g}$\r
+\EndFor\r
+\State $SM \gets SM_{curr}$\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 queue size exceeds $max_g$'}\r
+\EndIf\r
+\State $\Call{CheckLastSeqN}{MS_g,MS}$\r
+\EndProcedure\r
+\end{algorithmic}\r
 \r
-\ElsIf{$m = resize$}\r
-       \State $Data \gets CallServer(m,max,s,Data)$\r
-       \If{$Data = \emptyset$}\r
-               \State $ReportError(\emptyset,resize)$\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{GetValFromKey}{$k_g$}\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{Data Entry} \\\r
+$k$ is key of entry \\\r
+$v$ is value of entry \\\r
+$kv$ is a key-value entry $\tuple{k,v}$\\\r
+$D = \{kv,ss,qs,cr\}$ \\\r
+$DE = \{de \mid de \in D\}$ \\\r
+$Dat_s = \tuple{s,id,hmac_p,DE,hmac_c}$ \\\r
+$sv_s = \tuple{s, E(Dat_s)} = \r
+\tuple{s, E(\tuple{s,id,hmac_p,DE,hmac_c})}$ \\ \\\r
+\textbf{States} \\\r
+\textit{$cp$ = data entry $DE$ maximum size/capacity} \\\r
+\textit{$cr_p$ = saved cr entry $\tuple{s,id}$ on client if there is a collision\r
+(sent in the following slot)} \\\r
+\textit{$cr_{p_{last}}$ = saved cr entry $\tuple{s,id}$ on client if there is a \r
+collision in reinserting the last slot (sent in the following slot)} \\\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{$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{$KV$ = set of $\tuple{ck, \tuple{k,v}}$ of kv 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
+$CreateCR(s,id)=\tuple{s,id}$ \\\r
+$CreateQS(max')=qs$ \\\r
+$CreateSS(id,s_{last})=\tuple{id,s_{last}}$ \\\r
+$Encrypt(Dat_s,SK_s)=sv_s$ \\\r
+$GetStatus(\tuple{status,SL})=status$ \\\r
+$GetSL(\tuple{status,SL})=SL$ \\\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
+$GetKV(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{PutKVPair}{$KV_s,\tuple{k_s,v_s}$}\r
+\State $\tuple{ck_s,\tuple{k_s,v_t}} \gets GetKV(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{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}}$\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{CheckNeedSS}{$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}{$\tuple{stat_s,SL_s}$}\r
+\State $stat_s \gets GetStatus(\tuple{stat_s,SL_s})$\r
+\State $SL_s \gets GetSL(\tuple{stat_s,SL_s})$\r
+\If{$\neg stat_s$}\Comment{Handle collision}\r
+       \State $\tuple{s_{col},sv_{col}} \gets GetColSeqN(SL_s,s_s)$\r
+       \State $s_{col} \gets SeqN(\tuple{s_{col},sv_{col}})$\r
+       \State $sv_{col} \gets SlotVal(\tuple{s_{col},sv_{col}})$\r
+       \State $Dat_{col} \gets Decrypt(SK,sv_{col})$\r
+       \State $id_{col} \gets GetMacId(Dat_{col})$\r
+       \State $\tuple{s_{col},id_{col}} \gets CreateCR(s_{col},id_{col})$\r
+       \State $cr_s \gets \tuple{s_{col},id_{col}}$\r
+\Else\r
+       \State $cr_s \gets \emptyset$\r
+\EndIf\r
+\State $\Call{ProcessSL}{SL_s}$\r
+\State \Return{$cr_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\r
+\begin{algorithmic}[1]\r
+\Function{ReinsertLastSlot}{$need_s,sl_{s_{last}},max'_s$}\r
+\If{$need_s$}\r
+       \State $s_s \gets GetLastS(sl_{s_{last}})$\r
+       \State $sv_s \gets GetSV(sl_{s_{last}})$\r
+       \State $\tuple{stat_s,SL_s} \gets \Call{PutSlot}{s_s,sv_s,max'_s}$\r
+       \State $cr_s \gets \Call{HandleCollision}{\tuple{stat_s,SL_s}}$\r
+\EndIf\r
+\State \Return{$cr_s$}\r
+\EndFunction\r
+\end{algorithmic}\r
+\note{Shouldn't this function do something pretty sophisticated about seeing what data we actually need to keep from the last slot and not just insert the entire thing?}\r
+\r
+\note{Probably best to just not call this function is $need_s$ is false and not pass in such parameters.  It makes it harder to read.}\r
+\r
+\r
+\begin{algorithmic}[1]\r
+\Function{GetDEPairs}{$KV_s,max'_s,need_s,sl_s$}\r
+\State $DE_{ret} \gets \emptyset$\r
+\State $cp_s \gets cp$\r
+\If{$cr_p \neq \emptyset$}\Comment{Check and insert a $cr$}\r
+       \State $DE_{ret} \gets DE_{ret} \cup cr_p$\r
+       \State $cp_s \gets cp_s - 1$\r
+\EndIf\r
+\If{$cr_{p_{last}} \neq \emptyset$}\Comment{Check and insert a $cr$}\r
+       \State $DE_{ret} \gets DE_{ret} \cup cr_{p_{last}}$\r
+       \State $cp_s \gets cp_s - 1$\r
+\EndIf\r
+\If{$max'_s \neq \emptyset$}\Comment{Check and insert a $qs$}\r
+       \State $qs_s \gets max'_s$\r
+       \State $DE_{ret} \gets DE_{ret} \cup qs_s$\r
+       \State $cp_s \gets cp_s - 1$\r
+\EndIf\r
+\If{$need_s$}\Comment{Check and insert a $ss$}\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 $DE_{ret} \gets DE_{ret} \cup ss_s$\r
+       \State $cp_s \gets cp_s - 1$\r
+\EndIf\r
+\If{$|KV_s| \leq cp$}\Comment{$KV$ set can extend multiple slots}\r
+       \State $DE_{ret} \gets DE_{ret} \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_{ret} \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
+       \If{$|DE_{ret}| = cp$}\r
+               \State $ck_g \gets ck_g + cp_s$\Comment{Middle of KV set}\r
+       \Else\r
+               \State $ck_g \gets 0$\Comment{End of KV set}\r
        \EndIf\r
 \EndIf\r
-\State \Return{$Result$}\r
+\State \Return{$DE_{ret}$}\r
 \EndFunction\r
 \end{algorithmic}\r
 \r
-\subsection{Formal Guarantees}\r
-\r
-\textit{To be completed ...}\r
-\r
-\begin{defn}[System Execution]\r
-Let \\\r
-\begin{center}\r
-$Q = \{slot_{sn_1}, slot_{sn_2}, \dots, Slot_{sn_n}\}$, \\\r
-$SN = \{sn_1, sn_2, \dots, sn_n\}$ \\\r
-\end{center}\r
-denote a queue $Q$ of $n$ slots, with each slot entry being denoted by a\r
-valid sequence number $sn_i \in SN$. $Q$ represents a total order of all \r
-slot updates from all corresponding machines.\r
-%\textit{Formalize a system execution as a sequence of slot updates...\r
-%There is a total order of all slot updates.}\r
-\end{defn}\r
-\r
-\begin{defn}[Transitive Closure]\r
-A transitive closure $\tau : \tau = \epsilon_{update(slot_i)} R $\r
-$\epsilon_{receive(slot_i)}$ is a relation from slot update event\r
-$\epsilon$ to a slot receive event $\epsilon$ for $slot_i$.\r
-%Define transitive closure relation for slot updates...  There is an\r
-%edge from a slot update to a slot receive event if the receive event\r
-%reads from the update event.\r
-\end{defn}\r
-\r
-\begin{defn}[Suborder]\r
-Let \\\r
-\begin{center}\r
-$q = \{slot_{i}, slot_{i+1}, \dots, slot_{j}\}, \r
-sn_1 \leq i \leq j \leq sn_n \Longrightarrow q \subseteq Q$\r
-\end{center}\r
-denote a suborder of the total order. Set q is a sequence of contiguous\r
-slot updates that is a subset of a total order of all slot updates in Q.\r
-%Define suborder of total order.  It is a sequence of contiguous slots\r
-%updates (as observed by a given device).\r
-\end{defn}\r
-\r
-\begin{defn}[Prefix of a suborder]\r
-Given a suborder \\ \r
-\begin{center}\r
-$q' = \{slot_{i}, slot_{i+1}, \dots, slot_{j}, \dots\}, \r
-sn_1 \leq i \leq j \leq sn_n \Longrightarrow \r
-q' \subseteq Q$\r
-\end{center}\r
-with $slot_{j}$ as a slot update in $q'$, the prefix of $q'$ is a sequence \r
-of all slot updates $\{slot_{i}, slot_{i+1}, \dots, slot_{j-1}\} \cup\r
-slot_{j}$.\r
-%Given a sub order $o=u_{i},u_{i+1},...,u_j, u_{j+i},..., u', ...$ and\r
-%a slot update $u'$ in $o$, the prefix of $o$ is a sequence of all\r
-%updates that occur before $u'$ and $u'$.\r
-\end{defn}\r
-\r
-\begin{defn}[Consistency between a suborder and a total order]\r
-A suborder $q'$ is consistent with a total order $T$ of $Q$, if all\r
-updates in $q'$ appear in $T$ and they appear in the same order, as \r
-the following:\r
-\begin{center}\r
-$q' = \{slot_{i}, slot_{i+1}, \dots, slot_{j}\},$\r
-$T = \{slot_{sn_1}, \dots, slot_{i}, slot_{i+1}, \dots, slot_{j}, \dots,\r
-slot_{sn_n}\},$ \\ $sn_1 \leq i \leq j \leq sn_n \Longrightarrow\r
-q' \subseteq T$\r
-\end{center}\r
-%A suborder $o$ is consistent with a total order $t$, if all updates in $o$ %appear in $t$ and they appear in the same order.\r
-\end{defn}\r
-\r
-\begin{defn}[Consistency between suborders]\r
-Two suborders U and V are consistent if there exist a total order T \r
-such that both U and V are suborders of T.\r
-\begin{center}\r
-$U = \{slot_{i}, slot_{i+1}, \dots, slot_{j}\},$ \\\r
-$V = \{slot_{k}, slot_{k+1}, \dots, slot_{l}\},$ \\\r
-$sn_1 \leq i \leq j \leq k \leq l \leq sn_n,$ \\\r
-$U \subset T \land V \subset T$ \\\r
-$T = \{slot_{sn_1}, \dots, slot_{i}, slot_{i+1}, \dots, slot_{j}, $\\\r
-$\dots, slot_{k}, slot_{k+1}, \dots, slot_{l}, \dots, slot_{sn_n}\}$\r
-\end{center}\r
-%Define notion of consistency between suborders...  Two suborders U,V\r
-%are consistent if there exist a total order T such that both U and V\r
-%are suborders of T.\r
-\end{defn}\r
-\r
-\begin{defn}[Error-free execution]\r
-An error-free execution, for which the client does not flag any errors\r
-is defined by the following criteria:\r
+\begin{algorithmic}[1]\r
+\Procedure{PutDataEntries}{$th_p,m'_p$}\r
+\State $s_p \gets MaxLastSeqN(MS)$\r
+\State $max'_p \gets \Call{CheckResize}{MS,th_p,max'_g,m'_p}$\r
+\State $need_p \gets \Call{CheckNeedSS}{MS,max'_g}$\r
+\State $DE_p \gets \Call{GetDEPairs}{KV,max'_p,need_p,sl_{last}}$\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{stat_p,SL_p} \gets \Call{PutSlot}{s_p,sv_p,max'_p}$\r
+\State $cr_p \gets \Call{HandleCollision}{\tuple{stat_p,SL_p}}$\r
+\State $cr_{p_{last}} \gets \Call{ReinsertLastSlot}{need_p,sl_{last},max'_p}$\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\r
+  readability...  This include names of functions/variables, how\r
+  things are partitioned into functions, adding useful comments,...}\r
+\r
+\r
+\subsection{Definitions for Formal Guarantees}\r
+\r
 \begin{enumerate}\r
-\item Item 1\r
-\item Item 2\r
+\item Equality: Two messages $t$ and $u$ are equal if their sequence numbers, senders, and contents are exactly the same.\r
+\item Message: A message $t$, is the tuple $t = (i(t), s(t), contents(t))$ containing the sequence number, machine ID of the sender, and contents of $t$ respectively.\r
+\item Parent: A parent of a message $t$ is the message $A(t)$, unique by the correctness of HMACs, such that $HMAC_C(t) = HMAC_P(A(t))$.\r
+\item Partial message sequence: A partial message sequence is a sequence of messages, no two with the same sequence number, that can be divided into disjoint chains, where a chain of messages with length $n \ge 1$ is a message sequence $(t_i, t_{i+1}, ..., t_{i+n-1})$ such that for every index $i < k \le i+n-1$, $t_k$ has sequence number $k$ and is the parent of $t_{k-1}$.\r
+\item Total message sequence: A total message sequence $T$ with length $n$ is a chain of messages that starts at $i = 1$.\r
+\item Path: The path of a message $t$ is the total message sequence whose last message is $t$.\r
+\item Consistency: A partial message sequence $P$ is consistent with a total message sequence $T$ of length $n$ if for every message $p \in P$ with $i(p) < n$, $T_{i(p)} = p$. This implies that $\{p \in P | i(p) \le n\}$ is a subsequence of T.\r
+\item Transitive closure set at index $n$: A set $\mathscr{S}$ of clients comprising a connected component of an undirected graph, where two clients are connected by an edge if they both received the same message $t$ with index $i(t) > n$.\r
+\r
 \end{enumerate}\r
-%not flag any errors...\r
-%Define error-free execution --- execution for which the client does\r
-%not flag any errors...\r
-\end{defn}\r
-\r
-\begin{theorem} Error-free execution of algorithm ensures that the suborder\r
-for node n is consistent with the prefix suborder for all other nodes\r
-that are in the transitive closure.\r
-\end{theorem}\r
+\r
+\subsection{Formal Guarantee}\r
+\r
+\begin{prop} Every client $J$ who sends a message $t$ has $A(t)$ as its latest stored message, and $i(t) = i(A(t)) + 1$. \end{prop}\r
+\begin{proof} True by definition, because $J$ sets $HMAC_P(t) = HMAC_C(A(t))$ and $i(t) = i(A(t)) + 1$ when a message is sent. \end{proof}\r
+\r
+\begin{prop} If a rejected message entry is added to the RML at index $i$, the message will remain in the RML until every client has seen it. \end{prop}\r
+\begin{proof} Every RML entry $e$ remains in the queue until it reaches the tail, and is refreshed by the next sender $J$ at that time if $min(MS) > i(e)$; that is, until every client has sent a message with sequence number greater than $i(e)$. Because every client who sends a message with index $i$ has the state of the queue at $i - 1$, this client will have seen the message at $i(e)$. \end{proof}\r
+\r
+\begin{lem} \r
+\r
+\end{lem}\r
+\r
+\begin{figure}[h]\r
+  \centering\r
+      \xymatrix{\r
+\dots \ar[r] & q \ar[dr]_{J} \ar[r]^{K} & S_1 \ar[r] & S_2 \ar[rr] & & \dots \ar[r] & S_n = u \\\r
+& & R_1 \ar[r] & R_2 \ar[r] & \dots \ar[r] & R_m = t}\r
+\caption{By Lemma 2, receiving $t$ before $u$ is impossible.}\r
+\end{figure}\r
+\r
+\begin{lem} If two packets $t$ and $u$, with $i(t) \le i(u)$, are received without errors by a client $C$, then $t$ is in the path of $u$. \end{lem}\r
 \begin{proof}\r
-\textit{TODO}\r
-\end{proof}\r
+Assume that $t$ is not in the path of $u$. Take $u$ to be the packet of smallest index for which this occurs, and $t$ be the packet with largest index for this $u$. We will prove that an error occurs upon receipt of $u$.\r
+\r
+Let $R_1$ be the earliest member of the path of $t$ that is not in the path of $u$, and $q$ be its parent. $q$, the last common ancestor of $t$ and $u$, must exist, since all clients and the server were initialized with the same state. Let $S_1$ be the successor of $q$ that is in the path of $u$; we know $S_1 \neq R_1$. Let $R = (R_1, R_2, \dots, R_m = t)$ be the distinct portion of the path of $t$, and similarly let $S$ be the distinct portion of the path of $S_n = u$.\r
+\r
+Let $J = s(R_1)$, and $K = s(S_1)$. Because no client can send two messages with the same index, and $i(R_1) = i(S_1) = i(q) + 1$, we know that $J \neq K$.\r
+\r
+There are two cases:\r
+\r
+\begin{itemize}\r
+\item Case 1: $J$ did not send a message in $S$. Then $v_J(t) > v_J(q) = v_J(u)$.\r
+\begin{itemize}\r
+\item Case 1.1: $C$ will throw an error, because the latest index of $J$ changes in the opposite direction of the sequence number: $v_J(u) < v_J(t)$ but $i(u) > i(t)$.\r
+\r
+\r
+\r
+\end{itemize}\r
+\r
 \r
-\begin{defn}[State of Data Structure]\r
-Define in terms of playing all updates sequentially onto local data\r
-structure.\r
-\end{defn}\r
+\r
+\item Case 2: $J$ sent at least one message in $S$. Call the first one $p$. We know that $i(p) > i(S_1)$, since $J \neq K$. $R_1$ must be sent either before or after $p$.\r
+\begin{itemize}\r
+\item Case 2.1: Client $J$ sends $p$, and then $R_1$. When $p$ was sent, whether it was accepted or rejected, $i(J, p) \geq i(p)$. Since $i(p) > i(S_1)$, $i(J, p) > q$. So $i(q) < i(J, p)$, which would cause $J$ to fail to send $R_1$, a contradiction.\r
+\begin{itemize}\r
+\item Case 2.2.1: \r
+\r
+\r
+\r
+\end{itemize}\r
+\item Case 2.2: Client $J$ sends $R_1$, and then $p$. Let $X = (R_1, \dots )$ be the list of messages $J$ sends starting before $R_1$ and ending before $p$.\r
+\begin{itemize}\r
+\item Case 2.2.1: Some message in $X$ was accepted. In this case, before sending $p$, $J$'s value for its own latest index would be strictly greater than $v_J(q)$. ($J$ could not have sent a message with index less than $i(q)$ after receiving $q$). When preparing to send $p$, $J$ would have received its own latest index as at most $v_J(q)$. $J$ throws an error before sending $p$, because its own latest index decreases.\r
+\item Case 2.2.2: All messages in $X$ were rejected. Client $J$ will always add the latest rejected message to the rejected-message list in the next update; so for every $i$, $1 \leq i < |X|$, the $i$th element of $X$ will be recorded in the RML of all further elements of $X$; and every element of $X$ will be recorded in $RML(p)$. Since every rejected message in $RML(p)$ will be in $RML(C, u)$, and $u$ is the first message that $C$ sees which does not have $t$ in its path, $R_1$ will be recorded in $RML(C, p)$. When $C$ receives $u$, $C$ will throw an error from the match $(J, iq+1)$ in $RML(C, p)$.\r
+\end{itemize}\r
+\end{itemize}\r
+\end{itemize}\r
+\end{proof}\r
 \r
 \begin{theorem}\r
-Algorithm gives consistent view of data structure.\r
-\end{theorem}\r
+Suppose that there is a transitive closure set $\mathscr{S}$ of clients, at index $n$. Then there is some total message sequence $T$ of length $n$ such that every client $C$ in $\mathscr{S}$ sees a partial sequence $P_C$ consistent with $T$. \end{theorem}\r
+\r
 \begin{proof}\r
-\textit{TODO}\r
+The definition of consistency of $P_C$ with $T$ is that every message $p \in P_C$ with index $i(p) \le n$ is equal to the message in that slot in $T$. Let $C_1$ be some client in the transitive closure set, with partial message sequence $P_{C_1}$, and let $u$ be some message with $i(u) > i$ that $C_1$ shares with another client. Then let $T$ be the portion of the path of $u$ ending at index $i$ and $t$ be the message at that index. Clearly, by Lemma 1, $P_{C_1}$ is consistent with $T$, and furthermore. We will show that, for every other client $D$ with partial sequence $P_D$, $P_D$ has some message whose path includes $t$. Because $D$ is in the transitive closure, there is a sequence of edges from $C_1$ to $D$. Call this $\mathscr{C} = (C_1, C_2, ..., D)$. I will prove by induction that $D$ has a message whose path includes $t$.\r
+\r
+For the base case, $P_{C_1}$ includes $u$, whose path includes $t$. For the inductive step, suppose $P_{C_k}$ has an message $w$ with a path that includes $t$, and shares message $x$ with $P_{C_{k+1}}$ such that $i(x) > i$. If $i(w) = i(x)$, then $w = x$. If $i(w) < i(x)$, then, by Lemma 1, $w$ is in the path of $x$. If $i(w) > i(x)$, $x$ is in the path of $w$; note again that its index is greater than $i$. In any case, $t$ is in the path of $u_k+1$.\r
+\r
+Let $w$ the message of $D$ whose path includes $t$. By Lemma 1, every message in $P_D$ with index smaller than $i(w)$ is in the path of $w$. Since $t$ is in the path of $w$, every message in $P_D$ with smaller index than $i(t)$ is in $T$. Therefore, $P_D$ is consistent with $T$.\r
 \end{proof}\r
 \r
 \subsection{Future Work}\r
@@ -406,4 +759,3 @@ Algorithm gives consistent view of data structure.
 \r
 Idea is to separate subspace of entries...  Shared with other cloud...\r
 \end{document}\r
-\r