Ltac do_elim :=
    match goal with
      | [ H : findAtIndex _ _ = Some _ |- _ ] => apply findAtIndex_elim in H; intuition
      | [ H : In _ (findGtIndex _ _) |- _ ] => apply findGtIndex_necessary in H; intuition
    end.Ltac use_packet_subset_clear :=
    match goal with
      | [ H : forall _, In _ _ -> _, H' : In _ _ |- _ ] => apply H in H'; clear H; intuition
    end.Ltac use_packet_subset :=
    match goal with
      | [ H : forall _, In _ _ -> _, H' : In _ _ |- _ ] => apply H in H'; intuition
    end.Ltac use_nw_invariant :=
    match goal with
      | [ H : forall _ _ _ _ _ _ _, In _ _ -> Net.pBody _ = _ -> _,
            H' : Net.pBody ?p = AppendEntries _ _ _ _ ?xs _,
            _ : In ?p (nwPackets _) |- _] =>
        apply H in H'; clear H; intuition
    end.Ltac rewrite_if_log :=
    match goal with
      | [ H : _ |- _ ] => rewrite if_sum_bool_fun_comm with (f:=log) in *
    end.Ltac use_log_matching_nw_host_keep :=
    match goal with
      | [ H : forall _ _ _, In _ _ -> _,
            _ : eIndex ?e = eIndex ?e',
            Hin : In _ _
            |- _ ] =>
        match type of Hin with
          | context [ nwState _ ?h ] =>
            let x := fresh in pose proof H as x;
            (specialize (H h e e'); do 4 concludes) ||
            (specialize (H h e' e); do 4 concludes)
        end
    end.Ltac use_log_matching_nw_host :=
    match goal with
      | [ H : forall _ _ _, In _ _ -> _,
            _ : eIndex ?e = eIndex ?e',
            Hin : In _ _
            |- _ ] =>
        match type of Hin with
          | context [ nwState _ ?h ] =>
            (specialize (H h e e'); do 4 concludes) ||
            (specialize (H h e' e); do 4 concludes)
        end
    end.Ltac solve_uniqueIndices :=
    unfold uniqueIndices_host_invariant in *;
    intuition;
    match goal with
      | [ H : forall _, uniqueIndices _ |- _ ] => apply H
    end.Ltac use_log_matching_nw_nw :=
    match goal with
      | [ H : forall _ _ _ _ _ _ _, In _ _ -> _,
            Hp' : Net.pBody ?p' = AppendEntries _ _ _ _ ?entries' _,
            Hp : Net.pBody ?p = _
            |- context [ In _ ?entries' ] ] =>
        apply H in Hp; clear H; intuition
      | [ H : forall _ _ _ _ _ _ _, In _ _ -> _,
            Hp : Net.pBody _ = AppendEntries _ _ _ _ _ _,
            Hp' : Net.pBody _ = AppendEntries _ _ (eIndex ?e'') _ _ _
            |- _ ] =>
        apply H in Hp; auto; intuition; clear H
      | [ H : forall _ _ _ _ _ _ _, In _ _ -> _,
            Hp' : Net.pBody ?p' = AppendEntries _ _ _ ?plt' _ _,
            Hp : Net.pBody ?p = _
            |- ?plt = ?plt' ] =>
        apply H in Hp; auto; intuition; clear H
    end;
    try match goal with
          | [ H : forall _ _ _ _ _ _ _, In _ _ -> _,
              _ : eIndex ?e = eIndex ?e',
              Hp : Net.pBody ?p = _
          |- _ ] =>
          eapply H with (e1:=e)(e2:=e') in Hp; eauto
        end; intuition.Ltac shouldSend_true :=
    match goal with
      | _ : context [shouldSend ?st] |- _ =>
        destruct (shouldSend st) eqn:?
    end; tuple_inversion; [|(solve [in_crush])].

(* Specifications: *)
Theorem doLeader_log_matching_nw : forall net h out d ms net', doLeader (nwState net h) h = (out, d, ms) -> logs_sorted net -> log_matching net -> uniqueIndices_host_invariant net -> (forall p, In p (nwPackets net') -> In p (nwPackets net) \/ In p (map (fun m => mkPacket h (fst m) (snd m)) ms)) -> (forall h', nwState net' h' = if name_eq_dec h' h then d else nwState net h') -> log_matching_nw net'.