Proof using lmi smsi misi si.
red. unfold client_cache_correct in *. simpl in *. intros. subst.
find_higher_order_rewrite.
destruct_update; simpl in *; eauto.
repeat find_rewrite. find_apply_lem_hyp doGenericServer_spec.
intuition; repeat find_rewrite; eauto.
get_invariant_pre logs_sorted_invariant. unfold logs_sorted in *. intuition.
erewrite removeAfterIndex_app; eauto.
break_exists. intuition.
find_higher_order_rewrite.
find_eapply_lem_hyp applyEntries_execute_log'_cache; eauto. intuition.
- find_apply_hyp_hyp.
rewrite rev_app_distr.
eauto using output_correct_monotonic.
- unfold output_correct. break_exists. intuition.
rewrite rev_app_distr.
unfold deduplicate_log.
rewrite deduplicate_log'_app.
match goal with
| _ : context [execute_log' ?x ?y] |- _ =>
destruct (execute_log' x y) eqn:?
end.
simpl in *.
match goal with
| [ H : deduplicate_log' _ _ = ?xs ++ ?e :: ?ys |-
context [?l ++ deduplicate_log' _ _] ] =>
(exists (l ++ xs), e, ys)
end.
unfold execute_log.
repeat rewrite app_ass.
rewrite execute_log'_app.
break_let.
get_invariant_pre state_machine_log_invariant.
unfold state_machine_log in *.
repeat find_higher_order_rewrite.
unfold execute_log, deduplicate_log in *.
repeat find_rewrite. simpl in *.
match goal with
| [ H : execute_log' (_ ++ _) _ _ = (?tr, ?st) |-
context [execute_log' _ _ ?tr'] ] =>
(exists (tr' ++ tr), st)
end.
intuition.
+ f_equal.
repeat find_reverse_rewrite.
match goal with
| H : deduplicate_log' _ _ = _ ++ _ :: _ |- _ =>
clear H
end.
match goal with
| |- _ ?l _ = _ ?l' _ =>
assert (l = l') by
(f_equal; apply filter_fun_ext_eq;
intros;
repeat find_rewrite;
rewrite <- Bool.andb_true_l at 1;
f_equal;
symmetry; apply Nat.ltb_lt;
find_apply_lem_hyp findGtIndex_necessary; intuition)
end.
repeat find_rewrite.
apply deduplicate_log'_a_equiv.
apply a_equiv_sym.
apply client_cache_keys_correct_invariant; auto.
+ eauto using execute_log'_trace_nil.
+ rewrite rev_app_distr.
erewrite hd_error_Some_app; eauto.
Qed.

Lemma same_clientCache_same_getLastId :
forall st st' k,
clientCache st = clientCache st' ->
getLastId st k = getLastId st' k.