Section LogMatchingProof.
Context {orig_base_params : BaseParams}.
Context {one_node_params : OneNodeParams orig_base_params}.
Context {raft_params : RaftParams orig_base_params}.
Context {si : sorted_interface}.
Context {lsi : leader_sublog_interface}.
Context {uii : unique_indices_interface}.
Proof using.
intros.
unfold handleAppendEntries in *.
repeat break_match; find_inversion; simpl in *; intuition; repeat find_rewrite_lem advanceCurrentTerm_log; intuition.
simpl in *. do_in_app. intuition.
eauto using removeAfterIndex_in.
Qed.
Proof using.
intros.
unfold log_matching_hosts in *.
intuition; repeat rewrite <- H0 in *; eauto.
Qed.
Ltac log_matching_hosts_easy_case :=
repeat find_inversion; intros;
eapply log_matching_hosts_ignores_packets; eauto;
intros; simpl; repeat break_if; try congruence.
Proof using.
intros. split; unfold log_matching in *.
- intuition. eauto using log_matching_hosts_ignores_packets.
- unfold log_matching_nw in *. intros.
match goal with
| [ H : forall _, is_append_entries _ -> _,
H' : In ?p (nwPackets _) |- _] =>
pose proof H as Hpkt;
specialize (H p);
forward H; [solve [repeat eexists; eauto]|]; conclude H auto; repeat concludes
end.
break_and.
match goal with
| [ H : forall _ _ _ _, _,
H' : pBody ?p = _,
H'' : In ?p _ |- _ ] =>
specialize (H _ _ _ _ _ _ _ H'' H')
end.
intuition;
try match goal with
| [ H : forall _, _ = _ |- _ ] => rewrite <- H in *
end;
try match goal with
| [ H : forall _ _ _, In _ _ -> In _ _ ->  _,
H' : In ?e2 _,
_ : eIndex ?e1 = eIndex ?e2
|- _ ] =>
match type of H' with
| context [ nwState net ?host ] =>
specialize (H host e1 e2)
end
end; repeat concludes; intuition;
match goal with
| [ H : forall _ _ _ _ _ _ _, In _ _ -> pBody _ = _ -> _,
_ : eIndex ?e = eIndex ?f,
_ : In ?f ?xs,
_ : pBody ?p = AppendEntries _ _ _ _ ?xs _
|- _ ] =>
eapply H with (e1 := e)(p' := p); eauto 10
end.
Qed.
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])].

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'.