Definition sequence_equality (net : seq_num_network) :=
    forall p p',
      In p (nwPackets net) ->
      In p' (nwPackets net) ->
      (tmNum (pBody p)) = (tmNum (pBody p')) ->
      pSrc p = pSrc p' ->
      p = p'.

(* Specifications: *)
Theorem reachable_equality : true_in_reachable step_dup step_async_init sequence_equality.
Lemma processPackets_dedup : forall processed (rest : list seq_num_packet) n' l h net, (forall p, In p rest -> In p (nwPackets net)) -> sequence_sane net -> processPackets (tdNum (nwState net h)) l = (n', processed) -> dedup pkt_eq_dec ((@send_packets _ multi_params h processed) ++ rest) = (send_packets h processed) ++ (dedup pkt_eq_dec rest).
Theorem revertNetwork_input : forall (st : seq_num_network) h (d : @data orig_base_params) l l' n, sequence_sane st -> sequence_seen st -> sequence_equality st -> processPackets (tdNum (nwState st h)) l = (n, l') -> revertNetwork (@mkNetwork _ multi_params (send_packets h l' ++ nwPackets st) (update name_eq_dec (nwState st) h (@mkseq_num_data _ orig_multi_params n (tdSeen (nwState st h)) d))) = {| nwPackets := (@send_packets _ orig_multi_params h l) ++ (nwPackets (revertNetwork st)); nwState := update name_eq_dec (nwState (revertNetwork st)) h d |}.
Lemma step_dup_star_revert_simulation : forall net tr, step_dup_star step_async_init net tr -> exists tr', step_async_star step_async_init (revertNetwork net) tr' /\ filterMap trace_non_empty_out tr = filterMap trace_non_empty_out tr'.
Theorem reachable_revert : true_in_reachable step_dup step_async_init (fun st => reachable step_async step_async_init (revertNetwork st)).
Theorem true_in_reachable_transform : forall P, true_in_reachable step_async step_async_init P -> true_in_reachable step_dup step_async_init (fun net => P (revertNetwork net)).