Inductive step_1 : (step_relation data (input * output)) :=
  | S1T_deliver : forall (i : input) s s' (out : output),
                    handler i s = (out, s') ->
                    step_1 s s' [(i, out)].Inductive step_1 : (step_relation data (input * output)) :=
  | S1T_deliver : forall (i : input) s s' (out : output),
                    handler i s = (out, s') ->
                    step_1 s s' [(i, out)].Definition step_1_star := refl_trans_1n_trace step_1.Inductive step_s : (step_relation data (input + output)) :=
  | SST_deliver : forall i s s' out tr,
                    input_handler i s = (out, s') ->
                    tr = inl i :: map inr out ->
                    step_s s s' tr.Inductive step_s : (step_relation data (input + output)) :=
  | SST_deliver : forall i s s' out tr,
                    input_handler i s = (out, s') ->
                    tr = inl i :: map inr out ->
                    step_s s s' tr.Definition step_s_star := refl_trans_1n_trace step_s.Record packet := mkPacket { pSrc  : name ;
                             pDst  : name ;
                             pBody : msg }.Record packet := mkPacket { pSrc  : name ;
                             pDst  : name ;
                             pBody : msg }.Record packet := mkPacket { pSrc  : name ;
                             pDst  : name ;
                             pBody : msg }.Record packet := mkPacket { pSrc  : name ;
                             pDst  : name ;
                             pBody : msg }.Record packet := mkPacket { pSrc  : name ;
                             pDst  : name ;
                             pBody : msg }.Definition send_packets src ps := (map (fun m => mkPacket src (fst m) (snd m)) ps).Definition packet_eq_dec (p q : packet) : {p = q} + {p <> q}.Record network := mkNetwork { nwPackets : list packet ;
                               nwState   : name -> data }.Record network := mkNetwork { nwPackets : list packet ;
                               nwState   : name -> data }.Record network := mkNetwork { nwPackets : list packet ;
                               nwState   : name -> data }.Record network := mkNetwork { nwPackets : list packet ;
                               nwState   : name -> data }.Definition step_async_init : network :=
    mkNetwork [] init_handlers.Inductive step_async : step_relation network (name * (input + list output)) :=
  | StepAsync_deliver : forall net net' p xs ys out d l,
      nwPackets net = xs ++ p :: ys ->
      net_handlers (pDst p) (pSrc p) (pBody p) (nwState net (pDst p)) = (out, d, l) ->
      net' = mkNetwork (send_packets (pDst p) l ++ xs ++ ys)
                       (update name_eq_dec (nwState net) (pDst p) d) ->
      step_async net net' [(pDst p, inr out)]
  (* inject a message (f inp) into host h. analogous to step_1 *delivery* *)
  | StepAsync_input : forall h net net' out inp d l,
      input_handlers h inp (nwState net h) = (out, d, l) ->
      net' = mkNetwork (send_packets h l ++ nwPackets net)
                       (update name_eq_dec (nwState net) h d) ->
      step_async net net' [(h, inl inp); (h, inr out)].Inductive step_async : step_relation network (name * (input + list output)) :=
  | StepAsync_deliver : forall net net' p xs ys out d l,
      nwPackets net = xs ++ p :: ys ->
      net_handlers (pDst p) (pSrc p) (pBody p) (nwState net (pDst p)) = (out, d, l) ->
      net' = mkNetwork (send_packets (pDst p) l ++ xs ++ ys)
                       (update name_eq_dec (nwState net) (pDst p) d) ->
      step_async net net' [(pDst p, inr out)]
  (* inject a message (f inp) into host h. analogous to step_1 *delivery* *)
  | StepAsync_input : forall h net net' out inp d l,
      input_handlers h inp (nwState net h) = (out, d, l) ->
      net' = mkNetwork (send_packets h l ++ nwPackets net)
                       (update name_eq_dec (nwState net) h d) ->
      step_async net net' [(h, inl inp); (h, inr out)].Inductive step_async : step_relation network (name * (input + list output)) :=
  | StepAsync_deliver : forall net net' p xs ys out d l,
      nwPackets net = xs ++ p :: ys ->
      net_handlers (pDst p) (pSrc p) (pBody p) (nwState net (pDst p)) = (out, d, l) ->
      net' = mkNetwork (send_packets (pDst p) l ++ xs ++ ys)
                       (update name_eq_dec (nwState net) (pDst p) d) ->
      step_async net net' [(pDst p, inr out)]
  (* inject a message (f inp) into host h. analogous to step_1 *delivery* *)
  | StepAsync_input : forall h net net' out inp d l,
      input_handlers h inp (nwState net h) = (out, d, l) ->
      net' = mkNetwork (send_packets h l ++ nwPackets net)
                       (update name_eq_dec (nwState net) h d) ->
      step_async net net' [(h, inl inp); (h, inr out)].Definition step_async_star := refl_trans_1n_trace step_async.

Lemma packet_eta : forall p : packet, {| pSrc := pSrc p; pDst := pDst p; pBody := pBody p |} = p.