Section inner.
Variable client : clientId.
Variables id : nat.
Variable out : output.
Proof using.
unfold in_output_trace.
intros.
destruct (find (fun p => match snd p with
| inr l => match find (is_client_response client id out) l with
| Some x => true
| None => false
end
| _ => false
end) tr) eqn:?.
- find_apply_lem_hyp find_some. break_and.
repeat break_match; try discriminate.
find_apply_lem_hyp find_some. break_and.
unfold is_client_response, in_output_list in *.
break_match; try discriminate. break_if; try discriminate. do_bool. break_and. do_bool. subst.
left. exists l, (fst p). clean.
break_and. do_bool.
break_if; try congruence. subst. intuition.
find_reverse_rewrite.
rewrite <- surjective_pairing.
auto.
- right. intro. break_exists. break_and.
eapply find_none in Heqo; eauto.
simpl in *. break_match; try discriminate.
unfold in_output_list in *. break_exists.
find_eapply_lem_hyp find_none; eauto.
simpl in *. find_apply_lem_hyp Bool.andb_false_elim.
break_if; repeat (intuition; do_bool).
break_if; congruence.
Qed.
Proof using.
intros. unfold in_output_trace in *.
break_exists_exists.
intuition. do_in_app; intuition.
exfalso. eauto.
Qed.
Proof using.
intros.
unfold in_output_list in *.
break_exists; do_in_app; intuition eauto.
Qed.
Proof using.
intuition.
Qed.
Proof using.
intros. unfold doLeader, advanceCommitIndex in *.
repeat break_match; find_inversion; intuition eauto using key_in_output_list_empty.
Qed.
Proof using.
intros. unfold handleInput, handleTimeout, handleClientRequest, tryToBecomeLeader in *.
repeat break_match; find_inversion; intuition eauto using in_output_list_empty;
unfold in_output_list in *; break_exists; simpl in *; intuition; congruence.
Qed.
Proof using.
induction l; intros; simpl in *; intuition; eauto.
repeat break_match; simpl in *; eauto;
repeat find_insterU; break_exists; eexists; f_equal; eauto.
Qed.
Proof using.
eauto using deduplicate_log'_app.
Qed.
Proof using.
unfold in_output_trace.
simpl. intros. break_exists. intuition.
Qed.
Proof using.
unfold in_output_trace.
intuition.
break_exists. simpl in *. intuition.
find_inversion. auto.
Qed.
Proof using.
unfold in_output_list.
intuition.
Qed.
Proof using.
unfold in_output_trace.
intuition. break_exists_exists. simpl in *. intuition.
find_inversion.
Qed.
Proof using.
unfold in_output_list. simpl. intuition. discriminate.
Qed.
Proof using.
unfold handleInput, handleTimeout, handleInput, tryToBecomeLeader, handleClientRequest.
intuition.
repeat break_match; repeat find_inversion; eauto using in_output_trace_not_nil.
- exfalso. eapply in_output_list_not_leader_singleton; eauto.
- exfalso. eapply in_output_list_not_leader_singleton; eauto.
Qed.
Proof using.
unfold in_output_list.
simpl. intuition.
find_inversion. auto.
Qed.
Proof using.
induction l; simpl; intros; repeat break_match.
- discriminate.
- find_inversion. auto.
- intuition.
Qed.
Proof using.
unfold getLastId.
eauto using assoc_Some_In.
Qed.
Proof using.
induction xs; intros; simpl; auto using f_equal.
Qed.
Proof using.
induction es; simpl; intuition; repeat break_match; repeat find_inversion; do_bool.
- lia.
- auto.
- discriminate.
- f_equal. destruct (clientId_eq_dec (eClient a) (eClient e)).
+ repeat find_rewrite. find_injection.
eapply IHes with (n := eId a); auto with *.
now rewrite get_set_same.
+ eapply IHes; eauto.
rewrite get_set_diff by auto. auto.
- eauto.
- f_equal. destruct (clientId_eq_dec (eClient a) (eClient e)).
+ repeat find_rewrite. discriminate.
+ eapply IHes; eauto.
rewrite get_set_diff by auto. auto.
Qed.
Proof using.
induction es; simpl; intuition; repeat break_match; eauto using f_equal;
repeat find_reverse_rewrite.
- f_equal. subst. eapply deduplicate_log'_snoc_drop_keys; eauto.
now rewrite get_set_same.
- subst. do_bool. eapply deduplicate_log'_snoc_drop_keys; eauto; auto with *.
- f_equal. subst. eapply deduplicate_log'_snoc_drop_keys; eauto.
now rewrite get_set_same.
Qed.
Proof using.
intros. eapply deduplicate_log'_snoc_drop_es; eauto.
Qed.

Lemma deduplicate_log'_snoc_split :
forall es ks e,
(forall e', In e' es -> eClient e' = eClient e -> eId e' < eId e) ->
(forall i, assoc clientId_eq_dec ks (eClient e) = Some i -> i < eId e) ->
deduplicate_log' (es ++ [e]) ks = deduplicate_log' es ks ++ [e].