Proof using.
intros. simpl in *.
rewrite dedup_app; f_equal.
- apply dedup_NoDup_id.
apply NoDup_map_injective; eauto using processPackets_NoDup.
intros. find_inversion.
rewrite surjective_pairing at 1.
rewrite surjective_pairing.
unfold msg in *. simpl in *.
repeat find_rewrite. auto.
- intuition.
subst.
find_apply_lem_hyp in_map_iff. break_exists. intuition.
find_eapply_lem_hyp processPackets_ge_start; eauto.
match goal with
| _ : In ?p _, net : network |- _ =>
assert (In p (nwPackets net)) by eauto
end.
unfold sequence_sane in *.
find_apply_hyp_hyp. simpl in *. subst. simpl in *. omega.
Qed.

(* Specifications: *)
Lemma revertNetwork_deliver_step :
forall (st : seq_num_network) p xs ys (d : @data orig_base_params) l l' n,
sequence_sane st ->
sequence_seen st ->
sequence_equality st ->
nwPackets st = xs ++ p :: ys ->
~ In (tmNum (pBody p)) (assoc_default name_eq_dec (tdSeen (nwState st (pDst p))) (pSrc p) []) ->
processPackets (tdNum (nwState st (pDst p))) l = (n, l') ->
exists xs' ys',
nwPackets (revertNetwork st) = xs' ++ revertPacket p :: ys' /\
revertNetwork
(@mkNetwork _ multi_params
(map
(fun m : name * seq_num_msg =>
{| pSrc := pDst p; pDst := fst m; pBody := snd m |})
l' ++ xs ++ ys)
(update name_eq_dec (nwState st) (pDst p)
(@mkseq_num_data _ orig_multi_params
n
(assoc_set name_eq_dec
(tdSeen (nwState st (pDst p))) (pSrc p)
(tmNum (pBody p) :: assoc_default name_eq_dec (tdSeen (nwState st (pDst p))) (pSrc p) []))
d)))
= {|
nwPackets := (@send_packets _ orig_multi_params (pDst p) l) ++ xs' ++ ys';
nwState := update name_eq_dec (nwState (revertNetwork st)) (pDst p) d
|}.