Class GhostMultiParams `(P : MultiParams) :=
  {
    ghost_data : Type;
    ghost_init : ghost_data ;
    ghost_net_handlers :
      name -> name -> msg -> (ghost_data * data) -> ghost_data;
    ghost_input_handlers :
      name -> input -> (ghost_data * data) -> ghost_data
  }.Class GhostMultiParams `(P : MultiParams) :=
  {
    ghost_data : Type;
    ghost_init : ghost_data ;
    ghost_net_handlers :
      name -> name -> msg -> (ghost_data * data) -> ghost_data;
    ghost_input_handlers :
      name -> input -> (ghost_data * data) -> ghost_data
  }.Class GhostMultiParams `(P : MultiParams) :=
  {
    ghost_data : Type;
    ghost_init : ghost_data ;
    ghost_net_handlers :
      name -> name -> msg -> (ghost_data * data) -> ghost_data;
    ghost_input_handlers :
      name -> input -> (ghost_data * data) -> ghost_data
  }.Class GhostMultiParams `(P : MultiParams) :=
  {
    ghost_data : Type;
    ghost_init : ghost_data ;
    ghost_net_handlers :
      name -> name -> msg -> (ghost_data * data) -> ghost_data;
    ghost_input_handlers :
      name -> input -> (ghost_data * data) -> ghost_data
  }.Class GhostMultiParams `(P : MultiParams) :=
  {
    ghost_data : Type;
    ghost_init : ghost_data ;
    ghost_net_handlers :
      name -> name -> msg -> (ghost_data * data) -> ghost_data;
    ghost_input_handlers :
      name -> input -> (ghost_data * data) -> ghost_data
  }.Definition refined_net_handlers me src m st :=
  let '(out, st', ps) :=
      net_handlers me src m (snd st) in
  (out, (ghost_net_handlers me src m st, st'), ps).Definition refined_input_handlers me inp st :=
  let '(out, st', ps) := input_handlers me inp (snd st) in
  (out, (ghost_input_handlers me inp st, st'), ps).Definition refined_init_handlers (n : name) : ghost_data * data :=
  (ghost_init, init_handlers n).Definition refined_reboot (st : ghost_data * data) :=
  (fst st , reboot (snd st)).Instance refined_base_params : BaseParams :=
  {
    data := (ghost_data * data)%type ;
    input := input ;
    output := output
  }.Instance refined_multi_params : MultiParams _ :=
  {
    name := name ;
    msg := msg ;
    msg_eq_dec := msg_eq_dec ;
    name_eq_dec := name_eq_dec ;
    nodes := nodes ;
    all_names_nodes := all_names_nodes ;
    no_dup_nodes := no_dup_nodes ;
    init_handlers := refined_init_handlers;
    net_handlers := refined_net_handlers ;
    input_handlers := refined_input_handlers
  }.Instance refined_failure_params : FailureParams _ :=
  {
    reboot := refined_reboot
  }.Definition deghost_packet p :=
  @mkPacket _ multi_params
            (@pSrc _ refined_multi_params p)
            (pDst p)
            (pBody p).Definition deghost (net : @network _ refined_multi_params) : (@network _ multi_params).Definition deghost_prop I (failed_net : list name * network) : Prop :=
  I ((fst failed_net), deghost (snd failed_net)).Instance refined_base_params_tot_map :
 BaseParamsTotalMap refined_base_params base_params :=
  {
    tot_map_data := snd ;
    tot_map_input := id ;
    tot_map_output := id
  }.Instance refined_multi_params_name_tot_map :
 MultiParamsNameTotalMap refined_multi_params multi_params :=
  {
    tot_map_name := id ;
    tot_map_name_inv := id
  }.Instance refined_multi_params_name_tot_map_bijective :
 MultiParamsNameTotalMapBijective refined_multi_params_name_tot_map :=
  {
    tot_map_name_inv_inverse := fun _ => eq_refl ;
    tot_map_name_inverse_inv := fun _ => eq_refl
  }.Instance refined_multi_params_tot_msg_map :
 MultiParamsMsgTotalMap refined_multi_params multi_params :=
  {
    tot_map_msg := id
  }.Program Instance refined_multi_params_map_congruency :
 MultiParamsTotalMapCongruency refined_base_params_tot_map
  refined_multi_params_name_tot_map refined_multi_params_tot_msg_map :=
  {
    tot_init_handlers_eq := fun _ => eq_refl ;
    tot_net_handlers_eq := _ ;
    tot_input_handlers_eq := _
  }.Instance refined_failure_params_map_congruency :
 FailureParamsTotalMapCongruency refined_failure_params
  failure_params refined_base_params_tot_map :=
  {
    tot_reboot_eq := fun _ => eq_refl
  }.

Theorem ghost_simulation_2 : forall net net' failed failed' out gnet, @step_failure _ _ failure_params (failed, net) (failed', net') out -> deghost gnet = net -> exists gnet', step_failure (failed, gnet) (failed', gnet') out /\ deghost gnet' = net'.