Proof using out id client.
induction l; intros; simpl in *.
- find_inversion. exfalso. eapply in_output_list_empty; eauto.
- repeat break_let. find_inversion.
find_apply_lem_hyp in_output_list_app_or.
break_or_hyp.
+ break_if.
* unfold in_output_list in *.
do_in_map. find_inversion.
rewrite middle_app_assoc. apply output_correct_monotonic.
eapply cacheApplyEntry_output_correct; eauto.
* exfalso. eapply in_output_list_empty; eauto.
+ rewrite middle_app_assoc. eapply IHl.
* eauto.
* auto.
* eapply cacheApplyEntry_stateMachine_correct; eauto.
intros.
find_apply_hyp_hyp. unfold output_correct in *.
break_exists. break_and.
eexists. intuition eauto.
eapply deduplicate_log_In_if.
eauto with *.
* find_copy_apply_lem_hyp cacheApplyEntry_clientCache.
{ intros. break_or_hyp.
- break_and.
apply output_correct_monotonic.
unfold getLastId in *. repeat find_rewrite. eauto.
- break_let. break_and.
unfold getLastId in *.
repeat find_rewrite.
destruct (clientId_eq_dec (eClient a) c0).
+ subst.  rewrite get_set_same in *. find_inversion.
eapply cacheApplyEntry_output_correct; eauto.
+ rewrite get_set_diff in * by auto. eauto using output_correct_monotonic.
}
* intros.
do_in_app. simpl in *.
{ intuition.
- eapply_prop_hyp In In. break_exists. break_and. subst.
eauto using le_trans, cacheAppliedEntry_clientCache_nondecreasing.
- subst. find_copy_apply_lem_hyp cacheApplyEntry_clientCache.
intuition.
+ break_exists. break_and.
eauto using le_trans, cacheAppliedEntry_clientCache_nondecreasing.
+ unfold getLastId in *. break_let. break_and. repeat find_rewrite.
rewrite get_set_same in *. find_inversion. auto.
+ unfold getLastId in *. break_let. break_and.
repeat find_rewrite.
rewrite get_set_same in *. find_inversion. auto.
}
* intros.
do_in_app. simpl in *.
{ intuition.
- eapply_prop_hyp In In. break_exists. break_and.
find_copy_eapply_lem_hyp cacheAppliedEntry_clientCache_preserved; eauto.
break_exists_exists. intuition.
- subst. find_copy_apply_lem_hyp cacheApplyEntry_clientCache.
intuition.
+ break_exists. break_and.
find_copy_eapply_lem_hyp cacheAppliedEntry_clientCache_preserved; eauto.
break_exists_exists. intuition.
+ break_let. break_and. unfold getLastId. repeat find_rewrite.
eexists. eexists. rewrite get_set_same. intuition eauto.
+ break_let. break_and. unfold getLastId. repeat find_rewrite.
eexists. eexists. rewrite get_set_same. intuition eauto.
}
Qed.

Lemma cacheApplyEntry_spec :
forall st a l st',
cacheApplyEntry st a = (l, st') ->
log st' = log st /\
lastApplied st' = lastApplied st /\
commitIndex st' = commitIndex st.