Proof using.
intros.
unfold revertNetwork.
simpl in *.
match goal with
[ |- context [ dedup ?eq (map ?f ?l ++ ?l') ] ] =>
assert (dedup eq (map f l ++ l') = (map f l) ++ (dedup eq l'))
by (find_eapply_lem_hyp processPackets_dedup;
eauto; repeat find_rewrite; in_crush)
end.
find_rewrite.
rewrite filter_app. rewrite map_app. f_equal. f_equal.
- rewrite filter_true_id.
+ match goal with
| _ : processPackets ?n ?l = _ |- _ =>
rewrite <- (processPackets_preserves_messages n l)
end.
find_rewrite. simpl in *.
unfold revertPacket.
repeat rewrite map_map. auto.
+ intros.
in_crush.
find_eapply_lem_hyp processPackets_ge_start; [|eauto].
repeat (break_if; simpl in *; repeat find_rewrite; intuition);
unfold sequence_seen in *; find_apply_hyp_hyp; omega.
- f_equal. apply filter_fun_ext_eq.
intros. repeat (break_if; simpl in *; repeat find_rewrite; intuition).
- apply functional_extensionality. intros; repeat break_if; simpl in *; intuition.
Qed.
(* We need this for dedup_eliminates_duplicates *)
Arguments dedup _ _ _ : simpl nomatch.

(* Specifications: *)
Lemma reachable_revert_step :
forall st st' tr,
reachable step_dup step_async_init st ->
step_dup st st' tr ->
step_async (revertNetwork st) (revertNetwork st') tr \/
(revertNetwork st = revertNetwork st' /\ filterMap trace_non_empty_out tr = []).