Notation "'{{' m 'in' s 'at' id '}}'" := (find id s = Some m).
Notation "'{{' m 'in' s '}}'" := (exists id, {{m in s at id}}).
End Shared.
(* Local per-protocol state with per-node resources *)
Section Local.
Variable U : Type.
Definition nid := nat.
(* Local state of a a protocol is simply a partial map from node ids to their local contributions, along with the validity of the cumulative contribution. *)
Definition lstate_type := union_map [ordType of nid] U.
End Local.
(* Definition um_all {A:ordType} {B} (p : A -> B -> bool) (u : union_map A B) : bool := um_recf false true (fun k v f rec Hval Hpath => p k v && rec) u.  Definition um_some {A:ordType} {B} (p : A -> B -> bool) (u : union_map A B) : bool := um_recf false false (fun k v f rec Hval Hpath => p k v || rec) u. *)
Section Statelets.
(* A particular statelet instance. The Label and the PCM are the parameters and are defined by the protocol. The lstate and dsop are subject of the evolution. *)
Structure dstatelet  :=
DStatelet {
(* Not sure if it's the best way to represent information about kinds of messages in this particular dstatelet, but let's think of tags as of integers for now, so dTagToCont will map the tags to specific types. *)
(* Local state for each node as a pair of heaps; first heap is real, second heap is a ghost one. Let's deal with this model for now before we figure out how to discharge equalities in a better way *)
dstate     : lstate_type heap;
dsoup      : soup
}.
Fixpoint empty_lstate (ns : seq nid) :=
if ns is n :: ns'
then n \\-> Heap.empty \+ (empty_lstate ns')
else  Unit.
(* Definition empty_dstatelet ns : dstatelet := *)
(*   @DStatelet (empty_lstate (undup ns)) Unit. *)
(* Lemma valid_mt_soup ns : valid (dsoup (empty_dstatelet ns)). *)
(* Proof. by rewrite /= valid_unit. Qed. *)
(* Lemma dom_mt ns : *)
(*   valid (empty_lstate (undup ns)) /\ dom (empty_lstate (undup ns)) =i undup ns. *)
(* Proof. *)
(* elim: ns=>//=[|n ns [H1 H2]]; first by rewrite dom0. *)
(* case B: (n \in ns)=>//=; split. *)
(* - by rewrite gen_validPtUn/= H1 H2/=; apply/negbT; rewrite mem_undup. *)
(* move=> z; rewrite um_domPtUn inE/= gen_validPtUn/= H1 H2/=. *)
(* rewrite -mem_undup in B; rewrite B/=. *)
(* case C: (n == z)=>//=; first by rewrite in_cons eq_sym C. *)
(* by rewrite H2 in_cons eq_sym C/=. *)
(* Qed. *)
(* Lemma valid_mt_state ns : valid (dstate (empty_dstatelet ns)). *)
(* Proof. *)
(* elim:ns=>//=n ns H; case I: (n \in ns)=>//=.   *)
(* by rewrite gen_validPtUn H/=; case: (dom_mt ns)=>_->; rewrite mem_undup I. *)
(* Qed. *)
(* Lemma mt_nodes ns : dom (dstate (empty_dstatelet ns)) =i ns. *)
(* Proof. *)
(* by case: (dom_mt ns)=>_ H2 z; rewrite -mem_undup -H2. *)
(* Qed. *)
Definition empty_dstatelet : dstatelet :=
@DStatelet (empty_lstate [::]) Unit.

Lemma valid_mt_soup : valid (dsoup empty_dstatelet).