From mathcomp.ssreflect
Require Import ssreflect ssrbool ssrnat eqtype ssrfun seq path.
Require Import Eqdep.
From fcsl
Require Import axioms pred prelude ordtype finmap pcm unionmap heap.
From DiSeL
Require Import Freshness State EqTypeX Protocols Worlds NetworkSem Rely Actions.
From DiSeL
Require Import SeqLib QueryProtocol NewStatePredicates Actions.
From DiSeL
Require Import Injection Process Always HoareTriples InferenceRules While.

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 :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  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 => 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    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. *)

Lemma W_valid : valid W.
Proof.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
apply/andP; split=>/=; last by rewrite validPt.
(* Goal: forall (_ : @eq (prod (list (prod nid nat)) (list (prod nid nat))) (@pair (list (prod nid nat)) (list (prod nid nat)) rq rs) (@pair QueryProtocol.reqs QueryProtocol.resp x1 x2)) (_ : is_true (andb (@uniq (prod_eqType nat_eqType nat_eqType) x1) (@uniq (prod_eqType nat_eqType nat_eqType) x2))), is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
case: validUn=>//; rewrite ?validPt// =>l.
(* Goal: forall (coh_s : @Coherence.sort (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (getStatelet s lq)) (rt : @receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (pf : is_true (@in_mem nid z (@mem nid (ssrbool.predPredType nid) (nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq) (getStatelet s lq))))) (_ : @InMem (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) rt (@Mem (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (seq_PredType (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)))) (get_rt (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (_ : @eq nat (tag msg) (@t_rcv (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt)), and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end coh_s pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
rewrite !domPt !inE=>/eqP=>Z; subst l=>/eqP=>Z.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by subst lq; move/negbTE: Lab_neq; rewrite eqxx.
Qed.

Lemma W_complete : hook_complete W.
Proof.
(* Goal: or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move=>z lc ls t/=; rewrite domPt inE=>/eqP[]_<-<-_.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite !domUn !inE/= !domPt !inE !eqxx/= orbC.
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case/andP:W_valid=>->_.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite 3!andTb.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite inE.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by apply/orP; left.
Qed.

Lemma W_dom : dom W.1 =i [:: plab pc; lq].
Proof.
(* Goal: @eq_mem (Equality.sort (Ordered.eqType Label)) (@mem (Equality.sort (Ordered.eqType Label)) (seq_predType (Ordered.eqType Label)) (@UMC.dom Label protocol (union_mapUMC Label protocol) (@fst context hooks W))) (@mem (Equality.sort (Ordered.eqType Label)) (seq_predType (Ordered.eqType Label)) (@cons (Ordered.sort Label) (plab pc) (@cons (Ordered.sort Label) lq (@Datatypes.nil (Ordered.sort Label))))) *)
move=>z/=; rewrite domUn !inE/=; case/andP: W_valid=>->/=_. 
(* Goal: @eq bool (orb (@in_mem nat z (@mem nat (seq_predType (Ordered.eqType nat_ordType)) (@UMC.dom nat_ordType protocol (union_mapUMC Label protocol) (@um_pts Label protocol (plab pc) pc)))) (@in_mem nat z (@mem nat (seq_predType (Ordered.eqType nat_ordType)) (@UMC.dom nat_ordType protocol (union_mapUMC Label protocol) (@um_pts Label protocol lq pq))))) (orb (@eq_op nat_eqType z (plab pc)) (@eq_op nat_eqType z lq)) *)
rewrite !domPt !inE; rewrite -!(eq_sym z).
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /cond /= inE orbC.
(* Goal: @eq bool (orb (@eq_op (Ordered.eqType nat_ordType) lq z) (@eq_op (Ordered.eqType Label) z (plab pc))) (orb (@eq_op nat_eqType z (plab pc)) (@eq_op nat_eqType z lq)) *)
apply sym_eq.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by rewrite orbC eq_sym.
Qed.

Lemma eqW : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  W = (plab pc \\-> pc, Unit) \+ (plab pq \\-> pq, Unit) \+ (Unit, query_hookz).
Proof. by rewrite /PCM.join/=/W !unitL !unitR. Qed.

Lemma eqW' : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  W = (plab pc \\-> pc, Unit) \+ ((plab pq \\-> pq, Unit) \+ (Unit, query_hookz)).
Proof. by rewrite eqW joinA. Qed.

Lemma injW : injects (plab pc \\-> pc, Unit) W query_hookz.
Proof.
rewrite eqW; apply:injectL=>//; try by move=>????/=; rewrite dom0 inE.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by rewrite -eqW W_valid.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- move=>z lc ls t; rewrite domPt inE.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite /cond /= dom0.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- move=>z lc ls t; rewrite domPt inE.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite /cond /= dom0.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- move=>z lc ls t; rewrite domPt inE.
  case/eqP=>Z1 Z2 Z3 Z4; subst ls z lc t.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite !domUn !inE !domPt !inE !eqxx/=.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  case/andP:W_valid=>/=->_/=; rewrite orbC inE.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply/orP; left.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
move=>l; rewrite domPt inE=>/eqP=><-.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
move=>z lc ls t; rewrite domPt inE=>/eqP[]_ _<-_.  
apply/negbT; apply/eqP=>Z; subst lq; move/negbTE: Lab_neq.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by rewrite eqxx.
Qed.

Lemma labC : plab pc \in dom W.1.
Proof.
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case/andP: W_valid=>V1 V2.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by rewrite domUn !inE V1/= domPt inE eqxx.
Qed.

Lemma labQ : lq \in dom W.1.
Proof.
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case/andP: W_valid=>V1 V2.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite domUn !inE V1/= !domPt !inE /cond /= inE.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by apply/orP; right.
Qed.

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
Lemma injWQ : inj_ext injW = (lq \\-> pq, Unit).
Proof.
move: (W_valid)=>V; move: (cohK injW).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
rewrite {1}eqW/mkWorld/= -!joinA /PCM.join/= in V.
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case/andP: V=>/=V V'.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
rewrite {1}eqW/mkWorld/= -!joinA /PCM.join/=; case=>H K.
(* Goal: forall (_ : @eq (prod (list (prod nid nat)) (list (prod nid nat))) (@pair (list (prod nid nat)) (list (prod nid nat)) rq rs) (@pair QueryProtocol.reqs QueryProtocol.resp x1 x2)) (_ : is_true (andb (@uniq (prod_eqType nat_eqType nat_eqType) x1) (@uniq (prod_eqType nat_eqType nat_eqType) x2))), is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
case: (cancel V H)=>_; rewrite !unitR=>_{H}H1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
rewrite [inj_ext _]surjective_pairing -H1{H1}; congr (_, _).
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite !unitL joinC/=/query_hookz/= in V' K.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
rewrite -[_ \\-> _]unitR in V'.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
have Z:  (1, plab pc, (lq, tresp)) \\-> query_hook \+ Unit =
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
         (1, plab pc, (lq, tresp)) \\-> query_hook \+ (inj_ext injW).2
  by rewrite unitR.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by case: (cancel V' Z).
Qed.

Lemma prEqC : getProtocol W (plab pc) = pc.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getProtocol/W/= findUnL; last by case/andP: W_valid.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by rewrite domPt inE eqxx findPt.
Qed.

Lemma prEqQ : getProtocol W lq = pq.
Proof.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getProtocol/W/= findUnR; last by case/andP: W_valid.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by rewrite domPt inE eqxx findPt.
Qed.

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
Lemma prEqQ' : getProtocol (lq \\-> pq, Unit) lq = pq.
Proof. by rewrite /getProtocol findPt. Qed.

(* Finished constructing the composite world *)

Variable this : nid.
Hypothesis this_in_qnodes: this \in qnodes.

(* Now playing with the stability of the desired invariant *)

(* Core getters *)
Notation getSc s := (getStatelet s (plab pc)).
Notation getLc s := (getLocal this (getSc s)).
Notation getLc' s n := (getLocal n (getSc s)).

(* Query getters *)
Notation getSq s := (getStatelet s (plab pq)).
Notation getLq s := (getLocal this (getSq s)).

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Describing the response-permissions of our recipient *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
Definition holds_res_perms d n (pp : nat -> Prop) :=
  exists (reqs resp : seq (nid * nat)),
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    getLocal n d = qst :-> (reqs, resp) /\
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    forall rn, (this, rn) \in resp -> pp rn.

(* TODO: define the channel criterion *)
Definition request_msg (t: nat) (_ : seq nat) :=  t == treq.
Definition response_msg (t: nat) (_ : seq nat) := t == tresp.

(************************************************)
(*        Predicate for initial state           *)
(************************************************)

Definition query_init_state (to : nid) s :=
  [/\ to \in qnodes,
      holds_res_perms (getSq s) to (fun _ : nat => false),
      no_msg_from_to' this to request_msg (dsoup (getSq s)) &
      no_msg_from_to' to this response_msg (dsoup (getSq s))].    

(* This is the first serious one. *)
Lemma query_init_step' z to s s' :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  this != z -> query_init_state to s ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  network_step (lq \\-> pq, Unit) z s s' -> query_init_state to s'.
Proof.
(* Goal: forall (_ : @InMem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) rt (@Mem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) (seq_PredType (@receive_trans (Protocols.nodes pq) (Protocols.coh pq))) (rcv_trans pq))) (_ : @eq nat (tag msg) (@t_rcv (Protocols.nodes pq) (Protocols.coh pq) rt)) (_ : @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (dsoup (getStatelet s (plab pq)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage msg from to true))), msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
move=> N H S; case: (step_coh S)=>C1 _.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case: S; [by case=>_<- |
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  move=>l st H1 to'/= msg n H2 H3 C H4 H5 H6->{s'}|
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  move=>l rt H1 i from pf H3 C msg H2/=[H4]_->{s'}];
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
rewrite -(cohD C) domPt inE in H3; move/eqP: H3=>H3; subst l;
(* TODO: Get rid of irrelevant cases: by means of a tactic *)
rewrite /query_init_state/getStatelet !findU !eqxx (cohS C1)/=;
have Cq: coh pq (getStatelet s lq) by move: (coh_coh lq C1); rewrite /getProtocol findPt.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Send-transitions. *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case:H=>G1 G2 G3 G4.
(* Goal: or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
  move: st H1 H4 H5 H6; rewrite /get_st prEqQ'=>st H1 H4 H5 H6.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case B: (to == z); rewrite /holds_res_perms/getLocal findU B/=; last first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + split=>//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    move=>m t c; rewrite findUnR ?valid_fresh ?(cohVs Cq)//; case: ifP; last by move=>_/G3.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-{m}; rewrite findPt; case=>_ _ Z; subst z.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by move/negbTE: N; rewrite eqxx.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>m t c; rewrite findUnR ?valid_fresh ?(cohVs Cq)//; case: ifP; last by move=>_/G4.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-{m}; rewrite findPt; case=>_ _ Z; subst z.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by rewrite eqxx in B.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  move/eqP: B=>B; subst z; split=>//; first 1 last.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>m t c; rewrite findUnR ?valid_fresh ?(cohVs Cq)//; case: ifP; last by move=>_/G3.  
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-{m}; rewrite findPt; case=>_ _ Z; subst to.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by move/negbTE: N; rewrite eqxx.
  (* Now two interesting assertions. *)  
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>m t c; rewrite findUnR ?valid_fresh ?(cohVs Cq)//; case: ifP; last by move=>_/G4.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-{m}; rewrite findPt; case=>Z' Z2 Z; subst to' t c.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    (* Consider two possible send-transitions. *)
(* Goal: is_true (negb (response_msg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg)) *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap match (if @PCM.valid (@union_map_classPCM nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap)) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) then @Some Heap.heap n else @None Heap.heap) with | Some h => h | None => @PCM.unit heapPCM end (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end (@coh_s (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq s C) pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
    case: H1;[|case=>//]; move=>Z; subst st=>//. 
(* Goal: is_true (negb (response_msg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) (@QueryProtocol.qsend_resp Data qnodes serialize)) msg)) *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap match (if @PCM.valid (@union_map_classPCM nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap)) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) then @Some Heap.heap n else @None Heap.heap) with | Some h => h | None => @PCM.unit heapPCM end (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end (@coh_s (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq s C) pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
    case: (H4)=>_[C']/=[rid][d][_]; case: G2=>rq[rs][E]H.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by rewrite (getStK _ E)/==>/H.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap n (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap n (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end (@coh_s (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq s C) pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
  rewrite (cohVl Cq); case: G2=>rq[rs][E]H.  
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case: H1;[|case=>//]; move=>Z; subst st=>//; last first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + case: (H4)=>_[C']/=[rid][d][H']; subst msg.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
    rewrite (getStK _ E)/==>G.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap n (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap n (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end (@coh_s (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq s C) pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
    rewrite /=/QueryProtocol.send_step/=!(getStK _ E)/= G/= in H6; case: H6=>Z.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
    subst n; eexists rq, (seq.rem (to', rid) rs); split=>//.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by move=>rn; move/mem_rem; apply/H.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
  case: (H4)=>_[C']/==>Z.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap n (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end (@coh_s (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq s C) pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
  rewrite/QueryProtocol.send_req_prec (getStK _ E) in Z; subst msg. 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap n (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end (@coh_s (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq s C) pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
  rewrite /=/QueryProtocol.send_step/=!(getStK _ E)/= in H6; case: H6=>Z; subst n.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists ((to', fresh_id rq) :: rq), rs.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Receive-transitions *)
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case:H=>G1 G2 G3 G4.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: (coh_s _ _) rt pf H1 H2.
(* Goal: forall (coh_s : @Coherence.sort (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (getStatelet s lq)) (rt : @receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (pf : is_true (@in_mem nid z (@mem nid (ssrbool.predPredType nid) (nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq) (getStatelet s lq))))) (_ : @InMem (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) rt (@Mem (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (seq_PredType (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)))) (get_rt (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (_ : @eq nat (tag msg) (@t_rcv (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt)), and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end coh_s pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
rewrite /get_rt prEqQ'/==>Cq'; rewrite !(pf_irr Cq' Cq)=>{Cq'}.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move=>rt pf H1 H2.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case B: (to == z); rewrite /holds_res_perms/getLocal findU B/=; last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by split=>//; apply: no_msg_from_to_consume'=>//; rewrite ?(cohVs Cq).
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (@ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap match (if @PCM.valid (@union_map_classPCM nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap)) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) then @Some Heap.heap (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end Cq pf) else @None Heap.heap) with | Some h => h | None => @PCM.unit heapPCM end (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false)))) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
rewrite !(cohVl Cq); move/eqP:B=>B; subst z. 
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (@ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end Cq pf) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false)))) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
split=>//; try by apply: no_msg_from_to_consume'=>//; rewrite ?(cohVs Cq).
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case: G2=>rq[rs][E]H.
case: H1;[|case=>//]; move=>Z; subst rt=>//=; simpl in H2;
rewrite /QueryProtocol.receive_step (getStK _ E)/=; last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case: ifP=>_; last by eexists _, _.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists (seq.rem (from, head 0 msg) rq), rs. 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case: ifP=>_; last by eexists _, _.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
exists rq, ((from, head 0 msg) :: rs); split=>//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
move=>rn; rewrite inE; case/orP; last by apply: H.
(* Goal: forall _ : is_true (@eq_op (prod_eqType nat_eqType nat_eqType) (@pair nid nat this rn) (@pair nat nat from (@head nat O (tms_cont msg)))), is_true false *)
case/eqP=>Z1 Z2; subst rn from.
(* Goal: is_true false *)
case: msg H2 H4=>t c/=Z H4; subst t.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by move: (G3 _ _ _ H4).
Qed.

Lemma query_init_rely' to s s' :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  query_init_state to s ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  network_rely (lq \\-> pq, Unit) this s s' -> query_init_state to s'.
Proof.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
move=>H1 [n]H2; elim: n s H2 H1=>/=[s | n Hi s]; first by case=>Z _; subst s'.
case=>z[s1][N]H1 H2 H3; apply: (Hi s1 H2).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by apply: (query_init_step' _ _ _ _ N H3 H1).
Qed.

(* TODO: this is a good candidate for a general lemma in the
framework. *)

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Proving a large-footprint predicate out of a small-footprint
predicate, spanning only the query world. *)
Lemma query_init_rely to s s2 :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  query_init_state to s ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  network_rely W this s s2 -> query_init_state to s2.
Proof.
(* Goal: forall (_ : @InMem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) rt (@Mem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) (seq_PredType (@receive_trans (Protocols.nodes pq) (Protocols.coh pq))) (rcv_trans pq))) (_ : @eq nat (tag msg) (@t_rcv (Protocols.nodes pq) (Protocols.coh pq) rt)) (_ : @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (dsoup (getStatelet s (plab pq)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage msg from to true))), msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
move=>Q R; case:(rely_coh R)=>CD CD'.
(* Goal: query_init_state to s2 *)
rewrite eqW in CD; move: (coh_hooks CD)=>{CD}CD.
(* Goal: query_init_state to s2 *)
rewrite eqW in CD'; move: (coh_hooks CD')=>{CD'}CD'.
(* Goal: query_init_state to s2 *)
case: (coh_split CD _ _); try apply: hook_complete0.
(* Goal: forall (x : state) (_ : @ex state (fun s2 : state => and3 (@InMem state x (@Mem state (PredPredType state) (Coh (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (@union_map_classPCM (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type (union_mapUMC (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type))) (@um_pts Label protocol (plab pc) pc) (@PCM.unit (@union_map_classPCM (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type (union_mapUMC (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type))))))) (@InMem state s2 (@Mem state (PredPredType state) (Coh (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (@union_map_classPCM (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type (union_mapUMC (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type))) (@um_pts Label protocol (plab pq) pq) (@PCM.unit (@union_map_classPCM (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type (union_mapUMC (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type))))))) (@eq state s (@PCM.join (union_mapPCM Label dstatelet) x s2)))), query_init_state to s2 *)
move=>i1[j1][C1 D1 Z]; subst s.
(* Goal: query_init_state to s2 *)
case: (coh_split CD' _ _); try apply: hook_complete0.
(* Goal: forall (x : state) (_ : @ex state (fun s3 : state => and3 (@InMem state x (@Mem state (PredPredType state) (Coh (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (@union_map_classPCM (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type (union_mapUMC (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type))) (@um_pts Label protocol (plab pc) pc) (@PCM.unit (@union_map_classPCM (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type (union_mapUMC (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type))))))) (@InMem state s3 (@Mem state (PredPredType state) (Coh (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (@union_map_classPCM (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type (union_mapUMC (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type))) (@um_pts Label protocol (plab pq) pq) (@PCM.unit (@union_map_classPCM (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type (union_mapUMC (prod_ordType (prod_ordType nat_ordType Label) (prod_ordType Label nat_ordType)) hook_type))))))) (@eq state s2 (@PCM.join (union_mapPCM Label dstatelet) x s3)))), query_init_state to s2 *)
move=>i2[j2][C2 D2 Z]; subst s2.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /query_init_state in Q *.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite (locProjR CD _ D1) in Q; last by rewrite domPt inE andbC eqxx.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite (locProjR CD' _ D2); last by rewrite domPt inE andbC eqxx.
(* Goal: is_true (@PCM.valid (@union_map_classPCM nat_ordType protocol (union_mapUMC Label protocol)) (@PCM.join (@union_map_classPCM nat_ordType protocol (union_mapUMC Label protocol)) (@um_pts Label protocol lq pq) (@um_pts Label protocol (plab pc) pc))) *)
case: (rely_split injW C1 C2 R)=>Rc Rq; rewrite injWQ in Rq.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by apply: (query_init_rely' _ _ _ Q Rq).
Qed.

(***************************************************)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(*  Query-specific intermediate predicate          *)
(***************************************************)

(* 1. We've just sent our stuff. *)
Definition msg_just_sent d (reqs resp : seq (nid * nat)) req_num to :=
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  [/\ 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 :=
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  [/\ 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 :=
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  [/\ 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 *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
Variable local_indicator : Data -> Pred heap.

Hypothesis core_state_stable_step : forall z s data s' n,
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  this != z -> network_step (plab pc \\-> pc, Unit) z s s' ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  n \in qnodes ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  local_indicator data (getLc s) ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  core_state_to_data n (getLc' s n) data  -> 
  core_state_to_data n (getLc' s' n) data.

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
Lemma prEqC' : (getProtocol (plab pc \\-> pc, Unit) (plab pc)) = pc.
Proof. by rewrite /getProtocol findPt/=. Qed.
  
(* Showing that the core assertion is stable *)
Lemma core_state_stable_step_W s data s' z :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  this != z ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  network_step W z s s' ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  z \in qnodes ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  local_indicator data (getLc s) ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  core_state_to_data z (getLc' s z) data -> 
  core_state_to_data z (getLc' s' z) data.
Proof.
move=>N H2 G L H1; move:(step_coh H2)=>[C1 C2].
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite eqW' in C1 C2.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: (projectSE C1)(projectSE C2)=>E1 E2.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
set s1 := projectS (plab pc \\-> pc, Unit) s in E1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
set s2 := projectS ((plab pq \\-> pq, Unit) \+ (Unit, query_hookz)) s in E1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
set s1' := projectS (plab pc \\-> pc, Unit) s' in E2.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
set s2' := projectS ((plab pq \\-> pq, Unit) \+ (Unit, query_hookz)) s' in E2.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: (C1) (C2) =>C1' C2'.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite E1 E2 in H2 C1' C2'.
have [X X'] : (forall z, getLc' s z  = getLc' s1 z) /\
              (forall z, getLc' s' z = getLc' s1' z).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by split; move=>z'; rewrite /getStatelet find_umfilt domPt inE eqxx.
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case: (sem_split injW _ _ H2).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- apply: (@projectS_cohL (plab pc \\-> pc, Unit)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
                         ((plab pq \\-> pq, Unit) \+ (Unit, query_hookz)))=>//.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by move=>????; rewrite dom0.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- suff H : hook_complete (plab pc \\-> pc, Unit).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  apply: (@projectS_cohL _ ((plab pq \\-> pq, Unit)\+(Unit, query_hookz)))=>//.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by move=>????; rewrite dom0.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case=>H _; rewrite X'; rewrite !X in L H1.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: (core_state_stable_step _ _ _ _ _ N H _ L H1).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
by case=>_ E; rewrite X'; rewrite !X in L H1; rewrite -E.
Qed.

Lemma core_state_stable s data s' z :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  network_rely W this s s' ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  z \in qnodes ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  local_indicator data (getLc s) ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  core_state_to_data z (getLc' s z) data -> 
  core_state_to_data z (getLc' s' z) data.
Proof.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
move=> R Z L. move: (L); rewrite -(@rely_loc' _ _ (plab pc) s s' R)=>L'.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: R Z L.
case B: (this == z); [move/eqP: B=>B|move/negbT: B=>B].
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by subst z=>R; rewrite (@rely_loc' _ _ (plab pc) s s' R).
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
move=>[n]H2 H1; elim: n s H2=>/=[s | n Hi s]; first by case=>Z _; subst s'.
case=>y[s1][N]G1 G2 G3 G4; apply: (Hi s1 G2).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by rewrite /getLocal -(step_is_local (plab pc) G1 N). 
case B' : (z == y); [move/eqP: B'=>B' | move/negbT: B'=>B'].
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by subst y; apply: (core_state_stable_step_W _ _ _ _ B G1 _ G3).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
by rewrite /getLocal -(step_is_local (plab pc) G1 B').
Qed.

(************************************************************************)
(******       Auxiliary lemmas for establishing stability          ******)
(************************************************************************)

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
Lemma cohQ s : Coh W s -> (QueryProtocol.QCoh qnodes) (getSq s).
Proof. by move/(coh_coh lq); rewrite prEqQ. Qed.

Lemma send_lq_case1 req_num reqs resp to s
  (N : this != to) (Qn : to \in qnodes) 
  (M : msg_just_sent (getSq s) reqs resp req_num to)
  to' msg (n : heap) (C : Coh W s) (st : send_trans (Protocols.coh pq))
  (H1 : st \In snd_trans pq)
  (H2 : to \in qnodes)
  (H4 : send_safe st to to' (getSq s) msg) : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  all_hooks_fire query_hookz (plab pq) (t_snd st) s to msg to' -> Some n = send_step H4 ->
  let: d := getStatelet (upd (plab pq) 
              (DStatelet (upd to n (dstate (getSq s)))
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
               (dsoup (getSq s) \+ fresh (dsoup (getSq s)) \\->
                      Msg (TMsg (t_snd st) msg) to to' true)) s) lq in
  msg_just_sent d reqs resp req_num to.
Proof.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
move=>H5 H6; case: M=>G1 G2 G3 G4[rq][rs][E]Np; split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU  eqxx(cohS C)/==>z t c.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: forall _ : @eq (option (State.msg TaggedMessage)) (if @in_mem (Ordered.sort mid) z (@mem (Equality.sort (Ordered.eqType mid)) (seq_predType (Ordered.eqType mid)) (@UMC.dom mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)))) then @UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) z (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)) else @UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) z (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg t c) this to true)), is_true (negb (request_msg t c)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq)) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) to (fun _ : nat => is_true false) *)
  case: ifP; [|by move=>_; apply: G2].
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite domPt inE=>/eqP<-; rewrite findPt; case=>???; subst t c to'.
  case: H1;[|case=>//]; move=>Z; subst st=>//; simpl in H5, H6;
  rewrite/QueryProtocol.send_step (getStK _ E)/= in H6; case: H6=>H6/=; subst n.                                  
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case:H4=>_[C'][rid][_][_]; rewrite (getStK _ E); move/Np. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU  eqxx(cohS C)/=.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case:G4; case=>i[[c']Q1 Q3] Q2; split; last first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>j c; rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    case:ifP; last by move=>_; apply Q2. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-; rewrite findPt.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by case=>???; subst to; rewrite eqxx in N.
(* Goal: @ex (Ordered.sort mid) (@unique (Ordered.sort mid) (fun i : Ordered.sort mid => @ex (list nat) (fun c : list nat => @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true))))) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) to (fun _ : nat => is_true false) *)
  exists i; split=>[|j[c1]];rewrite findUnL ?(valid_fresh) ?(cohVs (cohQ s C))//.   
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by exists c'; rewrite (find_some Q1). 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case: ifP=>_; first by move=> T; apply: Q3; exists c1. 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case/findPt_inv=>_[]_ _?; subst to; rewrite eqxx in N. 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).  
case: H1;[|case=>//]; move=>Z; subst st=>//; simpl in H5, H6;
rewrite/QueryProtocol.send_step (getStK _ E)/= in H6; case: H6=>H6; subst n.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by exists ((to', fresh_id rq) :: rq), rs.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case: ifP=>_; last by exists rq, rs.                 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by exists rq, (seq.rem (to', head 0 msg) rs); split=>//rn/mem_rem/Np.
Qed.

Lemma send_lq_case3 req_num data reqs resp to s
  (N : this != to) (Qn : to \in qnodes) (H : core_state_to_data to (getLc' s to) data)
  (L : local_indicator data (getLc' s this))
  (M : msg_responded (getSq s) reqs resp req_num to data)
  to' msg (n : heap) (C : Coh W s) (st : send_trans (Protocols.coh pq))
  (H1 : st \In snd_trans pq)
  (H2 : to \in qnodes)
  (H4 : send_safe st to to' (getSq s) msg) : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  all_hooks_fire query_hookz (plab pq) (t_snd st) s to msg to' -> Some n = send_step H4 ->
  let: d := getStatelet (upd (plab pq) 
              (DStatelet (upd to n (dstate (getSq s)))
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
               (dsoup (getSq s) \+ fresh (dsoup (getSq s)) \\->
                      Msg (TMsg (t_snd st) msg) to to' true)) s) lq in
  msg_responded d reqs resp req_num to data.  
Proof.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move=>H5 H6.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
case: M=>G1 G2 G3 G4[rq][rs][E]Np; split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU  eqxx(cohS C)/==>z t c.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: forall _ : @eq (option (State.msg TaggedMessage)) (if @in_mem (Ordered.sort mid) z (@mem (Equality.sort (Ordered.eqType mid)) (seq_predType (Ordered.eqType mid)) (@UMC.dom mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)))) then @UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) z (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)) else @UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) z (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg t c) this to true)), is_true (negb (request_msg t c)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq)) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) to (fun _ : nat => is_true false) *)
  case: ifP; [|by move=>_; apply: G3].
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite domPt inE=>/eqP<-; rewrite findPt; case=>????; subst t c to to'.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite eqxx in N.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU  eqxx(cohS C)/=.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case:G4; case=>i[[c']Q1 Q3] Q2; split; last first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>j c; rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    case:ifP; last by move=>_; apply Q2. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-; rewrite findPt.
(* Goal: forall _ : @eq (option (State.msg TaggedMessage)) (if @pred_of_simpl (Ordered.sort mid) (@UMC.cond mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage))) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) then @Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true) else @None (State.msg TaggedMessage)) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true)), is_true (@eq_op (seq_eqType nat_eqType) c (@cons nat req_num (serialize data))) *)
(* Goal: @ex (Ordered.sort mid) (@unique (Ordered.sort mid) (fun i : Ordered.sort mid => @ex (list nat) (fun c : list nat => @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true))))) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) to (fun _ : nat => is_true false) *)
    case=>???; subst to' c.
    case: H1;[|case=>//]; move=>Z; subst st=>//; simpl in H5, H6;
    rewrite/QueryProtocol.send_step (getStK _ E)/= in H6; case: H6=>H6/=; subst n.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    by case:H4=>_[C']; rewrite (getStK _ E); case=>rid[d][->]/=/Np. 
(* Goal: @ex (Ordered.sort mid) (@unique (Ordered.sort mid) (fun i : Ordered.sort mid => @ex (list nat) (fun c : list nat => @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true))))) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) to (fun _ : nat => is_true false) *)
  exists i; split=>[|j[c1]];rewrite findUnL ?(valid_fresh) ?(cohVs (cohQ s C))//.   
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by exists c'; rewrite (find_some Q1). 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case: ifP=>_; first by move=> T; apply: Q3; exists c1. 
(* Goal: forall _ : @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) j (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c1) to this true)), @eq (Ordered.sort mid) i j *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) to (fun _ : nat => is_true false) *)
  case/findPt_inv=>_[]???; subst to'.
  case: H1;[|case=>//]; move=>Z; subst st=>//; simpl in H5, H6;
  rewrite/QueryProtocol.send_step (getStK _ E)/= in H6; case: H6=>H6/=; subst n.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case:H4=>_[C']; rewrite (getStK _ E); case=>rid[d][_]/=/Np. 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).  
case: H1;[|case=>//]; move=>Z; subst st=>//; simpl in H5, H6;
rewrite/QueryProtocol.send_step (getStK _ E)/= in H6; case: H6=>H6; subst n.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by exists ((to', fresh_id rq) :: rq), rs.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case: ifP=>_; last by exists rq, rs.                 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by exists rq, (seq.rem (to', head 0 msg) rs); split=>//rn/mem_rem/Np.
Qed.

Lemma send_lq_all_cases req_num data reqs resp to s
  (N : this != to) (Qn : to \in qnodes) (H : core_state_to_data to (getLc' s to) data)
  (L : local_indicator data (getLc' s this))
  (M : [\/ msg_just_sent (getSq s) reqs resp req_num to, msg_received (getSq s) reqs resp req_num to
        | msg_responded (getSq s) reqs resp req_num to data])
  to' msg (n : heap) (C : Coh W s) (st : send_trans (Protocols.coh (getProtocol W (plab pq))))
  (H1 : st \In get_st W (plab pq))
  (H2 : to \in nodes (getProtocol W (plab pq)) (getSq s))
  (H4 : send_safe st to to' (getSq s) msg) : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  all_hooks_fire query_hookz (plab pq) (t_snd st) s to msg to' -> Some n = send_step H4 ->
  let: d := getStatelet (upd (plab pq) 
              (DStatelet (upd to n (dstate (getSq s)))
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
               (dsoup (getSq s) \+ fresh (dsoup (getSq s)) \\->
                      Msg (TMsg (t_snd st) msg) to to' true)) s) lq 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].  
Proof.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move=>H5 H6.
(* Goal: or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: st H1 H4 H5 H6; rewrite /get_st prEqQ=>st H1 H4 H5 H6.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case: M; last 1 first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ (* already responded to our request, should be boring *)
(* Goal: forall _ : msg_responded (getStatelet s (plab pq)) reqs resp req_num to data, or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
(* Goal: forall _ : msg_just_sent (getStatelet s (plab pq)) reqs resp req_num to, or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
(* Goal: forall _ : msg_received (getStatelet s (plab pq)) reqs resp req_num to, or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
  constructor 3.
  by apply: (send_lq_case3 req_num data  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ H4). 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ (* just sent the request *)
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by constructor 1; apply: (send_lq_case1 req_num _ _ _ _ _ _ _ _ _ _ _ _ _ _ H4). 

Ltac kill_g3 s C G3 to N :=
  rewrite /getStatelet findU  eqxx(cohS C)/==>z t c;
  rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//;
  case: ifP; [|by move=>_; apply: G3]; 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite domPt inE=>/eqP<-; rewrite findPt;
  by case=>_ _ Z _; subst to; rewrite eqxx in N.

Ltac kill_g4 s C G4 to' t B:=
  rewrite /getStatelet findU  eqxx(cohS C)/==>z t c;
  rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//;
  case: ifP; [|by move=>_; apply: G4]; 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite domPt inE=>/eqP<-; rewrite findPt;
  by case=>??; try move=>?; try subst t; try subst to'; try rewrite ?eqxx in B.

(* now he can send us the message, this is the crucial step. *)
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case=>G1 G2 G3 G4 [rq][rs][E]Np.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case B : (to' == this); [move/eqP:B=>B; subst to'|]; last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- constructor 2. (* boring case : sending to someone else*)
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
  split=>//.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + kill_g3 s C G3 to N.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + kill_g4 s C G4 to' t B.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).  
  case: H1;[|case=>//]; move=>Z; subst st=>//; simpl in H5, H6;
  rewrite/QueryProtocol.send_step (getStK _ E)/= in H6; case: H6=>H6; subst n.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  - by exists ((to', fresh_id rq) :: rq), rs. 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case:ifP=>_; last by exists rq, rs.   
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists rq, (seq.rem (to', head 0 msg) rs); split=>//rn/mem_rem/Np.
(* Actually sending to us. *)  
case: H1;[|case=>//]; move=>Z; subst st=>//; simpl in H5, H6;
rewrite/QueryProtocol.send_step (getStK _ E)/= in H6; case: H6=>H6; subst n.                                  
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- constructor 2; split=>//. (* sending request (not response) -- this is boring *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + kill_g3 s C G3 to N.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + kill_g4 s C G4 to' t B.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists ((this, fresh_id rq) :: rq), rs.    
(* Sending response to us!!! *)                                          
(* Goal: or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat this (@head nat O msg)) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rs) then @pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O msg)) rs) else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) (@QueryProtocol.qsend_resp Data qnodes serialize)) msg) to this true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat this (@head nat O msg)) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rs) then @pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O msg)) rs) else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) (@QueryProtocol.qsend_resp Data qnodes serialize)) msg) to this true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat this (@head nat O msg)) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rs) then @pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O msg)) rs) else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) (@QueryProtocol.qsend_resp Data qnodes serialize)) msg) to this true)))) s) lq) reqs resp req_num to data) *)
case: (H4)=>_[C']/=[rid][d][Zm]Tr; subst msg.
rewrite  (getStK _ E)/= in Tr.
(* Goal: forall _ : msg_responded (getStatelet s (plab pq)) reqs resp req_num to data, or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
(* Goal: forall _ : msg_just_sent (getStatelet s (plab pq)) reqs resp req_num to, or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
(* Goal: forall _ : msg_received (getStatelet s (plab pq)) reqs resp req_num to, or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
rewrite Tr; constructor 3.
(* Now exploit the hook! *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
move: (H5 1 (plab pc) query_hook); rewrite findPt -!(cohD C).
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move/(_ (erefl _) labC labQ to rid d (erefl _))=>D.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize d)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize d))) to this true)))) s) lq) reqs resp req_num to data *)
move: (core_state_to_data_inj _ _ _ _ D H)=>Z; subst d.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
split=>//; first 3 last.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this rid) rs))) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) to (fun _ : nat => is_true false) *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  exists (rq), (seq.rem (this, rid) rs).
(* Goal: and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this rid) rs))) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true))))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this rid) rs)))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this rid) rs)))), is_true false) *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  rewrite /getLocal findU eqxx/= (cohVl C'); split=>// rn R.
(* Goal: is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  move/Np/eqP: (mem_rem R)=>Zr; subst rn.
(* Goal: is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  move/Np:Tr=>/eqP=>Zr; subst rid.
(* Goal: forall (_ : @eq (prod (list (prod nid nat)) (list (prod nid nat))) (@pair (list (prod nid nat)) (list (prod nid nat)) rq rs) (@pair QueryProtocol.reqs QueryProtocol.resp x1 x2)) (_ : is_true (andb (@uniq (prod_eqType nat_eqType nat_eqType) x1) (@uniq (prod_eqType nat_eqType nat_eqType) x2))), is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  case: (C')=>_ _ _/(_ to); rewrite E (cohDom C')=>/(_ Qn). 
(* Goal: forall (_ : @eq (prod (list (prod nid nat)) (list (prod nid nat))) (@pair (list (prod nid nat)) (list (prod nid nat)) rq rs) (@pair QueryProtocol.reqs QueryProtocol.resp x1 x2)) (_ : is_true (andb (@uniq (prod_eqType nat_eqType nat_eqType) x1) (@uniq (prod_eqType nat_eqType nat_eqType) x2))), is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  case=>[[x1 x2]][]/(hcancelPtV _); rewrite validPt/==>/(_ is_true_true).
(* Goal: forall (_ : @eq (prod (list (prod nid nat)) (list (prod nid nat))) (@pair (list (prod nid nat)) (list (prod nid nat)) rq rs) (@pair QueryProtocol.reqs QueryProtocol.resp x1 x2)) (_ : is_true (andb (@uniq (prod_eqType nat_eqType nat_eqType) x1) (@uniq (prod_eqType nat_eqType nat_eqType) x2))), is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  case=>Z1 Z2; subst x1 x2=>/andP[_]G.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite (rem_filter (this, req_num) G) mem_filter/= eqxx/= in R.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ by rewrite /getStatelet findU eqxx(cohS C)/getLocal findU (negbTE N). 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ rewrite /getStatelet findU eqxx (cohS C)/==>z t c.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite findUnR ?(valid_fresh) ?(cohVs C')//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case: ifP=>[|_]; last by apply: G3.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by rewrite domPt inE=>/eqP<-{z}; rewrite findPt; case=><-.
(* Here's the big hooking moment *)  
split=>[|i m]; 
  rewrite /getStatelet findU eqxx/= (cohS C)/=; last first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ rewrite findUnR ?(valid_fresh) ?(cohVs C')//; case: ifP=>[|_]; last by move/G4. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite domPt inE=>/eqP<-; rewrite findPt; case=><-.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by move/Np/eqP: Tr=>->; rewrite eqxx.
(* Goal: @ex nat (@unique nat (fun i : nat => @ex (list nat) (fun c : list nat => @eq (option (msg TaggedMessage)) (@UMC.find mid (msg TaggedMessage) (union_mapUMC mid (msg TaggedMessage)) i (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) (@Some (msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true))))) *)
exists (fresh (dsoup (getStatelet s lq))); split.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ exists (rid :: serialize data).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite findUnR ?(valid_fresh)?(cohVs C')// domPt inE eqxx findPt.
(* Goal: forall (x' : nat) (_ : @ex (list nat) (fun c : list nat => @eq (option (msg TaggedMessage)) (@UMC.find mid (msg TaggedMessage) (union_mapUMC mid (msg TaggedMessage)) x' (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) (@Some (msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true)))), @eq nat (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) x' *)
move=>i[c]; rewrite findUnR ?(valid_fresh)?(cohVs C')//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case: ifP=>[|_]; last by move/G4. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
by rewrite domPt inE=>/eqP<-; rewrite findPt. 
Qed.

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(*  A lemma covering send-cases in the lc-part of the world  *)
Lemma send_lc_all_cases req_num data reqs resp to s
  (N : this != to) (Qn : to \in qnodes) (H : core_state_to_data to (getLc' s to) data)
  (L : local_indicator data (getLc' s this))
  (M : [\/ msg_just_sent (getSq s) reqs resp req_num to, msg_received (getSq s) reqs resp req_num to
        | msg_responded (getSq s) reqs resp req_num to data])
  to' msg (n : heap) (C : Coh W s) (st : send_trans (Protocols.coh (getProtocol W (plab pc))))
  (H1 : st \In get_st W (plab pc))
  (H2 : to \in nodes (getProtocol W (plab pc)) (getSq s))
  (H4 : send_safe st to to' (getSq s) msg) : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  all_hooks_fire query_hookz (plab pc) (t_snd st) s to msg to' -> Some n = send_step H4 ->
  let: d := getStatelet (upd (plab pc) 
              (DStatelet (upd to n (dstate (getSq s)))
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
               (dsoup (getSq s) \+ fresh (dsoup (getSq s)) \\->
                      Msg (TMsg (t_snd st) msg) to to' true)) s) lq 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].  
Proof.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move=>H5 H6.
(* Goal: or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: st H1 H4 H5 H6; rewrite /get_st prEqC=>st H1 H4 H5 H6.
by case: M; [constructor 1|constructor 2|constructor 3];
   rewrite /getStatelet findU (negbTE Lab_neq)/=. 
Qed.

Lemma recv_lq_case1 req_num reqs resp to s
  (N : this != to) (Qn : to \in qnodes)
  (M : msg_just_sent (getSq s) reqs resp req_num to)
  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)) : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rt \In rcv_trans pq -> tag msg = t_rcv rt ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  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_just_sent d reqs resp req_num to \/
  msg_received d reqs resp req_num to. 
Proof.
(* Goal: forall (_ : @InMem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) rt (@Mem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) (seq_PredType (@receive_trans (Protocols.nodes pq) (Protocols.coh pq))) (rcv_trans pq))) (_ : @eq nat (tag msg) (@t_rcv (Protocols.nodes pq) (Protocols.coh pq) rt)) (_ : @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (dsoup (getStatelet s (plab pq)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage msg from to true))), msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
move=>H1 H2 H4; case: M=>G1 G2 G3 G4[rq][rs][Tr]Np.
case X: (this == from); [move/eqP:X=>X; subst from|constructor 1];
last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- split=>//.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by apply: no_msg_from_to_consume'=>//; rewrite (cohVs C').
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
    case: msg H2 H4=>t c H2 H4.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by apply: (msg_spec_consumeE (cohVs C') H4 G4); rewrite (negbT X).   
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).  
  case: H1;[|case=>//]; move=>Z; subst rt=>//=; simpl in H2, H4;
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite/QueryProtocol.receive_step (getStK _ Tr)/=.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + case:ifP=>_; last by exists rq, rs. 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nid nat)) rq (@cons (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) rs))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    exists rq, ((from, head 0 msg) :: rs); split=>//rn.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by rewrite inE; case/orP; [case/eqP=>Z; subst; rewrite eqxx in X|move/Np].
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case:ifP=>_; last by exists rq, rs. 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists (seq.rem (from, head 0 msg) rq), rs. 
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case: msg H2 H4=>t c H2 H4.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case: H1;[|case=>//]; move=>Z; subst rt=>//=; simpl in H2, H4; subst t; last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- constructor 1; split=>//.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by apply: no_msg_from_to_consume'=>//; rewrite (cohVs C').
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    by apply: (msg_spec_consumeE (cohVs C') H4 G4)=>/=; rewrite -(orbC true)/= orbC.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).  
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite/QueryProtocol.receive_step (getStK _ Tr)/=.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case:ifP=>_; last by exists rq, rs. 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists (seq.rem (this, head 0 c) rq), rs.  
(* Finally, the only interesting case here *)
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
constructor 2; split=>//.  
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *.     
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: (no_msg_spec_consume (cohVs C') H4 G4).
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
+ rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: no_msg_from_to_consume'=>//; rewrite (cohVs C').
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).  
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite/QueryProtocol.receive_step (getStK _ Tr)/=.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case:ifP=>X; last by move/negbT/negbNE/Np: X.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nid nat)) rq (@cons (prod nid nat) (@pair nid nat this (@head nat O c)) rs))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true (@eq_op nat_eqType rn req_num)))) *)
exists rq, ((this, head 0 c) :: rs); split=>//rn.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite inE=>/orP[]; last by move/Np.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
by case/eqP=>Z; subst rn; case:G4=>_/(_ _ _ H4)/eqP->.
Qed.

Lemma recv_lq_case2 req_num reqs resp to s
  (N : this != to) (Qn : to \in qnodes)
  (M : msg_received (getSq s) reqs resp req_num to)
  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)) : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rt \In rcv_trans pq -> tag msg = t_rcv rt ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  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_received d reqs resp req_num to.  
Proof.
(* Goal: forall (_ : @InMem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) rt (@Mem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) (seq_PredType (@receive_trans (Protocols.nodes pq) (Protocols.coh pq))) (rcv_trans pq))) (_ : @eq nat (tag msg) (@t_rcv (Protocols.nodes pq) (Protocols.coh pq) rt)) (_ : @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (dsoup (getStatelet s (plab pq)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage msg from to true))), msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
move=>H1 H2 H4; case: M=>G1 G2 G3 G4[rq][rs][Tr]Np.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: no_msg_from_to_consume'=>//; rewrite (cohVs C').
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU eqxx(cohS C)/=.  
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: no_msg_from_to_consume'=>//; rewrite (cohVs C').
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).  
case: H1;[|case=>//]; move=>Z; subst rt=>//=; simpl in H2, H4;
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite/QueryProtocol.receive_step (getStK _ Tr)/=.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case:ifP=>_; last by exists rq, rs. 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nid nat)) rq (@cons (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) rs))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  exists rq, ((from, head 0 msg) :: rs); split=>//rn.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case X: (this == from); last first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by rewrite inE; case/orP; [case/eqP=>Z; subst; rewrite eqxx in X|move/Np].
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  move/eqP:X=>X; subst from.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case: msg H2 H4=>t c/= H2 H4; move: (G3 _ _ _ H4); subst t.  
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case:ifP=>_; last by exists rq, rs. 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by exists (seq.rem (from, head 0 msg) rq), rs. 
Qed.

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)) : 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rt \In rcv_trans pq -> tag msg = t_rcv rt ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  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.  
Proof.
(* Goal: forall (_ : @InMem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) rt (@Mem (@receive_trans (Protocols.nodes pq) (Protocols.coh pq)) (seq_PredType (@receive_trans (Protocols.nodes pq) (Protocols.coh pq))) (rcv_trans pq))) (_ : @eq nat (tag msg) (@t_rcv (Protocols.nodes pq) (Protocols.coh pq) rt)) (_ : @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (dsoup (getStatelet s (plab pq)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage msg from to true))), msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
move=>H1 H2 H4; case: M=>G1 G2 G3 G4[rq][rs][Tr]Np.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by rewrite /getStatelet findU eqxx(cohS C)/=/getLocal/= findU (negbTE N) in G1 *. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: no_msg_from_to_consume'=>//; rewrite (cohVs C').
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU eqxx(cohS C)/=.
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
  case: msg H2 H4=>t c H2 H4.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: (msg_spec_consumeE (cohVs C') H4 G4); rewrite N orbC.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getStatelet findU eqxx (cohS C)/=/holds_res_perms.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getLocal/=findU eqxx/= (cohVl (cohQ s C)).  
case: H1;[|case=>//]; move=>Z; subst rt=>//=; simpl in H2, H4;
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite/QueryProtocol.receive_step (getStK _ Tr)/=.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case:ifP=>_; last by exists rq, rs. 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nid nat)) rq (@cons (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) rs))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  exists rq, ((from, head 0 msg) :: rs); split=>//rn.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  case X: (this == from); last first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by rewrite inE; case/orP; [case/eqP=>Z; subst; rewrite eqxx in X|move/Np].
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  move/eqP:X=>X; subst from.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case: msg H2 H4=>t c/= H2 H4; move: (G3 _ _ _ H4); subst t.  
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case:ifP=>_; last by exists rq, rs. 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by exists (seq.rem (from, head 0 msg) rq), rs. 
Qed.

(***********************************************************)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* 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]].

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* This lemma employs hooking -= it's better hold!.. :-s *)
Lemma msg_story_step' req_num data reqs resp to s s' :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  this != to ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  msg_story s req_num to data reqs resp ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  network_step W to s s' ->
  msg_story s' req_num to data reqs resp.
