Proof using.
intros.
invc H; simpl; break_match; auto;
repeat rewrite app_nil_r in *;
simpl in *;
try find_apply_lem_hyp PB_net_defn;
try find_apply_lem_hyp PB_input_handler_defn;
intuition; subst.
- rewrite inputs_m_inr_singleton.
rewrite update_eq by auto.
auto.
- rewrite inputs_m_inr_singleton.
rewrite update_eq by auto.
auto.
- break_exists. intuition; break_match.
+ intuition. subst.
rewrite inputs_m_inr_singleton. simpl. eauto.
+ break_exists.  intuition. subst.
rewrite inputs_m_inr_singleton. simpl. eauto.
- rewrite inputs_m_inr_singleton.
rewrite update_diff by auto. auto.
- rewrite inputs_m_inr_singleton.
rewrite update_diff by auto. auto.
- break_exists. intuition; subst; rewrite inputs_m_primary_inl; eauto.
- rewrite inputs_m_inl_read. rewrite update_eq by auto. auto.
- rewrite inputs_m_inl_read. rewrite update_diff by auto. auto.
- rewrite inputs_m_backup.
rewrite update_diff by auto. auto.
Qed.
Definition network_invariant (net : @network _ PB_multi_params) : Prop :=
(nwPackets net = [] /\ state (nwState net Primary) = state (nwState net Backup)) \/
(exists i is, nwPackets net = [mkPacket Primary Backup (BackItUp i)] /\
queue (nwState net Primary) = i :: is /\
state (nwState net Primary) = state (nwState net Backup)) \/
(nwPackets net = [mkPacket Backup Primary Ack] /\
exists i is, queue (nwState net Primary) = i :: is /\
snd (handler i (state (nwState net Primary))) = state (nwState net Backup)).
Ltac prep := subst; simpl in *; try find_inversion; repeat find_rewrite; simpl in *.
Ltac workhorse :=
repeat (prep;
match goal with
| [ H : _ /\ _ |- _ ] => break_and
| [ H : exists _, _ |- _ ] => break_exists
| [ H : _ ++ _ :: _ = [] |- _ ] => solve [exfalso; eapply app_cons_not_nil; eauto]
| [ H : _ ++ _ :: _ = [ _ ] |- _ ] => apply app_cons_singleton_inv in H
| [ H : context [ let (_,_) := ?X in _ ] |- _ ] => destruct X eqn:?
| [ |- context [ let (_,_) := ?X in _ ] ] => destruct X eqn:?
| [ |- context [ update _ (nwState ?net) ?x (nwState ?net ?x) _ ] ] => rewrite update_nop
| [ |- context [ update _ _ ?x _ ?x ] ] => rewrite update_eq by auto
| [ |- context [ update _ _ ?x _ ?y ] ] => rewrite update_diff by auto
| [ H : _ \/ _ |- _ ] => invc H
end); prep.

(* Specifications: *)
Lemma network_invariant_inductive :
forall net net' tr,
step_async net net' tr ->
network_invariant net ->
network_invariant net'.