(* Simple protocol for querying a state *)
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)].

Lemma consume_coh d m : QCoh d -> soupCoh (consume_msg (dsoup d) m).