Definition hists_mono (h1 h2 : list (hist * hist)) := Forall2 (fun a b =>
(exists l, fst b = fst a ++ l) /\ (exists l, snd b = snd a ++ l)) h1 h2.
Instance hists_mono_refl : RelationClasses.Reflexive hists_mono.
Hint Resolve hists_mono_refl.
Instance hists_mono_trans : RelationClasses.Transitive hists_mono.

(* Specifications: *)
Lemma add_item_trace_mono : forall h k v i s h', add_item_trace h k v i s h' -> hists_mono h h'.
Corollary add_items_trace_mono : forall h la h', add_items_trace h la h' ->
hists_mono h h'.
Lemma remove_last_full_hist : forall lh h j h' k v i k' i' (Hj : 0 <= j < Zlength lh) (Hh : Znth j lh [] = h)
(Hi' : 0 <= i' < Zlength h) (Hadd : add_item_trace h' k v i false h) (Hk : k <> 0) (Hrep : repable_signed k)
(Hfull : full_hist' (concat (map fst (map (fun h => Znth i' h ([], [])) lh))) k'),
full_hist' (concat (upd_Znth j (map fst (map (fun h => Znth i' h ([], [])) lh))
(fst (Znth i' h' ([], []))))) k'.
Lemma remove_last_full_hist' : forall lh h j h' k v i k' i' (Hj : 0 <= j < Zlength lh) (Hh : Znth j lh [] = h)
(Hi' : 0 <= i' < Zlength h) (Hadd : add_item_trace h' k v i true h) (Hk : k <> 0) (Hrep : repable_signed k)
(Hfull : full_hist' (concat (map fst (map (fun h => Znth i' h ([], [])) lh))) k') (Hneq : i' <> i),
full_hist' (concat (upd_Znth j (map fst (map (fun h => Znth i' h ([], [])) lh))
(fst (Znth i' h' ([], []))))) k'.
Lemma add_key_success : forall la h' t e i v (Hadd : add_items_trace empty_hists la h')
(Hin : In (t, e) (fst (Znth i h' ([], [])))) (Hval : writes e v)
(Hnzk : Forall (fun x => let '(k, _, _, _) := x in k <> 0 /\ repable_signed k) la),
exists k v', In (k, v', i, true) la /\ v = vint k /\ e = CAS (vint 0) (vint 0) (vint k) /\ repable_signed k.
Lemma add_val_success : forall la h' t e i v (Hadd : add_items_trace empty_hists la h')
(Hin : In (t, e) (snd (Znth i h' ([], [])))) (Hval : value_of e = vint v) (Hv : repable_signed v)
(Hrep : Forall (fun x => let '(_, v, _, _) := x in repable_signed v) la),
exists k, In (k, v, i, true) la /\
exists t', In (t', CAS (vint 0) (vint 0) (vint k)) (fst (Znth i h' ([], []))).
Lemma writes_val : forall i e h v v', writes e v -> apply_hist i (h ++ [e]) = Some v' -> v' = v.
Lemma apply_no_write : forall i h l v (Hl : hist_list' h l) (Hv : apply_hist i l = Some v)
(Hh : Forall (fun p => ~writes (snd p) v) h), v = i /\ Forall (fun e => forall w, ~writes e w) l.
Lemma one_CAS_succeeds : forall h v a t1 t2 b1 b2 (Hl : full_hist' h v) (Hin1 : In (t1, CAS a a b1) h)
(Hin2 : In (t2, CAS a a b2) h) (Ha : Forall (fun p => ~writes (snd p) a) h),
t1 = t2 /\ b1 = b2.
Lemma timestamp_unique : forall (h : list hist) l t e1 e2 i1 i2 (Hl : hist_list' (concat h) l)
(Ht1 : In (t, e1) (Znth i1 h [])) (Ht2 : In (t, e2) (Znth i2 h [])), i1 = i2.
Lemma add_items_Znth : forall h la h' j, add_items_trace h la h' -> 0 <= j < Zlength la ->
exists h1 h2, let '(k, v, i, s) := Znth j la (0, 0, 0, false) in
add_item_trace h1 k v i s h2 /\ hists_mono h h1 /\ hists_mono h2 h'.
Lemma one_add_succeeds : forall lr keys
(Hadd : Forall (fun '(la, h) => add_items_trace empty_hists la h) lr)
(Hfullk : Forall2 full_hist' (map fst (fold_right join_hists empty_hists (map snd lr))) (map (fun x => vint x) keys))
(Hkeys : Forall2 (fun h v => forall t e, In (t, e) h -> value_of e <> vint 0 -> vint v = value_of e)
(map fst (fold_right join_hists empty_hists (map snd lr))) keys)
(Hrepk : Forall repable_signed keys)
(Hnzk : Forall (fun x => Forall (fun x => let '(k, _, _, _) := x in k <> 0 /\ repable_signed k) (fst x)) lr)
k (Hin : In k (map fst (map fst (map fst (concat (map fst lr)))))),
exists v i th t, In (k, v, i, true) (fst (Znth th lr ([], []))) /\
In (t, CAS (vint 0) (vint 0) (vint k)) (fst (Znth i (snd (Znth th lr ([], []))) ([], []))).
Lemma only_one_add_succeeds : forall lr keys th1 th2 k v1 v2 i1 i2
(Hadd : Forall (fun '(la, h) => add_items_trace empty_hists la h) lr)
(Hfullk : Forall2 full_hist' (map fst (fold_right join_hists empty_hists (map snd lr))) (map (fun x => vint x) keys))
(Hkeys : Forall2 (fun h v => forall t e, In (t, e) h -> value_of e <> vint 0 -> vint v = value_of e)
(map fst (fold_right join_hists empty_hists (map snd lr))) keys)
(Hrepk : Forall repable_signed keys)
(Hnzk : Forall (fun x => Forall (fun x => let '(k, _, _, _) := x in k <> 0 /\ repable_signed k) (fst x)) lr)
(Hsucc1 : In (k, v1, i1, true) (fst (Znth th1 lr ([], []))))
(Hsucc2 : In (k, v2, i2, true) (fst (Znth th2 lr ([], [])))),
th1 = th2 /\ i1 = i2.