Ltac get_invariant_pre inv :=
    match goal with
      | H : raft_intermediate_reachable _ |- _=>
        match (type of H) with
          | context [mkNetwork] =>
            fail 2
        end || copy_apply inv H
    end.Ltac get_invariant_post inv :=
    match goal with
      | H : raft_intermediate_reachable _ |- _=>
        match (type of H) with
          | context [mkNetwork] =>
            copy_apply inv H            
        end
    end.Definition clientCache_to_ks (c : list (clientId * (nat * output))) :=
    map (fun e => (fst e, fst (snd e))) c.

(* Specifications: *)
Lemma snd_execute_log' : forall l st o o', snd (execute_log' l st o) = snd (execute_log' l st o').
Lemma clientCache_to_ks_assoc : forall c client id, assoc clientId_eq_dec (clientCache_to_ks c) client = Some id -> exists o, assoc clientId_eq_dec c client = Some (id, o).
Lemma clientCache_to_ks_assoc_getLastId : forall st client id, assoc clientId_eq_dec (clientCache_to_ks (clientCache st)) client = Some id -> exists o, getLastId st client = Some (id, o).
Lemma clientCache_to_ks_assoc_none : forall c client, assoc clientId_eq_dec (clientCache_to_ks c) client = None -> assoc clientId_eq_dec c client = None.
Lemma clientCache_to_ks_assoc_getLastId_none : forall st client, assoc clientId_eq_dec (clientCache_to_ks (clientCache st)) client = None -> getLastId st client = None.
Lemma cacheApplyEntry_stateMachine_apply : forall st e os st' id o o' d, cacheApplyEntry st e = (os, st') -> getLastId st (eClient e) = Some (id, o) -> id < eId e -> handler (eInput e) (stateMachine st) = (o', d) -> stateMachine st' = d.
Lemma cacheApplyEntry_cache_apply : forall st e os st' id o o' d, cacheApplyEntry st e = (os, st') -> getLastId st (eClient e) = Some (id, o) -> id < eId e -> handler (eInput e) (stateMachine st) = (o', d) -> assoc_set clientId_eq_dec (clientCache st) (eClient e) (eId e, o') = clientCache st'.
Lemma cacheApplyEntry_stateMachine_apply_none : forall st e os st' o' d, cacheApplyEntry st e = (os, st') -> getLastId st (eClient e) = None -> handler (eInput e) (stateMachine st) = (o', d) -> stateMachine st' = d.
Lemma cacheApplyEntry_cache_apply_none : forall st e os st' o' d, cacheApplyEntry st e = (os, st') -> getLastId st (eClient e) = None -> handler (eInput e) (stateMachine st) = (o', d) -> assoc_set clientId_eq_dec (clientCache st) (eClient e) (eId e, o') = clientCache st'.
Lemma cacheApplyEntry_stateMachine_no_apply : forall st e os st' id o, cacheApplyEntry st e = (os, st') -> getLastId st (eClient e) = Some (id, o) -> eId e <= id -> stateMachine st' = stateMachine st.
Lemma cacheApplyEntry_cache_no_apply : forall st e os st' id o, cacheApplyEntry st e = (os, st') -> getLastId st (eClient e) = Some (id, o) -> eId e <= id -> clientCache st = clientCache st'.
Lemma clientCache_to_ks_assoc_set : forall c client id o, assoc_set clientId_eq_dec (clientCache_to_ks c) client id = clientCache_to_ks (assoc_set clientId_eq_dec c client (id, o)).
Lemma applyEntries_lastApplied_commitIndex_log : forall l h st os st', applyEntries h st l = (os, st') -> lastApplied st' = lastApplied st /\ commitIndex st' = commitIndex st /\ log st' = log st.
Lemma filter_and : forall A (l : list A) f g, (forall x, In x l -> f x = true) -> filter (fun x => f x && g x) l = filter (fun x => g x) l.
Lemma log_to_ks'_app : forall l1 l2 ks, log_to_ks' (l1 ++ l2) ks = log_to_ks' l2 (log_to_ks' l1 ks).
Lemma log_to_ks'_a_equiv : forall l ks ks', a_equiv clientId_eq_dec ks ks' -> a_equiv clientId_eq_dec (log_to_ks' l ks) (log_to_ks' l ks').
Lemma log_to_ks'_max_id_for_client : forall l c ks, assoc_default clientId_eq_dec (log_to_ks' l ks) c 0 = max_id_for_client_default (assoc_default clientId_eq_dec ks c 0) c l.
Lemma max_id_for_client_default_le : forall l x c, (forall e, In e l -> eClient e = c -> eId e <= x) -> max_id_for_client_default x c l = x.
Lemma max_id_for_client_default_on_max : forall c l x x', max_id_for_client_default (max x x') c l = max x (max_id_for_client_default x' c l).
Lemma max_id_for_client_default_or_entry : forall c l x, max_id_for_client_default x c l = x \/ exists e, In e l /\ eClient e = c /\ max_id_for_client_default x c l = eId e.
Lemma max_id_for_client_default_is_max : forall l x c e, In e l -> eClient e = c -> eId e <= max_id_for_client_default x c l.
Lemma max_id_for_client_default_ge_default : forall l x c, x <= max_id_for_client_default x c l.
Lemma max_id_for_client_default_subset : forall l l' x c, (forall e, In e l -> In e l') -> max_id_for_client_default x c l <= max_id_for_client_default x c l'.
Lemma max_id_for_client_default_ext : forall l l' x c, (forall e, In e l -> In e l') -> (forall e, In e l' -> In e l) -> max_id_for_client_default x c l = max_id_for_client_default x c l'.
Lemma log_to_ks'_assoc_default_ks : forall l ks c i, i <= assoc_default clientId_eq_dec (log_to_ks' l (assoc_set clientId_eq_dec ks c i)) c 0.
Lemma log_to_ks'_assoc_default_assoc_default_le : forall l ks c, assoc_default clientId_eq_dec ks c 0 <= assoc_default clientId_eq_dec (log_to_ks' l ks) c 0.
Lemma log_to_ks'_assoc_default_eq : forall l ks ks' c, assoc_default clientId_eq_dec (log_to_ks' l ks) c 0 <= assoc_default clientId_eq_dec ks' c 0 -> assoc_default clientId_eq_dec (log_to_ks' l ks') c 0 = assoc_default clientId_eq_dec ks' c 0.
Lemma log_to_ks'_assoc_set_diff : forall l ks k v k', k <> k' -> assoc clientId_eq_dec (log_to_ks' l (assoc_set clientId_eq_dec ks k v)) k' = assoc clientId_eq_dec (log_to_ks' l ks) k'.
Lemma log_to_ks'_assoc_default_set_diff : forall l ks k v k', k <> k' -> assoc_default clientId_eq_dec (log_to_ks' l (assoc_set clientId_eq_dec ks k v)) k' 0 = assoc_default clientId_eq_dec (log_to_ks' l ks) k' 0.
Lemma assoc_set_log_to_ks'_le: forall (l : list entry) (ks : list (clientId * nat)) c i, assoc_default clientId_eq_dec (log_to_ks' l ks) c 0 <= i -> a_equiv clientId_eq_dec (assoc_set clientId_eq_dec (log_to_ks' l ks) c i) (log_to_ks' l (assoc_set clientId_eq_dec ks c i)).
Lemma in_ks_log_to_ks'_le : forall e l ks id, assoc clientId_eq_dec ks (eClient e) = Some id -> exists id', assoc clientId_eq_dec (log_to_ks' l ks) (eClient e) = Some id' /\ id <= id'.
Lemma in_l_log_to_ks'_le : forall e l ks, In e l -> exists id, assoc clientId_eq_dec (log_to_ks' l ks) (eClient e) = Some id /\ eId e <= id.
Lemma handleAppendEntries_preserves_lastApplied_entries': forall (p : packet) (net : network) (d : raft_data) (m : msg) (t : term) (n : name) (pli : logIndex) (plt : term) (es : list entry) (ci : logIndex) xs ys ps' st' e, raft_intermediate_reachable net -> raft_intermediate_reachable {| nwPackets := ps'; nwState := st' |} -> (forall h : name, st' h = update name_eq_dec (nwState net) (pDst p) d h) -> (forall p' : packet, In p' ps' -> In p' (xs ++ ys) \/ p' = {| pSrc := pDst p; pDst := pSrc p; pBody := m |}) -> handleAppendEntries (pDst p) (nwState net (pDst p)) t n pli plt es ci = (d, m) -> nwPackets net = xs ++ p :: ys -> pBody p = AppendEntries t n pli plt es ci -> eIndex e <= lastApplied (nwState net (pDst p)) -> In e (log (nwState net (pDst p))) -> In e (log d).
Lemma handleAppendEntries_preserves_lastApplied_entries: forall (p : packet) (net : network) (d : raft_data) (m : msg) (t : term) (n : name) (pli : logIndex) (plt : term) (es : list entry) (ci : logIndex) xs ys ps' st', raft_intermediate_reachable net -> raft_intermediate_reachable {| nwPackets := ps'; nwState := st' |} -> (forall h : name, st' h = update name_eq_dec (nwState net) (pDst p) d h) -> (forall p' : packet, In p' ps' -> In p' (xs ++ ys) \/ p' = {| pSrc := pDst p; pDst := pSrc p; pBody := m |}) -> handleAppendEntries (pDst p) (nwState net (pDst p)) t n pli plt es ci = (d, m) -> nwPackets net = xs ++ p :: ys -> pBody p = AppendEntries t n pli plt es ci -> removeAfterIndex (log d) (lastApplied d) = removeAfterIndex (log (nwState net (pDst p))) (lastApplied (nwState net (pDst p))).
Lemma removeAfterIndex_cons : forall l x i, i < eIndex x -> removeAfterIndex (x :: l) i = removeAfterIndex l i.
Lemma handleClientRequest_preserves_lastApplied_entries: forall h (net : network) (d : raft_data) client id c out l, raft_intermediate_reachable net -> handleClientRequest h (nwState net h) client id c = (out, d, l) -> removeAfterIndex (log d) (lastApplied d) = removeAfterIndex (log (nwState net h)) (lastApplied (nwState net h)).
Lemma client_cache_keys_correct_clientCache_complete : forall net, client_cache_keys_correct net -> client_cache_complete net.
Lemma deduplicate_log'_app : forall l1 l2 ks, deduplicate_log' (l1 ++ l2) ks = deduplicate_log' l1 ks ++ (deduplicate_log' l2 (log_to_ks' l1 ks)).
Lemma deduplicate_log'_a_equiv : forall l ks ks', a_equiv clientId_eq_dec ks ks' -> deduplicate_log' l ks = deduplicate_log' l ks'.
Lemma applyEntries_app : forall l h st os d l', applyEntries h st (l ++ l') = (os, d) -> exists os' os'' d', applyEntries h st l = (os', d') /\ applyEntries h d' l' = (os'', d) /\ os = os' ++ os''.
Lemma getLastId_clientCache_to_ks_assoc : forall (st : RaftState.raft_data term name entry logIndex serverType data clientId output) (client : clientId) (id : nat) o, getLastId st client = Some (id, o) -> assoc clientId_eq_dec (clientCache_to_ks (clientCache st)) client = Some id.
Lemma i_lt_assoc_default_0 : forall K K_eq_dec ks (k : K) i, i < assoc_default K_eq_dec ks k 0 -> exists i', assoc K_eq_dec ks k = Some i' /\ i < i'.
Lemma applyEntries_log_to_ks' : forall l h st o st', applyEntries h st l = (o, st') -> a_equiv clientId_eq_dec (clientCache_to_ks (clientCache st')) (log_to_ks' l (clientCache_to_ks (clientCache st))).
Lemma deduplicate_log_app : forall l l', exists l'', deduplicate_log (l ++ l') = deduplicate_log l ++ l''.
Lemma output_correct_monotonic : forall c i o xs ys, output_correct c i o xs -> output_correct c i o (xs ++ ys).
Lemma execute_log'_trace: forall l d d' tr tr' tr'', execute_log' l d tr = (tr', d') -> execute_log' l d (tr'' ++ tr) = (tr'' ++ tr', d').
Lemma hd_error_Some_app : forall A l l' (x : A), hd_error l = Some x -> hd_error (l ++ l') = Some x.
Lemma client_cache_keys_correct_do_generic_server : raft_net_invariant_do_generic_server' client_cache_keys_correct.
Lemma client_cache_keys_correct_append_entries : raft_net_invariant_append_entries' client_cache_keys_correct.
Lemma client_cache_keys_correct_append_entries_reply : raft_net_invariant_append_entries_reply' client_cache_keys_correct.
Lemma client_cache_keys_correct_request_vote : raft_net_invariant_request_vote' client_cache_keys_correct.
Lemma client_cache_keys_correct_request_vote_reply : raft_net_invariant_request_vote_reply' client_cache_keys_correct.
Lemma client_cache_keys_correct_client_request : raft_net_invariant_client_request' client_cache_keys_correct.
Lemma client_cache_keys_correct_timeout : raft_net_invariant_timeout' client_cache_keys_correct.
Lemma client_cache_keys_correct_do_leader : raft_net_invariant_do_leader' client_cache_keys_correct.
Lemma client_cache_keys_correct_reboot : raft_net_invariant_reboot' client_cache_keys_correct.
Lemma client_cache_keys_correct_state_same_packet_subset : raft_net_invariant_state_same_packet_subset client_cache_keys_correct.
Lemma client_cache_keys_correct_init : raft_net_invariant_init client_cache_keys_correct.
Lemma client_cache_keys_correct_invariant: forall (net : network), raft_intermediate_reachable net -> client_cache_keys_correct net.
Lemma state_machine_do_generic_server : raft_net_invariant_do_generic_server' state_machine_log.
Lemma state_machine_append_entries : raft_net_invariant_append_entries' state_machine_log.
Lemma state_machine_append_entries_reply : raft_net_invariant_append_entries_reply' state_machine_log.
Lemma state_machine_request_vote : raft_net_invariant_request_vote' state_machine_log.
Lemma state_machine_request_vote_reply : raft_net_invariant_request_vote_reply' state_machine_log.
Lemma state_machine_timeout : raft_net_invariant_timeout' state_machine_log.
Lemma state_machine_client_request : raft_net_invariant_client_request' state_machine_log.
Lemma state_machine_do_leader : raft_net_invariant_do_leader' state_machine_log.
Lemma state_machine_reboot : raft_net_invariant_reboot' state_machine_log.
Lemma state_machine_state_same_packet_subset : raft_net_invariant_state_same_packet_subset state_machine_log.
Lemma state_machine_init : raft_net_invariant_init state_machine_log.
Lemma state_machine_log_invariant : forall net, raft_intermediate_reachable net -> state_machine_log net.
Lemma client_cache_correct_do_generic_server : raft_net_invariant_do_generic_server' client_cache_correct.
Lemma same_clientCache_same_getLastId : forall st st' k, clientCache st = clientCache st' -> getLastId st k = getLastId st' k.