Section AllEntriesLog.
Context {orig_base_params : BaseParams}.
Context {one_node_params : OneNodeParams orig_base_params}.
Context {raft_params : RaftParams orig_base_params}.
Context {llli : logs_leaderLogs_interface}.
Context {aerlli : append_entries_leaderLogs_interface}.
Context {rlmli : refined_log_matching_lemmas_interface}.
Context {aellti : allEntries_leaderLogs_term_interface}.
Context {llci : leaderLogs_contiguous_interface}.
Context {ollpti : one_leaderLog_per_term_interface}.
Context {llsi : leaderLogs_sorted_interface}.
Context {tsi : term_sanity_interface}.
Context {rri : raft_refinement_interface}.
Context {aetsi : allEntries_term_sanity_interface}.
(* strategy : prove allEntries_log as inductive invariant, then prove allEntries_leaderLogs inductive from that *)
Definition no_entries_past_current_term_host_lifted net :=
forall (h : name) e,
In e (log (snd (nwState net h))) ->
eTerm e <= currentTerm (snd (nwState net h)).
Proof using rri tsi.
unfold no_entries_past_current_term_host_lifted.
pose proof deghost_spec.
do 4 intro.
repeat find_reverse_higher_order_rewrite.
eapply lift_prop; eauto.
intros.
find_apply_lem_hyp no_entries_past_current_term_invariant; eauto.
Qed.
(** Succeed iff [x] is in the list [ls], represented with left-associated nested tuples. *)
Ltac inList x ls :=
match ls with
| x => idtac
| (_, x) => idtac
| (?LS, _) => inList x LS
end.
(** Try calling tactic function [f] on every element of tupled list [ls], keeping the first call not to fail. *)
Ltac app f ls :=
match ls with
| (?LS, ?X) => f X || app f LS || fail 1
| _ => f ls
end.
(** Run [f] on every element of [ls], not just the first that doesn't fail. *)
Ltac all f ls :=
match ls with
| (?LS, ?X) => f X; all f LS
| (_, _) => fail 1
| _ => f ls
end.
Proof using rlmli.
intros.
unfold haveNewEntries in *. do_bool. intuition;
[unfold not_empty in *; break_match; subst; simpl in *; intuition; congruence|].
break_match; try congruence.
do_bool. find_apply_lem_hyp findAtIndex_elim. intuition.
assert (es <> nil) by (destruct es; subst; simpl in *; intuition; congruence).
find_eapply_lem_hyp maxIndex_non_empty.
break_exists. intuition.
find_copy_eapply_lem_hyp entries_sorted_nw_invariant; eauto.
match goal with
| H : In e es |- _ => copy_eapply maxIndex_is_max H; eauto
end.
repeat find_rewrite.
find_eapply_lem_hyp entries_match_nw_host_invariant; eauto.
Qed.
Proof using.
intros. destruct l2; intuition.
simpl in *. right.
destruct l1; intuition.
find_copy_eapply_lem_hyp findAtIndex_None; simpl in *; eauto.
unfold contiguous_range_exact_lo in *.
simpl in *. intuition.
destruct (lt_eq_lt_dec 0 (eIndex e)); intuition; eauto.
destruct (lt_eq_lt_dec (eIndex e0) (eIndex e)); intuition.
exfalso. repeat break_if; do_bool; intuition.
match goal with
| H : forall _, _ < _ <= _ -> _ |- _ =>
specialize (H (eIndex e))
end; conclude_using lia.
simpl in *. break_exists. intuition; subst; intuition.
eapply findAtIndex_None; eauto.
Qed.
Proof using.
intros. find_eapply_lem_hyp maxIndex_le; intuition; eauto.
break_exists. intuition.
unfold contiguous_range_exact_lo in *.
intuition.
find_insterU. conclude_using eauto. lia.
Qed.
Proof using.
induction l1; intros; simpl in *; intuition; eauto.
subst. find_insterU. conclude_using ltac:(apply in_app_iff; intuition eauto).
intuition.
Qed.

Lemma sorted_app_sorted_app_in1_in2 :
forall l1 l2 l3 e e',
sorted (l1 ++ l3) ->
sorted (l2 ++ l3) ->
In e l1 ->
In e' (l2 ++ l3) ->
eIndex e' = eIndex e ->
In e' l2.