Section TPCProtocol.
(* Coordinator node *)
Variable cn : nid.
(* Participant nodes *)
Variable pts : seq nid.
(* Other nodes *)
Variable others : seq nid.
Hypothesis Hnin : cn \notin pts.
Hypothesis Puniq : uniq pts.
(* Local state contains the C/P state and the log *)
(* TODO: think of the open design with the possibility to refine the state *)
Definition localCoh (n : nid) : Pred heap :=
[Pred h | valid h /\
if n == cn
then exists (s : CStateT) (l : Log),
h = st :-> s \+ log :-> l
else if n \in pts
then exists (s : PStateT) (l : Log),
h = st :-> s \+ log :-> l
else log \notin dom h].
(* Involved nodes *)
Definition nodes := [:: cn] ++ pts ++ others.
Definition prep_req : nat := 0.
Definition prep_yes : nat := 1.
Definition prep_no : nat := 2.
Definition commit_req : nat := 3.
Definition abort_req : nat := 4.
Definition commit_ack : nat := 5.
Definition abort_ack : nat := 6.
(* Interaction with the clients *)
Definition eval_req : nat := 7.
Definition eval_resp : nat := 8.
Definition ttag := nat.
Definition payload := seq nat.
Definition tags : seq ttag :=
[:: prep_req;
prep_yes;
prep_no;
commit_req;
abort_req;
commit_ack;
abort_ack;
eval_req;
eval_resp].
Definition tagFromParticipant (t : nat) : bool :=
(t \in [:: prep_yes; prep_no; commit_ack; abort_ack]).
(* Messages from participants only keep current stage/era number y *)
Definition msgFromParticipant (tms : TaggedMessage) (y : nat) : bool :=
tagFromParticipant (tag tms)
&& (tms_cont tms == [:: y]).
Definition tagFromCoordinator (t : nat) : bool :=
(t \in [:: prep_req; commit_req; abort_req]).
(* Messages from coordinator contain stuff to be committed *)
Definition msgFromCoordinator (tms : TaggedMessage) (y : nat) : Prop :=
let: body := tms_cont tms in
if tag tms == prep_req
then exists data, body = y :: data
else if tag tms == commit_req
then body = [:: y]
else if tag tms == abort_req
then body = [:: y]
else False.
Definition cohMsg (ms: msg TaggedMessage) (y : nat) : Prop :=
if from ms == cn
then to ms \in pts /\ msgFromCoordinator (content ms) y
else if from ms \in pts
then to ms == cn /\ msgFromParticipant (content ms) y
else True.
Definition soupCoh : Pred soup :=
[Pred s | valid s /\
forall m ms, find m s = Some ms -> exists y, cohMsg ms y].
Definition tpc_coh d : Prop :=
let: dl := dstate d in
let: ds := dsoup d in
[/\ soupCoh ds, dom dl =i nodes,
valid dl &
forall n, n \in nodes -> localCoh n (getLocal n d)].
Definition getStC d (C : TPCCoh d) : CStateT :=
match find st (getLocal cn d) as f return _ = f -> _ with
Some v => fun epf => icast (sym_eq (cohStC C epf)) (dyn_val v)
| _ => fun epf => (0, CInit)
end (erefl _).
Program Definition getStP n d (C : TPCCoh d) (pf : n \in nodes) : PStateT.
(* Log getter *)
Definition getStL n d (C : TPCCoh d) (pf : n \in nodes) : Log :=
match find log (getLocal n d) as f return _ = f -> _ with
Some v => fun epf => icast (sym_eq (cohStL C pf epf)) (dyn_val v)
| _ => fun epf => [::]
end (erefl _).

(* TODO: get rid of duplication *)
Lemma getStL_Kc n d (C : TPCCoh d) (pf : n \in nodes) (m : CStateT) (l : Log):
getLocal n d = st :-> m \+ log :-> l -> getStL C pf = l.