Section SpecLemmas.
Context {orig_base_params : BaseParams}.
Context {one_node_params : OneNodeParams orig_base_params}.
Context {raft_params : RaftParams orig_base_params}.
Proof using.
intros. unfold handleRequestVote, advanceCurrentTerm in *.
repeat break_match; tuple_inversion; simpl in *; intuition; try discriminate;
try solve [exfalso; do_bool; lia].
Qed.
Proof using.
unfold handleRequestVote.
intros.
repeat break_match; repeat find_inversion; intuition idtac.
- simpl in *. discriminate.
- unfold advanceCurrentTerm in *.
break_if; simpl in *; do_bool; intuition.
Qed.
Proof using.
intros.
unfold handleRequestVoteReply, advanceCurrentTerm in *; repeat break_match;
subst; do_bool; intuition.
Qed.
Proof using.
unfold handleAppendEntries, advanceCurrentTerm.
intros.
repeat break_match; repeat tuple_inversion; simpl in *;
do_bool; auto; try lia.
Qed.
Proof using.
intros. unfold handleAppendEntriesReply, advanceCurrentTerm in *.
repeat break_match; repeat tuple_inversion; simpl in *; do_bool; congruence.
Qed.
Proof using.
unfold doGenericServer.
intros.
repeat break_match; repeat find_inversion;
use_applyEntries_spec; subst; simpl in *;
auto.
Qed.
Proof using.
intros. unfold doLeader in *.
repeat break_match; find_inversion; auto.
Qed.
Proof using.
intros. unfold handleAppendEntriesReply, advanceCurrentTerm in *.
repeat break_match; tuple_inversion; do_bool; simpl; auto; lia.
Qed.
Proof using.
intros. unfold handleAppendEntries, advanceCurrentTerm in *.
repeat break_match; find_inversion; do_bool; auto.
Qed.
Proof using.
unfold tryToBecomeLeader.
intros.
find_inversion. simpl.
auto with arith.
Qed.
Proof using.
unfold handleTimeout.
intros.
break_match; eauto using tryToBecomeLeader_currentTerm.
find_inversion. simpl.
auto with arith.
Qed.
Proof using.
intros. unfold haveNewEntries, not_empty in *.
do_bool. intuition. repeat break_match; congruence.
Qed.
Proof using.
intros.
unfold advanceCurrentTerm. break_if; simpl in *; auto.
Qed.
Proof using.
intros. unfold handleAppendEntries in *.
break_if; [find_inversion; subst; eauto|].
break_if;
[do_bool; break_if; find_inversion; subst;
try find_apply_lem_hyp haveNewEntries_not_empty; intuition; simpl in *;
eauto using advanceCurrentTerm_log|].
break_if.
- break_match; [|find_inversion; subst; eauto].
break_if; [find_inversion; subst; eauto|].
find_inversion; subst; simpl in *.
right. right.
find_apply_lem_hyp findAtIndex_elim. intuition; do_bool; eauto.
find_apply_lem_hyp haveNewEntries_not_empty. congruence.
- repeat break_match; find_inversion; subst; eauto.
simpl in *. eauto using advanceCurrentTerm_log.
Qed.
Proof using.
intros.
find_apply_lem_hyp handleAppendEntries_log.
intuition; subst; try find_rewrite; auto.
break_exists. intuition eauto.
Qed.
Proof using.
intros.
unfold haveNewEntries, not_empty in *.
repeat break_match; do_bool; intuition eauto; try congruence.
do_bool. eauto.
Qed.
Proof using.
intros.
unfold advanceCurrentTerm. break_if; simpl in *; auto.
Qed.
Proof using.
congruence.
Qed.
Proof using.
intros. unfold advanceCurrentTerm in *.
break_if; do_bool; intuition.
Qed.

Theorem handleAppendEntries_log_detailed :
forall h st t n pli plt es ci st' ps,
handleAppendEntries h st t n pli plt es ci = (st', ps) ->
(commitIndex st' = commitIndex st /\ log st' = log st) \/
(leaderId st' <> None /\
currentTerm st' = t /\
commitIndex st' = max (commitIndex st) (min ci (maxIndex es)) /\
es <> nil /\
pli = 0 /\ t >= currentTerm st /\ log st' = es /\
(findAtIndex (log st) (maxIndex es) = None \/
exists e,
findAtIndex (log st) (maxIndex es) = Some e /\
eTerm e <> maxTerm es)) \/
(leaderId st' <> None /\
currentTerm st' = t /\
commitIndex st' = max (commitIndex st)
(min ci (maxIndex (es ++ (removeAfterIndex (log st) pli)))) /\
es <> nil /\
exists e,
In e (log st) /\
eIndex e = pli /\
eTerm e = plt) /\
t >= currentTerm st /\
log st' = es ++ (removeAfterIndex (log st) pli) /\
(findAtIndex (log st) (maxIndex es) = None \/
exists e,
findAtIndex (log st) (maxIndex es) = Some e /\
eTerm e <> maxTerm es).