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          ******)
(************************************************************************)
(***********************************************************)
(* A rely-inductive predicate describing the message story *)
(***********************************************************)
Definition msg_story s req_num to data reqs resp :=
[/\ to \in qnodes,
core_state_to_data to (getLc' s to) data,
local_indicator data (getLc s) &
let: d := getSq s in
[\/ msg_just_sent d reqs resp req_num to,
msg_received d reqs resp req_num to |
msg_responded d reqs resp req_num to data]].

(* This lemma employs hooking -= it's better hold!.. :-s *)
Lemma msg_story_step' req_num data reqs resp to s s' :
this != to ->
msg_story s req_num to data reqs resp ->
network_step W to s s' ->
msg_story s' req_num to data reqs resp.