Proof.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
move=> N H S; case: H=> Qn H L M; split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- apply: (core_state_stable s data s')=>//.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists 1, to, s'; split=>//=; split=>//; case/step_coh: S.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- suff R : (network_rely W this s s') by rewrite -(rely_loc' _ R) in L.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists 1, to, s'; split=>//=; split=>//; case/step_coh: S.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case: S; [by case=>_<- |
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  move=>l st H1 to'/= msg n H2 H3 C H4 H5 H6->{s'}|
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  move=>l rt H1 i from pf H3 C msg H2/=[H4]_->{s'}];
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite -(cohD C) domUn !inE !domPt !inE in H3;
  case/andP:H3=>_ H3; case/orP: H3=>/eqP H3; subst l.

(* Something sending in lc, should be irrelevant for us. *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- move: st H1 H4 H5 H6; rewrite /get_st prEqC=>st H1 H4 H5 H6.
  by case: M; [constructor 1|constructor 2|constructor 3];
     rewrite /getStatelet findU (negbTE Lab_neq). 

(* Something sending in lq, this is where the interesting stuff happens! *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by apply: send_lq_all_cases.

(* Something is receiving in lc, should be irrelevant for us. *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- move: (coh_s _ _) rt pf H1 H2 H4; rewrite /get_rt prEqC=>C' rt pf H1 H2 H4.
  by case: M; [constructor 1|constructor 2|constructor 3];
     rewrite /getStatelet findU (negbTE Lab_neq). 

(* Something receiving in lq, requires honest proving. *)  
(* Goal: or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: (coh_s _ _) rt pf H1 H2 H4; rewrite /get_rt prEqQ=>C' rt pf H1 H2 H4.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case: M=>M;[|constructor 2|constructor 3]; last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by apply: recv_lq_case3.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by apply: recv_lq_case2.
by case:(recv_lq_case1 req_num _ _ to s N Qn M i from msg C C' pf _ H1 H2 H4);
  [constructor 1|constructor 2].
Qed.

Lemma msg_story_step req_num to data reqs resp z s s' :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  this != z ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  msg_story s req_num to data reqs resp ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  network_step W z s s' ->
  msg_story s' req_num to data reqs resp.
Proof.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case A: (to == z); first by move/eqP: A=>A; subst to; apply: msg_story_step'.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
move=> N H S; case: H=> Qn H L M; split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- apply: (core_state_stable s data s')=>//.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists 1, z, s'; split=>//=; split=>//; case/step_coh: S.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- suff R : (network_rely W this s s') by rewrite -(rely_loc' _ R) in L.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by exists 1, z, s'; split=>//=; split=>//; case/step_coh: S.

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case: S; [by case=>_<- |
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  move=>l st H1 to'/= msg n H2 H3 C H4 H5 H6->{s'}|
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  move=>l rt H1 i from pf H3 C msg H2/=[H4]_->{s'}];
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite -(cohD C) domUn !inE !domPt !inE in H3;
  case/andP:H3=>_ H3; case/orP: H3=>/eqP H3; subst l;
  do? [by rewrite /getStatelet findU (negbTE Lab_neq)];
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getStatelet findU eqxx(cohS C)/=.                

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Now only consider send-receive transitions within pq protocol *)

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(** Send-transitions **)
case:M; case=>G1 G2 G3 G4 G5; [constructor 1|constructor 2|constructor 3].

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Send-transition, case 1 *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- split=>//=; first by rewrite /getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>i t c; rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    case:ifP; last by move=>_; apply G2. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-; rewrite findPt.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by case=>???; subst to; rewrite eqxx in A.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + case: G4; case=>i[[c']Q1 Q3] Q2; split; last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    - move=>j c; rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
      case:ifP; last by move=>_; apply Q2.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
      rewrite domPt inE=>/eqP<-; rewrite findPt.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
      by case=>????; subst z to' c; rewrite eqxx in N.
(* Goal: @ex (Ordered.sort mid) (@unique (Ordered.sort mid) (fun i : Ordered.sort mid => @ex (list nat) (fun c : list nat => @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true))))) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) to (fun _ : nat => is_true false) *)
    exists i; split=>[|j[c1]];rewrite findUnL ?(valid_fresh) ?(cohVs (cohQ s C))//.   
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    - by exists c'; rewrite (find_some Q1). 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    case: ifP=>_; first by move=> T; apply: Q3; exists c1. 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by case/findPt_inv=>_[]????; subst to' z; rewrite eqxx in N.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case:G5=>rq[rs][Tr]Np; exists rq, rs; rewrite /getLocal/=findU A/=. 
    
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Send-transition, case 2 *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- split=>//=; first by rewrite /getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>i t c; rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    case:ifP; last by move=>_; apply G3. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-; rewrite findPt.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by case=>????; subst z to'; rewrite eqxx in N.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>i t c; rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    case:ifP; last by move=>_; apply G4. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-; rewrite findPt.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by case=>????; subst z to'; rewrite eqxx in A.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case:G5=>rq[rs][Tr]Np; exists rq, rs; rewrite /getLocal/=findU A/=. 

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Send-transition, case 3 *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- split=>//=; first by rewrite /getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>i t c; rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    case:ifP; last by move=>_; apply G3. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite domPt inE=>/eqP<-; rewrite findPt.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by case=>????; subst to' z; rewrite eqxx in N.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + case: G4; case=>i[[c']Q1 Q3] Q2; split; last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    - move=>j c; rewrite findUnR ?(valid_fresh) ?(cohVs (cohQ s C))//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
      case:ifP; last by move=>_; apply Q2.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
      rewrite domPt inE=>/eqP<-; rewrite findPt.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
      by case=>????; subst z to' c; rewrite eqxx in A.
(* Goal: @ex (Ordered.sort mid) (@unique (Ordered.sort mid) (fun i : Ordered.sort mid => @ex (list nat) (fun c : list nat => @eq (option (State.msg TaggedMessage)) (@UMC.find mid (State.msg TaggedMessage) (union_mapUMC mid (State.msg TaggedMessage)) i (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg (@t_snd (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) st) msg) to to' true)))) (@Some (State.msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true))))) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes pq) (Protocols.coh pq) st) msg) to to' true)))) s) lq) to (fun _ : nat => is_true false) *)
    exists i; split=>[|j[c1]];rewrite findUnL ?(valid_fresh) ?(cohVs (cohQ s C))//.   
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    - by exists c'; rewrite (find_some Q1). 
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    case: ifP=>_; first by move=> T; apply: Q3; exists c1. 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by case/findPt_inv=>_[]????; subst to' z; rewrite eqxx in A.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case:G5=>rq[rs][Tr]Np; exists rq, rs; rewrite /getLocal/=findU A/=. 

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(** Receive-transitions **)
case:M; case=>G1 G2 G3 G4 G5; [constructor 1|constructor 2|constructor 3].

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Receive-transition, case 1 *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- split=>//=; first by rewrite /getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by apply: no_msg_from_to_consume'=>//; rewrite (cohVs (cohQ s C)).
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + case: msg H2 H4=>t c H2 H4.
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
    apply: (msg_spec_consumeE (cohVs (cohQ s C)) H4 G4).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by rewrite (negbT A) orbC.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case:G5=>rq[rs][Tr]Np; exists rq, rs; rewrite /getLocal/=findU A/=. 

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Receive-transition, case 2 *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- split=>//=; first by rewrite /getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by apply: no_msg_from_to_consume'=>//; rewrite (cohVs (cohQ s C)).
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by apply: no_msg_from_to_consume'=>//; rewrite (cohVs (cohQ s C)).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case:G5=>rq[rs][Tr]Np; exists rq, rs; rewrite /getLocal/=findU A/=. 

(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
(* Receive-transition, case 3 *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- split=>//=; first by rewrite /getLocal/= findU (negbTE N) in G1 *. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by apply: no_msg_from_to_consume'=>//; rewrite (cohVs (cohQ s C)).
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + case: msg H2 H4=>t c H2 H4.
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
    apply: (msg_spec_consumeE (cohVs (cohQ s C)) H4 G4).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by rewrite (negbTE N) orbC.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case:G5=>rq[rs][Tr]Np; exists rq, rs; rewrite /getLocal/=findU A/=.
Qed.


Lemma msg_story_rely req_num to data reqs resp s s2 :
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  msg_story s req_num to data reqs resp ->
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  network_rely W this s s2 ->
  msg_story s2 req_num to data reqs resp.
Proof.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
move=>H1 [n]H2; elim: n s H2 H1=>/=[s | n Hi s]; first by case=>Z _; subst s2.
case=>z[s1][N]H1 H2 H3; apply: (Hi s1 H2).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by apply: (msg_story_step _ _ _ _ _ _ _ _ N H3 H1).
Qed.  


(**************************************************************)
(*********************  Query Programs ************************)
(**************************************************************)

(****************** Reading a request number *******************)

Program Definition read_request_id to :
  {rrd : seq (nid * nat) * seq (nid * nat) * Data}, DHT [this, W]
   (fun i =>
      let: (reqs, resp, data) := rrd in 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
      [/\ getLq i = qst :-> (reqs, resp),
       local_indicator data (getLc i),
       query_init_state to i &
       core_state_to_data to (getLc' i to) data],
   fun (r : nat) m => 
     let: (reqs, resp, data) := rrd in 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
     [/\ getLq m = qst :-> (reqs, resp),
       local_indicator data (getLc m),
       query_init_state to m,
       core_state_to_data to (getLc' m to) data &                                              
       r = fresh_id reqs]) :=
  Do _ (act (@skip_action_wrapper W this lq pq prEqQ _
                                (fun s pf => fresh_id (getSt this pf).1))).
Next Obligation.
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
apply: ghC=>i0 [[rq rs] d][P1] P2 P3 P4 C1.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
apply: act_rule=>i1 R1; split=>[|r i2 i3]; first by case: (rely_coh R1).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case=>/=H1[Cj]Z; subst i1=>->R2.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
rewrite !(rely_loc' _ R2) !(rely_loc' _ R1); split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by apply: (query_init_rely _ _ _ _ R2); apply: (query_init_rely _ _ _ _ R1).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- apply: (core_state_stable _ _ _ _ R2); [by case: P3|by rewrite !(rely_loc' _ R1)|].
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: (core_state_stable _ _ _ _ R1)=>//; case: P3.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
rewrite -(rely_loc' _ R1) in P1.
suff X: getSt this (Actions.safe_local prEqQ H1) = (rq, rs) by rewrite X. 
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by move: (getStK (Actions.safe_local prEqQ H1) P1)=>/=.
Qed.
    
(********************** Sending request ***********************)

Program Definition send_req rid to :=
  act (@send_action_wrapper W pq this (plab pq) prEqQ
                            (qsend_req qnodes) _ [:: rid] to).
Next Obligation. by rewrite !InE; left. Qed.

Program Definition send_req_act (rid : nat) (to : nid) :
  {rrd : seq (nid * nat) * seq (nid * nat) * Data}, DHT [this, W]
   (fun i =>
      let: (reqs, resp, data) := rrd in 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
      [/\ getLq i = qst :-> (reqs, resp),
       local_indicator data (getLc i),
       rid = fresh_id reqs,
       query_init_state to i &
       core_state_to_data to (getLc' i to) data],
   fun (r : seq nat) m => 
     let: (reqs, resp, data) := rrd in 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
     [/\ getLq m = qst :-> ((to, rid) :: reqs, resp),
      local_indicator data (getLc m),
      r = [:: rid],
      msg_story m rid to data ((to, rid) :: reqs) resp &
      core_state_to_data to (getLc' m to) data])
  := Do (send_req rid to).

Next Obligation.
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
apply: ghC=>s0[[reqs resp] d]/=[P1] Pi P2 Q P3 C0.
apply: act_rule=>i1 R0; split=>//=[|r i2 i3[Hs]St R2].
(* Precondition *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /Actions.send_act_safe/=.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  move/rely_coh: (R0)=>[_ C1]; rewrite -(rely_loc' _ R0) in P1.
  move: (coh_coh lq C1); rewrite prEqQ=>Cq1; 
  split=>//; [split=>//; try by case:Q| | ].
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by exists Cq1; rewrite /QueryProtocol.send_req_prec (getStK _ P1)/= P2.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  + by apply/andP; split=>//; rewrite -(cohD C1) W_dom !inE eqxx orbC.
(* Goal: forall (x' : nat) (_ : @ex (list nat) (fun c : list nat => @eq (option (msg TaggedMessage)) (@UMC.find mid (msg TaggedMessage) (union_mapUMC mid (msg TaggedMessage)) x' (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) (@Some (msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true)))), @eq nat (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) x' *)
  move=>z lc hk; rewrite find_umfilt eqxx /query_hookz.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
  move => F.
  apply sym_eq in F.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
  move: F.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by move/find_some; rewrite domPt !inE=>/eqP.
(* Postcondition *)
have N: network_step W this i1 i2.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- apply: (Actions.send_act_step_sem _ _ St)=>//; first by rewrite prEqQ.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite !InE; left.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite (rely_loc' _ R2).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
rewrite -(rely_loc' _ R0) in P1.
move/rely_coh: (R0)=>[_]C1; move: (coh_coh lq C1);rewrite prEqQ=>Cq1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case: St=>->[h]/=[].
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite/QueryProtocol.send_step/QueryProtocol.send_step_fun/=.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite (pf_irr (QueryProtocol.send_safe_coh _) Cq1).
rewrite (getStK _ P1); case=>Z Z'; subst h rid.
rewrite Z' locE; last first;
[by apply: cohVl Cq1| by apply: cohS C1|
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
   by rewrite -(cohD C1) W_dom !inE eqxx orbC|].
have X : getLc i3 = getLc s0.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite (rely_loc' _ R2) -(rely_loc' _ R0) Z'.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by rewrite /getStatelet findU; move/negbTE: Lab_neq; rewrite eq_sym=>->.
(* Massaging the hypotheses. *)
(* Goal: and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (@ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end Cq pf) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false)))) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
split=>//; try by rewrite X//.
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
apply: (msg_story_rely _ _ _ _ _ i2)=>//.
have E: core_state_to_data to (getLc' i1 to) = core_state_to_data to (getLc' i2 to).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case B: (to == this); [move/eqP:B=>Z; subst to | ]; last first.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + by rewrite /getLocal (step_is_local _ N)=>//; move/negbT: B.
  subst i2; rewrite ![getLc' _ _]/getLocal /getStatelet/=.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by rewrite findU; move/negbTE: Lab_neq; rewrite eq_sym=>->.
move: (query_init_rely _ s0 i1 Q R0)=>{Q}Q; subst i2.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: (Q)=>[Q1 Q2 Q3 Q4].
(* Goal: or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: (core_state_stable _ _ _ _ R0 Q1 Pi P3); rewrite E=>{E}E.
clear N R2 Q C0 X i3 P3.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU; move/negbTE: Lab_neq; rewrite eq_sym=>->//=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite (rely_loc' _ R0).
constructor 1. 
(* Goal: forall (coh_s : @Coherence.sort (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (getStatelet s lq)) (rt : @receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (pf : is_true (@in_mem nid z (@mem nid (ssrbool.predPredType nid) (nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq) (getStatelet s lq))))) (_ : @InMem (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) rt (@Mem (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (seq_PredType (@receive_trans (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)))) (get_rt (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq))) (_ : @eq nat (tag msg) (@t_rcv (Protocols.nodes (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (@UMC.sort Label protocol (union_mapUMC Label protocol)) (PCM.sort (union_mapPCM hook_domain hook_type)) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt)), and4 (is_true (@in_mem nid to (@mem nat (seq_predType nat_eqType) qnodes))) (holds_res_perms (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) z (@receive_step (Protocols.nodes (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) (Protocols.coh (getProtocol (@pair (UMDef.tp Label protocol) (UMDef.tp hook_domain hook_type) (@um_pts Label protocol lq pq) (@PCM.unit (union_mapPCM hook_domain hook_type))) lq)) rt z from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end coh_s pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) to (fun _ : nat => is_true false)) (no_msg_from_to' this to request_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) (no_msg_from_to' to this response_msg (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i)) *)
split=>//; rewrite ?inE ?eqxx=>//=.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite locE=>//; 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  [by rewrite -(cohD C1) W_dom !inE eqxx orbC|
   apply: cohS C1|by apply: cohVl Cq1].
(* Prove the interesting transition *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- move=>m t c; rewrite /getStatelet findU eqxx (cohS C1)/=.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  set ds := (dsoup _); rewrite findUnR; last first.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite valid_fresh; apply: cohVs Cq1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite domPt !inE/=; case:ifP=>[/eqP<-|_]; last by apply: Q4.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by rewrite findPt; case=><-. 
(* TODO: refactor this into a separate lemma about those state predicates *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet findU eqxx (cohS C1)/=.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
  set ds := (dsoup _); split=>//.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
  exists (fresh ds); split=>//.
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + exists [:: fresh_id reqs].
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    rewrite findUnR; last by rewrite valid_fresh; apply: cohVs Cq1.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by rewrite domPt inE eqxx findPt. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + move=>x[c]; rewrite findUnR; last by rewrite valid_fresh; apply: cohVs Cq1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    case:ifP=>[|_[]]; first by rewrite domPt inE=>/eqP->.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by move/(Q3 x treq c).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  move=>x c ; rewrite findUnR; last by rewrite valid_fresh; apply: cohVs Cq1.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  case:ifP=>[|_[]]; last by move/(Q3 x treq c).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by rewrite domPt inE=>/eqP->; rewrite findPt;case=>->.
set ds := (dsoup _).
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case: Q2=>reqs'[resp'][G1 G2].
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case X: (to == this).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- exists ((this, fresh_id reqs) :: reqs), resp; move/eqP:X=>X; subst to.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite P1 in G1; have V: valid (qst :-> (reqs, resp)) by [].
(* Goal: forall (_ : @eq (prod (list (prod nid nat)) (list (prod nid nat))) (@pair (list (prod nid nat)) (list (prod nid nat)) rq rs) (@pair QueryProtocol.reqs QueryProtocol.resp x1 x2)) (_ : is_true (andb (@uniq (prod_eqType nat_eqType nat_eqType) x1) (@uniq (prod_eqType nat_eqType nat_eqType) x2))), is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  case: (hcancelPtV V G1)=>Z1 Z2; subst reqs' resp'=>{G1}.
  split=>//; rewrite locE//; last first;
    [by apply: cohVl Cq1| by apply: cohS C1|
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
       by rewrite -(cohD C1) W_dom !inE eqxx orbC].
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- exists reqs', resp'; split=>//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getStatelet findU eqxx (cohS C1)/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by rewrite /getLocal findU X. 
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case: (Q)=>Nq _ _ _.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: (core_state_stable _ _ _ _ R0 Nq Pi P3)=>H1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
rewrite -(rely_loc' _ R0) in Pi.
have Pi': local_indicator d (getLc' i2 this).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by rewrite Z'/getStatelet findU/= eq_sym; move/negbTE:Lab_neq->. 
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
apply: (core_state_stable _ _ _ _ R2 Nq Pi').
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
by rewrite Z'/getStatelet findU/= eq_sym; move/negbTE:Lab_neq->. 
Qed.

(***************** Receiving request in a loop ******************)

Program Definition tryrecv_resp (rid : nat) (to : nid) :=
  act (@tryrecv_action_wrapper W this
      (fun k n t (b : seq nat) => [&& k == lq, n == to, t == tresp,
                                   head 0 b == rid & to \in qnodes]) _).
Next Obligation.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case/andP:H=>/eqP=>->_; rewrite joinC domUn inE domPt inE eqxx andbC/=.
(* Goal: is_true (@PCM.valid (@union_map_classPCM nat_ordType protocol (union_mapUMC Label protocol)) (@PCM.join (@union_map_classPCM nat_ordType protocol (union_mapUMC Label protocol)) (@um_pts Label protocol lq pq) (@um_pts Label protocol (plab pc) pc))) *)
case: validUn=>//=; rewrite ?validPt//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
move=>k; rewrite !domPt !inE=>/eqP<-/eqP Z; subst lq.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by move/negbTE: Lab_neq; rewrite eqxx.
Qed.

(* Ending condition *)
Definition recv_resp_cond (res : option Data): bool :=
  if res is Some v then false else true.

(* Invariant relates the argument and the shape of the state *)
Definition recv_resp_inv (rid : nat) to
           (rrd : (seq (nid * nat) * seq (nid * nat) * Data)) :
  cont (option Data) :=
  fun res i =>
    let: (reqs, resp, data) := rrd in
    if res is Some d
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    then [/\ getLq i = qst :-> (reqs, resp),
          local_indicator data (getLc i),
          query_init_state to i,
          core_state_to_data to (getLc' i to) data &
          d = data]
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    else [/\ getLq i = qst :-> ((to, rid) :: reqs, resp),
          local_indicator data (getLc i) &
          msg_story i rid to data ((to, rid) :: reqs) resp].

Program Definition receive_resp_loop (rid : nat) to :
  {(rrd : (seq (nid * nat) * seq (nid * nat) * Data))}, DHT [this, W]
  (fun i => let: (reqs, resp, data) := rrd in
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    [/\ getLq i = qst :-> ((to, rid) :: reqs, resp),
     local_indicator data (getLc i),
     msg_story i rid to data ((to, rid) :: reqs) resp &
     core_state_to_data to (getLc' i to) data],
  fun res m =>
    let: (reqs, resp, data) := rrd in
    exists d, res = Some d /\
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
     [/\ getLq m = qst :-> (reqs, resp),
      local_indicator data (getLc m),
      query_init_state to m,
      core_state_to_data to (getLc' m to) data &
      d = data]) := 
  Do _ (@while this W _ _ recv_resp_cond (recv_resp_inv rid to) _
         (fun _ => Do _ (
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
           r <-- tryrecv_resp rid to;
             match r with
             | Some (from, tg, body) =>
               ret _ _ (Some (deserialize (behead body)))             
             | None => ret _ _ None
             end              
         )) None).

Next Obligation. by apply: with_spec x. Defined.
Next Obligation.
(* Goal: recv_resp_inv rid to (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) l l0) d) b s1 *)
case: b H=>[b|]; rewrite /recv_resp_inv !(rely_loc' _ H0); case=>H1 H2 H3.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- move=>H4 ->; split=>//; try by apply: (query_init_rely _ _ _ H3 H0).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by apply: (core_state_stable _ _ _ _ H0 _ H2)=>//; case: H3. 
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
split=>//; try apply: (msg_story_rely _ _ _ _ _ _ _ H3 H0).
Defined.
  
Next Obligation.
rename H into d.
(* Goal: @verify this W (option Data) i1 (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (fun (res : option Data) (m : state) => @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) d) (@eq Data d0 d)))) *)
apply: ghC=>i0 [[reqs resp] data][G0 H0] C0; apply: step.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
apply: act_rule=>i1 R1/=; split; first by case: (rely_coh R1).
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case=>[[[from tg] body] i2 i3|i2 i3]; last first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case=>S/=[]C1; case; last by case=>?[?][?][?][?][?][].
  case=>_ _ Z; subst i2=>R3; apply: ret_rule=>i4 R4/=.
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
  case: d G0 H0=>//=_[H1 H2 H3].
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
  rewrite !(rely_loc' _ R4)!(rely_loc' _ R3)!(rely_loc' _ R1); split=>//.
  by apply: (msg_story_rely _ _ _ _ _ _ _ _ R4);
    apply: (msg_story_rely _ _ _ _ _ _ _ _ R3);
    apply: (msg_story_rely _ _ _ _ _ _ _ _ R1).
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
case=>Sf[]C1[]=>[|[l'][mid][tms][from'][rt][pf][][E]Hin E2 Hw/=]; first by case. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case/andP=>/eqP Z1/andP[/eqP Z2]/andP[/eqP Z3]/andP[/eqP Z4]Qn->{i2}[Z5] Z6 Z7 R3.
subst l' from' from tg body rid.
(* Goal: forall (x' : nat) (_ : @ex (list nat) (fun c : list nat => @eq (option (msg TaggedMessage)) (@UMC.find mid (msg TaggedMessage) (union_mapUMC mid (msg TaggedMessage)) x' (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) (@Some (msg TaggedMessage) (@Msg TaggedMessage (TMsg tresp c) to this true)))), @eq nat (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) x' *)
move: rt pf (coh_s (w:=W) lq (s:=i1) C1) Hin R3 E2 Hw Z3 E; rewrite !prEqQ.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move=>/=rt pf C1' Hin R E2 Hw G E.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
have D: rt = qrecv_resp _ by move: Hin G; do![case=>/=; first by move=>->].  
subst rt=>{G}; simpl in E2.
set i2 := (upd _ _ _) in R.
apply: ret_rule=>i4 R3/=; rewrite !(rely_loc' _ R3)!(rely_loc' _ R).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
suff X : [/\ getLocal this (getStatelet i2 lq) = qst :-> (reqs, resp),
          local_indicator data (getLc' i2 this),
          query_init_state to i2 &
          deserialize (behead tms) = data].
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case: X=>X1 X2 X3 X4; split=>//.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: (query_init_rely _ _ _ _ R3); apply: (query_init_rely _ _ _ _ R).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case: d G0 H0=>//=_[_ H2][_] H3 _ _; case: X3=>Nq _ _ _.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  move: (X2); rewrite -(rely_loc' _ R)=>X3.
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
  apply: (core_state_stable _ _ _ _ R3 Nq X3).  
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
  apply: (core_state_stable _ _ _ _ R Nq X2).  
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
  move: (core_state_stable _ _ _ _ R1 Nq H2 H3)=>{H2 H3 X3 X4}Y.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by subst i2; rewrite /getStatelet findU eq_sym; move/negbTE:Lab_neq=>->.  
clear R i4 R3.  
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case: d G0 H0=>//=_[Q1 Q2 Q3]; rewrite -!(rely_loc' _ R1) in Q1 Q2.
(* Goal: forall (_ : all_hooks_fire query_hookz (plab pc) (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) s to msg to') (_ : @eq (option Heap.heap) (@Some Heap.heap n) (@send_step (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st to to' (getStatelet s (plab pq)) msg H4)), or3 (msg_just_sent (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_received (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to) (msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pc) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to n (dstate (getStatelet s (plab pq)))) (@PCM.join (union_mapPCM mid (State.msg TaggedMessage)) (dsoup (getStatelet s (plab pq))) (@um_pts nat_ordType (State.msg TaggedMessage) (@fresh (State.msg TaggedMessage) (dsoup (getStatelet s (plab pq)))) (@Msg TaggedMessage (TMsg (@t_snd (Protocols.nodes (getProtocol W (plab pc))) (Protocols.coh (getProtocol W (plab pc))) st) msg) to to' true)))) s) lq) reqs resp req_num to data) *)
move: (msg_story_rely _ _ _ _ _ _ _ Q3 R1)=>{Q3}Q3.
have P1: valid (dstate (getSq i1)) by case: (C1')=>P1 P2 P3 P4.
have P2: valid i1 by apply: (cohS C1).
have P3: lq \in dom i1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  rewrite -(cohD C1) domUn inE !domPt !inE/= inE eqxx orbC andbC/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case/andP: W_valid.
clear Hin R1 C0 i0 i3 Hw. 
(* Consider different cases for msg_story. *)
(* Goal: msg_spec' to this tresp (@cons nat req_num (serialize data)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i) *)
(* Goal: holds_res_perms (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) to (fun _ : nat => is_true false) *)
case: Q3=>_ Q3 Q4 [].
(* Now dismiss two first disjuncts. *)
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case=>_/(_ mid (tag tms) (tms_cont tms)); rewrite -E.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case: (tms)E2=>t c/=E2=>/(_ (erefl _))/=; subst t. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case=>_ _ _/(_ mid (tag tms) (tms_cont tms)); rewrite -E.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by case: (tms)E2=>t c/=E2=>/(_ (erefl _))/=; subst t. 
(* The interesting part *)
(* Goal: is_true (@PCM.valid (@union_map_classPCM nat_ordType protocol (union_mapUMC Label protocol)) (@PCM.join (@union_map_classPCM nat_ordType protocol (union_mapUMC Label protocol)) (@um_pts Label protocol lq pq) (@um_pts Label protocol (plab pc) pc))) *)
case=>X1 _ X2 X3 X4; rewrite /query_init_state.
subst i2.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /receive_step/=/QueryProtocol.receive_step !(getStK C1' X1)/=!inE!eqxx/=.
rewrite !locE ?Qn/=;[|by case: C1'|by apply: cohS C1|by case: C1'].
apply sym_eq in E.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
split=>//; last 1 first.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case:X3; case=>m'[[c]]E'/(_ mid) H.
  have Z: m' = mid by apply: H; exists (tms_cont tms);
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
    rewrite E; case: (tms) E2=>/=t c'->.
  subst m'; clear H; rewrite E in E'.
(* Goal: forall (_ : @eq (prod (list (prod nid nat)) (list (prod nid nat))) (@pair (list (prod nid nat)) (list (prod nid nat)) rq rs) (@pair QueryProtocol.reqs QueryProtocol.resp x1 x2)) (_ : is_true (andb (@uniq (prod_eqType nat_eqType nat_eqType) x1) (@uniq (prod_eqType nat_eqType nat_eqType) x2))), is_true false *)
(* Goal: @eq Heap.heap (getLocal this (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp)) *)
(* Goal: no_msg_from_to' this to request_msg (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
(* Goal: msg_spec' to this tresp (@cons (Equality.sort nat_eqType) req_num (serialize data)) (dsoup (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) lq (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (QueryProtocol.mkLocal (@pair QueryProtocol.reqs (list (prod nat nat)) rq (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat this (@head nat O (@cons nat rid (serialize data)))) rs))) (dstate (getStatelet s lq))) (@PCM.join (union_mapPCM mid (msg TaggedMessage)) (dsoup (getStatelet s lq)) (@um_pts nat_ordType (msg TaggedMessage) (@fresh (msg TaggedMessage) (dsoup (getStatelet s lq))) (@Msg TaggedMessage (TMsg QueryProtocol.tresp (@cons nat rid (serialize data))) to this true)))) s) lq)) *)
  case: (tms) E' E=>t c'[]Z1 Z2; subst c' t=>E.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by move/(_ _ _ E)=>/eqP->/=; apply: ds_inverse.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by rewrite /getStatelet findU eq_sym; move/negbTE:Lab_neq=>->.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- case B: (to == this); last first. 
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: forall _ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) (@cons (prod nat nat) (@pair nat nat from (@head nat O (tms_cont msg))) rs))), is_true false *)
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (QueryProtocol.mkLocal (if @in_mem (prod nid nat) (@pair nid nat from (@head nat O (tms_cont msg))) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) rq) then @pair (list (prod nat nat)) QueryProtocol.resp (@seq.rem (prod_eqType nat_eqType nat_eqType) (@pair nid nat from (@head nat O (tms_cont msg))) rq) rs else @pair (list (prod nid nat)) (list (prod nid nat)) rq rs)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : nat) (_ : is_true (@in_mem (prod nid nat) (@pair nid nat this rn) (@mem (prod nat nat) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  + rewrite /getStatelet findU eqxx/= (cohS C1)/=.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
    rewrite /holds_res_perms in X4.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
    case: X4=> rq[rs][G1 G2]; exists rq, rs; split=>//.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
    by rewrite /getLocal/= findU; case:ifP=>//=/eqP Z; subst to; rewrite eqxx in B.
  move/eqP:B=>B; subst to; case: X4=> rq[rs][G1 G2].
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite G1 in X1.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  have V: valid (qst :-> (rq, rs)) by apply: validPt.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
  case: (hcancelPtV V X1)=>Z1 Z2; subst rq rs; exists reqs, resp; split=>//.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
  rewrite /getStatelet/= findU eqxx (cohS C1)/=/getLocal/=findU eqxx/=. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
  by case: C1'=>_->. 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- rewrite /getStatelet/= findU eqxx/= (cohS C1)/=.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
  by apply: (no_msg_from_to_consume' _ X2); case: C1'; case.
(* Goal: @ex (list (prod nid nat)) (fun reqs : list (prod nid nat) => @ex (list (prod nid nat)) (fun resp : list (prod nid nat) => and (@eq Heap.heap (getLocal to (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (fun (_ : dstatelet) (x : nat) => @pred_of_eq_seq nat_eqType qnodes x) (QueryProtocol.QCoh qnodes) rt to from (tms_cont msg) match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end C' pf) (dstate match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end)) (consume_msg (dsoup match @UMC.find Label dstatelet (union_mapUMC Label dstatelet) lq s with | Some d => d | None => empty_dstatelet end) i))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (forall (rn : Equality.sort nat_eqType) (_ : is_true (@in_mem (prod nid (Equality.sort nat_eqType)) (@pair nid (Equality.sort nat_eqType) this rn) (@mem (Equality.sort (prod_eqType nat_eqType nat_eqType)) (seq_predType (prod_eqType nat_eqType nat_eqType)) resp))), is_true false))) *)
rewrite /getStatelet/= findU eqxx/= (cohS C1)/=.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
case: (tms) E2 E=>t c/=-> E;apply: (no_msg_spec_consume _ E X3).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by case: C1'; case.
Qed.

Next Obligation.
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
apply:ghC=>i1[[reqs resp] d][L1 I1 M1 S1] C1.
(* Goal: @verify this W (option Data) i1 (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (fun (res : option Data) (m : state) => @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) d) (@eq Data d0 d)))) *)
apply: (gh_ex (g:=(reqs, resp, d))); apply: call_rule=>// res i2[Q1 Q2] C2.
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by case: res Q1 Q2=>//=data _ [Q1 Q2 Z]; exists data.
Qed.

(*****************************************************************)
(*********           Full request program            *************)
(*****************************************************************)

Variable default_data : Data.

Program Definition request_data_program to :
  {rrd : seq (nid * nat) * seq (nid * nat) * Data}, DHT [this, W]
   (fun i =>
      let: (reqs, resp, data) := rrd in 
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
      [/\ getLq i = qst :-> (reqs, resp),
       local_indicator data (getLc i),
       query_init_state to i &
       core_state_to_data to (getLc' i to) data],
    fun res m =>
      let: (reqs, resp, data) := rrd in
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
      [/\ getLq m = qst :-> (reqs, resp),
       local_indicator data (getLc m),
       query_init_state to m,
       core_state_to_data to (getLc' m to) data &
       res = data]) :=
  Do _ (
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
     rid <-- read_request_id to;
     send_req_act rid to;;
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
     r <-- receive_resp_loop rid to;
     ret _ _ (if r is Some d then d else default_data) 
     ).
Next Obligation.
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
apply:ghC=>i1[[reqs resp] d][L1 I1 M1 S1] C1.
(* Goal: @verify this W (option Data) i1 (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (fun (res : option Data) (m : state) => @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) d) (@eq Data d0 d)))) *)
apply: step; apply: (gh_ex (g:=(reqs, resp, d))).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
apply: call_rule=>//r i2[P1 P2 P3 P4->{r}] C2.
(* Goal: @verify this W (option Data) i1 (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (fun (res : option Data) (m : state) => @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) d) (@eq Data d0 d)))) *)
apply: step; apply: (gh_ex (g:=(reqs, resp, d))).
(* Goal: @conseq W (option Data) this (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun rrd : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun i : state => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => and4 (@eq Heap.heap (getLocal this (getStatelet i lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp))) (local_indicator data (getLocal this (getStatelet i (plab pc)))) (msg_story i rid to data (@cons (prod nid nat) (@pair nid nat to rid) reqs) resp) (core_state_to_data to (getLocal to (getStatelet i (plab pc))) data)) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)) (fun (res : option Data) (m : state) => (let 'pair p data as rrd' := rrd return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd' rrd, Prop) in let 'pair reqs resp as p0 := p return (forall _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data p0 data) rrd, Prop) in fun _ : @eq (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (@pair (prod (list (prod nid nat)) (list (prod nid nat))) Data (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp) data) rrd => @ex Data (fun d : Data => and (@eq (option Data) res (@Some Data d)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator data (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) data) (@eq Data d data)))) (@Logic.eq_refl (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) rrd)))) *)
apply: call_rule=>//_ i3[Q1 Q2 _ Q3 Q4]C3.
(* Goal: @verify this W (option Data) i1 (receive_resp_loop_obligation_1 rid to (@while this W (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (option Data) recv_resp_cond (recv_resp_inv rid to) (fun (a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (b : option Data) (s0 s1 : state) (H : recv_resp_inv rid to a b s0) (H0 : network_rely W this s0 s1) => receive_resp_loop_obligation_2 rid to a b s0 s1 H H0) (fun b : option Data => @do' this W (option Data) (@logvar (option Data) (prod (prod (list (prod nid nat)) (list (prod nid nat))) Data) (fun a : prod (prod (list (prod nid nat)) (list (prod nid nat))) Data => @binarify (option Data) (fun s : state => and (is_true (recv_resp_cond b)) (recv_resp_inv rid to a b s)) (fun (b' : option Data) (s1 : state) => recv_resp_inv rid to a b' s1))) (receive_resp_loop_obligation_3 (@bind this W (option (prod (prod nid nat) (list nat))) (option Data) (tryrecv_resp rid to) (fun r : option (prod (prod nid nat) (list nat)) => match r as r' return (forall _ : @eq (option (prod (prod nid nat) (list nat))) r' r, DT this W (option Data)) with | Some p => let (p0, body) as p0 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) p0) r, DT this W (option Data)) := p in let (from, tg) as p1 return (forall _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) p1 body)) r, DT this W (option Data)) := p0 in fun _ : @eq (option (prod (prod nid nat) (list nat))) (@Some (prod (prod nid nat) (list nat)) (@pair (prod nid nat) (list nat) (@pair nid nat from tg) body)) r => @ret this W (option Data) (@Some Data (deserialize (@behead nat body))) | None => fun _ : @eq (option (prod (prod nid nat) (list nat))) (@None (prod (prod nid nat) (list nat))) r => @ret this W (option Data) (@None Data) end (@Logic.eq_refl (option (prod (prod nid nat) (list nat))) r)))) (receive_resp_loop_obligation_4 rid to b)) (@None Data))) (fun (res : option Data) (m : state) => @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet m lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet m (plab pc)))) (query_init_state to m) (core_state_to_data to (getLocal to (getStatelet m (plab pc))) d) (@eq Data d0 d)))) *)
apply: step; apply: (gh_ex (g:=(reqs, resp, d))).
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
apply: call_rule=>//? i4[d'][->][T1] T2 T3 T4->{d'}C4.
(* Goal: msg_responded (getStatelet (@UMC.upd Label dstatelet (union_mapUMC Label dstatelet) (plab pq) (DStatelet (@UMC.upd nat_ordType Heap.heap (union_mapUMC nat_ordType Heap.heap) to (@receive_step (Protocols.nodes pq) (Protocols.coh pq) rt to from (tms_cont msg) (getStatelet s (plab pq)) C' pf) (dstate (getStatelet s (plab pq)))) (consume_msg (dsoup (getStatelet s (plab pq))) i)) s) lq) reqs resp req_num to data *)
apply: ret_rule=>i5 R; rewrite !(rely_loc' _ R); split=>//.
(* Goal: core_state_to_data to (getLocal to (getStatelet s1 (plab pc))) d *)
(* Goal: and3 (@eq Heap.heap (getLocal this (getStatelet s0 (plab pq))) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) (@cons (prod nid nat) (@pair nid nat to rid) l) l0))) (local_indicator d (getLocal this (getStatelet s0 (plab pc)))) (msg_story s1 rid to d (@cons (prod nid nat) (@pair nid nat to rid) l) l0) *)
- by apply: (query_init_rely _ _ _ _ R).
(* Goal: @ex Data (fun d0 : Data => and (@eq (option Data) res (@Some Data d0)) (and5 (@eq Heap.heap (getLocal this (getStatelet i2 lq)) (@heap_pts (prod (list (prod nid nat)) (list (prod nid nat))) qst (@pair (list (prod nid nat)) (list (prod nid nat)) reqs resp))) (local_indicator d (getLocal this (getStatelet i2 (plab pc)))) (query_init_state to i2) (core_state_to_data to (getLocal to (getStatelet i2 (plab pc))) d) (@eq Data d0 d))) *)
by apply: (core_state_stable _ _ _ _ R _ T2 T4); case: T3.  
Qed.

End QueryHooked.
