Section QueryHooked.
(* Constructing the composite world *)
Variables (lq : Label) (pc : protocol).
Variable Data : Type.
Variable qnodes : seq nat.
Variable serialize : Data -> seq nat.
Variable deserialize : seq nat -> Data.
Hypothesis ds_inverse : left_inverse serialize deserialize.
Definition pq := QueryProtocol qnodes serialize lq.
Variable core_state_to_data : nid -> heap -> Data -> Prop.
Hypothesis core_state_to_data_inj :
forall n h d d', core_state_to_data n h d -> core_state_to_data n h d' -> d = d'.
(* The query hook extracts certain data from the the core protocol *)
(* local state if it's present there. *)
Definition query_hook : hook_type :=
fun hc hq ms to =>
forall n rid d, ms = rid :: serialize d -> core_state_to_data n hc d.
Definition query_hookz := (1, (plab pc), (plab pq, tresp)) \\-> query_hook.
Definition W : world := ((plab pc \\-> pc) \+ (plab pq \\-> pq), query_hookz).
Hypothesis Lab_neq: lq != (plab pc).
(* Hypothesis Nodes_eq: forall d, nodes pc d =i qnodes. *)
rewrite /getProtocol/W/= findUnL; last by case/andP: W_valid.
by rewrite domPt inE eqxx findPt.
Qed.
(* TODO: this is a good candidate for a general lemma in the framework. *)
(***************************************************)
(*  Query-specific intermediate predicate          *)
(***************************************************)
(* 1. We've just sent our stuff. *)
Definition msg_just_sent d (reqs resp : seq (nid * nat)) req_num to :=
[/\ getLocal this d = qst :-> (reqs, resp),
no_msg_from_to' to this response_msg (dsoup d),
(to, req_num) \in reqs,
msg_spec' this to treq ([:: req_num]) (dsoup d) &
holds_res_perms d to (fun _ => false)].
(* 2. Our request is received but not yet responded. *)
Definition msg_received d (reqs resp : seq (nid * nat)) req_num to :=
[/\ getLocal this d = qst :-> (reqs, resp),
(to, req_num) \in reqs,
no_msg_from_to' this to request_msg (dsoup d),
no_msg_from_to' to this response_msg (dsoup d) &
holds_res_perms d to (fun rn => rn == req_num)].
(* 3. Our request is responded. *)
Definition msg_responded d (reqs resp : seq (nid * nat)) req_num to data :=
[/\ getLocal this d = qst :-> (reqs, resp),
(to, req_num) \in reqs,
no_msg_from_to' this to request_msg (dsoup d),
msg_spec' to this tresp (req_num :: serialize data) (dsoup d) &
holds_res_perms d to (fun _ => false)].
(* 4. Stability of the local state of a core protocol, to be proved separately *)
(* A local assertion ensuring stability of the core_state_to_data *)
Variable local_indicator : Data -> Pred heap.
Hypothesis core_state_stable_step : forall z s data s' n,
this != z -> network_step (plab pc \\-> pc, Unit) z s s' ->
n \in qnodes ->
local_indicator data (getLc s) ->
core_state_to_data n (getLc' s n) data  ->
core_state_to_data n (getLc' s' n) data.
(************************************************************************)
(******       Auxiliary lemmas for establishing stability          ******)
(************************************************************************)

Lemma recv_lq_case3 req_num reqs resp to s data
(N : this != to) (Qn : to \in qnodes)
(M : msg_responded (getSq s) reqs resp req_num to data)
(H : core_state_to_data to (getLc' s to) data)
(L : local_indicator data (getLc' s this))
i from msg (C : Coh W s) (C' : (coh pq) (getSq s))
(pf : to \in nodes pq (getSq s))
(rt : receive_trans (Protocols.coh pq)) :
rt \In rcv_trans pq -> tag msg = t_rcv rt ->
find i (dsoup (getSq s)) = Some (Msg msg from to true) ->
let: d := getStatelet (upd (plab pq)
(DStatelet (upd to (receive_step rt from msg C' pf) (dstate (getSq s)))
(consume_msg (dsoup (getSq s)) i)) s) lq in
msg_responded d reqs resp req_num to data.