Section  QueryProtocol.
(* Arbitrary data type *)
Variable Data : Type.
Variable nodes : seq nat.
(* Serialize/decerialize functions *)
Variable serialize : Data -> seq nat.
Variable deserialize : seq nat -> Data.
Hypothesis ds_inverse : left_inverse serialize deserialize.
(* Protocol state *)
Definition st := ptr_nat 1.
(* Pending requests (client-side): node, request id *)
(* Pending responses (server-side): node, response id *)
Definition reqs := seq (nid * nat)%type.
Definition resp := seq (nid * nat)%type.
Definition qstate := (reqs * resp)%type.
(* All responses and requests are unique per-node *)
Definition localCoh (n : nid) : Pred heap :=
[Pred h | exists (s : qstate), h = st :-> s /\ (uniq s.1 && uniq s.2)].
(* Tags *)
Definition treq : nat := 0.
Definition tresp : nat := 1.
Definition tags := [:: treq; tresp].
Definition cohMsg (ms: msg TaggedMessage) : Prop :=
let body := content ms in
(* If a message is a request, it carries a request number *)
if tag body == treq then exists req_num, tms_cont body = [:: req_num]
(* Otherwise it's a response and serialized data *)
else exists resp_num sdata, tms_cont body = resp_num :: sdata.
Definition soupCoh : Pred soup :=
[Pred s | valid s /\ forall m ms, find m s = Some ms -> cohMsg ms].
Definition qcoh d : Prop :=
let: dl := dstate d in
let: ds := dsoup d in
[/\ soupCoh ds, valid dl, dom dl =i nodes &
forall n, n \in dom dl -> localCoh n (getLocal n d)].
(****************************************************)
(********* Getter lemmas for local state ************)
(****************************************************)
Definition getSt n d (C : QCoh d) : qstate :=
match find st (getLocal n d) as f return _ = f -> _ with
Some v => fun epf => icast (sym_eq (cohSt C epf)) (dyn_val v)
| _ => fun epf => ([::], [::])
end (erefl _).

Lemma getStE n i j C C' (pf : n \in nodes) :
getLocal n j = getLocal n i ->
@getSt n j C' = @getSt n i C.