Definition strict_prefix_history {ora: RandomOracle} (h1 h2: RandomHistory): Prop :=
prefix_history h1 h2 /\ exists n, h1 n <> h2 n.
Definition n_bounded_prefix_history {ora: RandomOracle} (m: nat) (h1 h2: RandomHistory): Prop :=
forall n, (h1 n = None /\ h2 (n + m) = None) \/ h1 n = h2 n.
Definition n_conflict_history {ora: RandomOracle} (n: nat) (h1 h2: RandomHistory): Prop :=
match h1 n, h2 n with
| Some a1, Some a2 => projT1 a1 <> projT1 a2
| Some _, None => True
| None, Some _ => True
| None, None => False
end.
Definition conflict_history {ora: RandomOracle} (h1 h2: RandomHistory): Prop :=
exists n, history_coincide n h1 h2 /\ n_conflict_history n h1 h2.
Definition strict_conflict_history {ora: RandomOracle} (h1 h2: RandomHistory): Prop :=
exists n,
history_coincide n h1 h2 /\
match h1 n, h2 n with
| Some a1, Some a2 => projT1 a1 <> projT1 a2
| _, _ => False
end.

(* Specifications: *)
Lemma history_coincide_sym {ora: RandomOracle}: forall h1 h2 n,
history_coincide n h1 h2 ->
history_coincide n h2 h1.
Lemma n_conflict_history_sym {ora: RandomOracle}: forall h1 h2 n,
n_conflict_history n h1 h2 ->
n_conflict_history n h2 h1.
Lemma conflict_history_sym {ora: RandomOracle}: forall h1 h2,
conflict_history h1 h2 ->
conflict_history h2 h1.
Lemma strict_conflict_history_sym {ora: RandomOracle}: forall h1 h2,
strict_conflict_history h1 h2 ->
strict_conflict_history h2 h1.
Lemma history_coincide_trans {ora: RandomOracle}: forall h1 h2 h3 n,
history_coincide n h1 h2 ->
history_coincide n h2 h3 ->
history_coincide n h1 h3.
Lemma is_0_history_non_conflict {ora: RandomOracle}: forall h1 h2,
is_n_history 0 h1 ->
is_n_history 0 h2 ->
conflict_history h1 h2 ->
False.
Lemma fstn_history_Some {ora: RandomOracle}: forall n m h, m < n -> (fstn_history n h) m = h m.
Lemma fstn_history_None {ora: RandomOracle}: forall n m h, n <= m -> (fstn_history n h) m = None.
Lemma history_coincide_weaken {ora: RandomOracle}: forall n m h1 h2,
n <= m ->
history_coincide m h1 h2 ->
history_coincide n h1 h2.
Lemma is_n_history_None {ora: RandomOracle}: forall n m h, n <= m -> is_n_history n h -> h m = None.
Lemma fstn_history_is_n_history {ora: RandomOracle}: forall n m h,
m <= n ->
is_n_history n h ->
is_n_history m (fstn_history m h).
Lemma fstn_history_coincide {ora: RandomOracle}: forall n h,
history_coincide n h (fstn_history n h).
Lemma prefix_history_refl {ora: RandomOracle}: forall h, prefix_history h h.
Lemma prefix_history_trans {ora: RandomOracle}: forall h1 h2 h3, prefix_history h1 h2 -> prefix_history h2 h3 -> prefix_history h1 h3.
Lemma prefix_history_anti_sym {ora: RandomOracle}: forall h1 h2, prefix_history h1 h2 -> prefix_history h2 h1 -> h1 = h2.
Lemma prefix_history_comparable {ora: RandomOracle}: forall h1 h2 h, prefix_history h1 h -> prefix_history h2 h -> prefix_history h1 h2 \/ prefix_history h2 h1.
Lemma conflict_history_strict_conflict {ora: RandomOracle}: forall h h',
is_inf_history h ->
conflict_history h' h ->
prefix_history h' h \/ strict_conflict_history h' h.
Lemma fstn_history_finite {ora: RandomOracle}: forall n h, is_fin_history (fstn_history n h).
Lemma fstn_history_prefix {ora: RandomOracle}: forall n h, prefix_history (fstn_history n h) h.
Lemma n_conflict_at_least_n_history1 {ora: RandomOracle}: forall n h1 h2,
history_coincide n h1 h2 ->
n_conflict_history n h1 h2 ->
is_at_least_n_history n h1.
Lemma n_conflict_at_least_n_history2 {ora: RandomOracle}: forall n h1 h2,
history_coincide n h1 h2 ->
n_conflict_history n h1 h2 ->
is_at_least_n_history n h2.
Lemma prefix_history_coincide {ora: RandomOracle}: forall n h1 h2,
prefix_history h1 h2 ->
is_at_least_n_history n h1 ->
history_coincide n h1 h2.
Lemma is_at_least_n_history_fstn_history {ora: RandomOracle}: forall n m h, n <= m -> (is_at_least_n_history n (fstn_history m h) <-> is_at_least_n_history n h).
Lemma n_conflict_proper_aux_right {ora: RandomOracle}: forall n h1 h2 h3,
history_coincide (S n) h2 h3 ->
(history_coincide n h1 h2 /\ n_conflict_history n h1 h2 <->
history_coincide n h1 h3 /\ n_conflict_history n h1 h3).
Lemma n_conflict_proper_aux_left {ora: RandomOracle}: forall n h1 h2 h3,
history_coincide (S n) h2 h3 ->
(history_coincide n h2 h1 /\ n_conflict_history n h2 h1 <->
history_coincide n h3 h1 /\ n_conflict_history n h3 h1).
Lemma n_conflict_proper_aux {ora: RandomOracle}: forall n l1 l2 r1 r2,
history_coincide (S n) l1 l2 ->
history_coincide (S n) r1 r2 ->
(history_coincide n l1 r1 /\ n_conflict_history n l1 r1 <->
history_coincide n l2 r2 /\ n_conflict_history n l2 r2).
Lemma squeeze_history_coincide {ora: RandomOracle}: forall n h1 h2,
prefix_history (fstn_history n h1) h2 ->
prefix_history h2 h1 ->
history_coincide n h1 h2.
Lemma strict_conflict_prefix_conflict_left {ora: RandomOracle}: forall h h1 h2,
strict_conflict_history h2 h ->
prefix_history h1 h2 ->
conflict_history h1 h.
Lemma strict_conflict_prefix_conflict_right {ora: RandomOracle}: forall h h1 h2,
strict_conflict_history h h2 ->
prefix_history h1 h2 ->
conflict_history h h1.
Lemma strict_conflict_prefix_left {ora: RandomOracle}: forall h h1 h2,
strict_conflict_history h2 h ->
prefix_history h1 h2 ->
prefix_history h1 h \/ strict_conflict_history h1 h.
Lemma strict_conflict_prefix_right {ora: RandomOracle}: forall h h1 h2,
strict_conflict_history h h2 ->
prefix_history h1 h2 ->
prefix_history h1 h \/ strict_conflict_history h h1.