Proof using.
intros.
induction H10.
- intuition.
-  match goal with [H : step_failure _ _ _ |- _ ] => invcs H end.
+ unfold refined_net_handlers in *. simpl in *.
unfold RaftNetHandler, update_elections_data_net in *.
repeat break_let.
repeat find_inversion.
assert
(refined_raft_intermediate_reachable
{|
nwPackets := (xs ++ ys) ++ send_packets (pDst p) l2;
nwState := update name_eq_dec (nwState net) (pDst p)
(update_elections_data_net (pDst p)
(pSrc p)
(pBody p)
(nwState net (pDst p)), r0) |})
by (eapply RRIR_handleMessage; eauto; in_crush).
assert
(refined_raft_intermediate_reachable
{|
nwPackets := ((xs ++ ys)
++ send_packets (pDst p) l2)
++ send_packets (pDst p) l3 ;
nwState := update name_eq_dec
(nwState
{|
nwPackets := (xs ++ ys) ++ send_packets (pDst p) l2;
nwState := update name_eq_dec
(nwState net)
(pDst p)
(update_elections_data_net
(pDst p) (pSrc p)
(pBody p) (nwState net (pDst p)), r0) |})
(pDst p)
(update_elections_data_net (pDst p)
(pSrc p) (pBody p) (nwState net (pDst p)), r1) |})
by
(eapply RRIR_doLeader; eauto;
[simpl in *; break_if; try congruence; eauto| in_crush]).
eapply_prop refined_raft_net_invariant_do_generic_server. eauto.
eapply_prop refined_raft_net_invariant_do_leader. eauto.
eapply refined_raft_invariant_handle_message with (P := P); eauto using in_app_or.
auto.
simpl. break_if; intuition eauto.
eauto.
simpl. eapply in_app_or. auto.
simpl. break_if; eauto; congruence.
simpl. intros.
break_if; subst;
repeat rewrite update_same by auto;
repeat rewrite update_neq by auto; auto.
simpl. in_crush.
+ unfold refined_input_handlers in *. simpl in *.
unfold RaftInputHandler, update_elections_data_input in *. repeat break_let.
repeat find_inversion.
assert
(refined_raft_intermediate_reachable
{|
nwPackets := nwPackets net ++ send_packets h l2;
nwState := update name_eq_dec (nwState net) h
(update_elections_data_input h
inp
(nwState net h), r0) |})
by (eapply RRIR_handleInput; eauto; in_crush).
assert
(refined_raft_intermediate_reachable
{|
nwPackets := (nwPackets net
++ send_packets h l2)
++ send_packets h l4 ;
nwState := update name_eq_dec
(nwState
{|
nwPackets := nwPackets net ++ send_packets h l2;
nwState := update name_eq_dec
(nwState net)
h
(update_elections_data_input h inp
(nwState net h), r0) |})
h
(update_elections_data_input h inp (nwState net h), r1) |})
by
(eapply RRIR_doLeader; eauto;
[simpl in *; break_if; try congruence; eauto| in_crush]).
eapply_prop refined_raft_net_invariant_do_generic_server. eauto.
eapply_prop refined_raft_net_invariant_do_leader. eauto.
eapply refined_raft_invariant_handle_input with (P := P); eauto using in_app_or.
auto.
simpl. break_if; intuition eauto.
eauto.
simpl. eapply in_app_or.
auto.
simpl. break_if; eauto; congruence.
simpl. intros.
break_if; subst;
repeat rewrite update_same by auto;
repeat rewrite update_neq by auto; auto.
simpl. unfold send_packets.  intros. in_crush.
+ match goal with
| [ H : nwPackets ?net = _ |- _ {| nwPackets := ?ps ; nwState := ?st |} ] =>
assert (forall p, In p (nwPackets {| nwPackets := ps ; nwState := st |}) ->
In p (nwPackets net)) by (intros; simpl in *; find_rewrite; in_crush)
end.
eapply_prop refined_raft_net_invariant_state_same_packet_subset; [|eauto|idtac|];
eauto.
+ match goal with
| [ H : nwPackets ?net = _ |- _ {| nwPackets := ?ps ; nwState := ?st |} ] =>
assert (forall p, In p (nwPackets {| nwPackets := ps ; nwState := st |}) ->
In p (nwPackets net)) by (intros; simpl in *; find_rewrite; in_crush)
end.
eapply_prop refined_raft_net_invariant_state_same_packet_subset; [|eauto|idtac|];
eauto.
+ auto.
+ eapply_prop refined_raft_net_invariant_reboot; eauto;
intros; simpl in *; repeat break_if; intuition; subst; intuition eauto.
destruct (nwState net h); auto.
- eapply refined_raft_invariant_handle_input; eauto.
- eapply refined_raft_invariant_handle_message; eauto.
- eapply_prop refined_raft_net_invariant_do_leader; eauto.
- eapply_prop refined_raft_net_invariant_do_generic_server; eauto.
Qed.

(* Specifications: *)
Lemma refined_raft_invariant_handle_message' P :
forall xs p ys net st' ps' gd d l,
refined_raft_net_invariant_append_entries' P ->
refined_raft_net_invariant_append_entries_reply' P ->
refined_raft_net_invariant_request_vote' P ->
refined_raft_net_invariant_request_vote_reply' P ->
handleMessage (pSrc p) (pDst p) (pBody p) (snd (nwState net (pDst p))) = (d, l) ->
update_elections_data_net (pDst p) (pSrc p) (pBody p) (nwState net (pDst p)) = gd ->
P net ->
refined_raft_intermediate_reachable net ->
refined_raft_intermediate_reachable (mkNetwork ps' st') ->
nwPackets net = xs ++ p :: ys ->
(forall h, st' h = update name_eq_dec (nwState net) (pDst p) (gd, d) h) ->
(forall p', In p' ps' -> In p' (xs ++ ys) \/
In p' (send_packets (pDst p) l)) ->
P (mkNetwork ps' st').