Class RaftParams (orig_base_params : BaseParams)
  := {
      N : nat ;
      input_eq_dec : forall x y : input, {x = y} + {x <> y} ;
      output_eq_dec : forall x y : output, {x = y} + {x <> y} ;
      clientId : Type ;
      clientId_eq_dec : forall x y : clientId, {x = y} + {x <> y}
    }.Class RaftParams (orig_base_params : BaseParams)
  := {
      N : nat ;
      input_eq_dec : forall x y : input, {x = y} + {x <> y} ;
      output_eq_dec : forall x y : output, {x = y} + {x <> y} ;
      clientId : Type ;
      clientId_eq_dec : forall x y : clientId, {x = y} + {x <> y}
    }.Class RaftParams (orig_base_params : BaseParams)
  := {
      N : nat ;
      input_eq_dec : forall x y : input, {x = y} + {x <> y} ;
      output_eq_dec : forall x y : output, {x = y} + {x <> y} ;
      clientId : Type ;
      clientId_eq_dec : forall x y : clientId, {x = y} + {x <> y}
    }.Class RaftParams (orig_base_params : BaseParams)
  := {
      N : nat ;
      input_eq_dec : forall x y : input, {x = y} + {x <> y} ;
      output_eq_dec : forall x y : output, {x = y} + {x <> y} ;
      clientId : Type ;
      clientId_eq_dec : forall x y : clientId, {x = y} + {x <> y}
    }.Class RaftParams (orig_base_params : BaseParams)
  := {
      N : nat ;
      input_eq_dec : forall x y : input, {x = y} + {x <> y} ;
      output_eq_dec : forall x y : output, {x = y} + {x <> y} ;
      clientId : Type ;
      clientId_eq_dec : forall x y : clientId, {x = y} + {x <> y}
    }.Class RaftParams (orig_base_params : BaseParams)
  := {
      N : nat ;
      input_eq_dec : forall x y : input, {x = y} + {x <> y} ;
      output_eq_dec : forall x y : output, {x = y} + {x <> y} ;
      clientId : Type ;
      clientId_eq_dec : forall x y : clientId, {x = y} + {x <> y}
    }.Definition term := nat.Definition logIndex := nat.Definition name := fin N.Definition nodes : list name := all_fin _.Definition name_eq_dec : forall x y : name, {x = y} + {x <> y} := fin_eq_dec _.Notation "a == b" := (beq_nat a b) (at level 70).Notation "a != b" := (negb (beq_nat a b)) (at level 70).Notation "a === b" := (if fin_eq_dec _ a b then true else false) (at level 42).Record entry := mkEntry {
                      eAt : name;
                      eClient : clientId;
                      eId : nat;
                      eIndex : logIndex;
                      eTerm : term;
                      eInput : input
                    }.Record entry := mkEntry {
                      eAt : name;
                      eClient : clientId;
                      eId : nat;
                      eIndex : logIndex;
                      eTerm : term;
                      eInput : input
                    }.Record entry := mkEntry {
                      eAt : name;
                      eClient : clientId;
                      eId : nat;
                      eIndex : logIndex;
                      eTerm : term;
                      eInput : input
                    }.Record entry := mkEntry {
                      eAt : name;
                      eClient : clientId;
                      eId : nat;
                      eIndex : logIndex;
                      eTerm : term;
                      eInput : input
                    }.Record entry := mkEntry {
                      eAt : name;
                      eClient : clientId;
                      eId : nat;
                      eIndex : logIndex;
                      eTerm : term;
                      eInput : input
                    }.Record entry := mkEntry {
                      eAt : name;
                      eClient : clientId;
                      eId : nat;
                      eIndex : logIndex;
                      eTerm : term;
                      eInput : input
                    }.Record entry := mkEntry {
                      eAt : name;
                      eClient : clientId;
                      eId : nat;
                      eIndex : logIndex;
                      eTerm : term;
                      eInput : input
                    }.Record entry := mkEntry {
                      eAt : name;
                      eClient : clientId;
                      eId : nat;
                      eIndex : logIndex;
                      eTerm : term;
                      eInput : input
                    }.Inductive msg : Type :=
  | RequestVote : term -> name -> logIndex -> term -> msg
  | RequestVoteReply : term -> bool -> msg
  | AppendEntries : term -> (name) -> logIndex -> term -> (list entry) -> logIndex -> msg
  | AppendEntriesReply : term -> (list entry) -> bool -> msg.Inductive msg : Type :=
  | RequestVote : term -> name -> logIndex -> term -> msg
  | RequestVoteReply : term -> bool -> msg
  | AppendEntries : term -> (name) -> logIndex -> term -> (list entry) -> logIndex -> msg
  | AppendEntriesReply : term -> (list entry) -> bool -> msg.Inductive msg : Type :=
  | RequestVote : term -> name -> logIndex -> term -> msg
  | RequestVoteReply : term -> bool -> msg
  | AppendEntries : term -> (name) -> logIndex -> term -> (list entry) -> logIndex -> msg
  | AppendEntriesReply : term -> (list entry) -> bool -> msg.Inductive msg : Type :=
  | RequestVote : term -> name -> logIndex -> term -> msg
  | RequestVoteReply : term -> bool -> msg
  | AppendEntries : term -> (name) -> logIndex -> term -> (list entry) -> logIndex -> msg
  | AppendEntriesReply : term -> (list entry) -> bool -> msg.Inductive msg : Type :=
  | RequestVote : term -> name -> logIndex -> term -> msg
  | RequestVoteReply : term -> bool -> msg
  | AppendEntries : term -> (name) -> logIndex -> term -> (list entry) -> logIndex -> msg
  | AppendEntriesReply : term -> (list entry) -> bool -> msg.Inductive raft_input : Type :=
  | Timeout : raft_input
  | ClientRequest : clientId -> nat -> input -> raft_input.Inductive raft_input : Type :=
  | Timeout : raft_input
  | ClientRequest : clientId -> nat -> input -> raft_input.Inductive raft_input : Type :=
  | Timeout : raft_input
  | ClientRequest : clientId -> nat -> input -> raft_input.Inductive raft_output : Type :=
  | NotLeader : clientId -> nat -> raft_output
  | ClientResponse : clientId -> nat -> output -> raft_output.Inductive raft_output : Type :=
  | NotLeader : clientId -> nat -> raft_output
  | ClientResponse : clientId -> nat -> output -> raft_output.Inductive raft_output : Type :=
  | NotLeader : clientId -> nat -> raft_output
  | ClientResponse : clientId -> nat -> output -> raft_output.Inductive serverType : Set :=
  | Follower
  | Candidate
  | Leader.Inductive serverType : Set :=
  | Follower
  | Candidate
  | Leader.Inductive serverType : Set :=
  | Follower
  | Candidate
  | Leader.Inductive serverType : Set :=
  | Follower
  | Candidate
  | Leader.Definition serverType_eq_dec : forall x y : serverType, {x = y} + {x <> y}.Definition term_eq_dec : forall x y : term, {x = y} + {x <> y}.Definition entry_eq_dec : forall x y : entry, {x = y} + {x <> y}.Definition msg_eq_dec : forall x y: msg, {x = y} + {x <> y}.Definition raft_data :=
    RaftState.raft_data term name entry logIndex serverType data clientId output.Notation currentTerm         := (RaftState.currentTerm term name entry logIndex serverType data clientId output).Notation votedFor            := (RaftState.votedFor term name entry logIndex serverType data clientId output).Notation leaderId            := (RaftState.leaderId term name entry logIndex serverType data clientId output).Notation log                 := (RaftState.log term name entry logIndex serverType data clientId output).Notation commitIndex         := (RaftState.commitIndex term name entry logIndex serverType data clientId output).Notation lastApplied         := (RaftState.lastApplied term name entry logIndex serverType data clientId output).Notation nextIndex           := (RaftState.nextIndex term name entry logIndex serverType data clientId output).Notation matchIndex          := (RaftState.matchIndex term name entry logIndex serverType data clientId output).Notation shouldSend          := (RaftState.shouldSend term name entry logIndex serverType data clientId output).Notation votesReceived       := (RaftState.votesReceived term name entry logIndex serverType data clientId output).Notation type                := (RaftState.type term name entry logIndex serverType data clientId output).Notation clientCache := (RaftState.clientCache term name entry logIndex serverType data clientId output).Notation stateMachine := (RaftState.stateMachine term name entry logIndex serverType data clientId output).Notation electoralVictories := (RaftState.electoralVictories term name entry logIndex serverType data clientId output).Notation mkRaft_data              := (RaftState.mkRaft_data term name entry logIndex serverType data clientId output).Fixpoint removeAfterIndex (entries : list entry) (i : logIndex) : list entry :=
    match entries with
      | nil => nil
      | e :: es => if leb (eIndex e) i then
                    e :: es
                  else
                    removeAfterIndex es i
    end.Fixpoint maxIndex (entries : list entry) : logIndex :=
    match entries with
      | nil => 0
      | e :: es => eIndex e
    end.Fixpoint maxTerm (entries : list entry) : term :=
    match entries with
      | nil => 0
      | e :: es => eTerm e
    end.Definition getNextIndex state h :=
    assoc_default name_eq_dec (nextIndex state) h (maxIndex (log state)).Definition haveNewEntries (state : raft_data) (entries : list entry) :=
    andb (not_empty entries) (match findAtIndex (log state) (maxIndex entries) with
                                | None => true
                                | Some e => (negb (beq_nat (maxTerm entries) (eTerm e)))
                              end).Fixpoint div2 a :=
    match a with
      | S (S n) => S (div2 n)
      | 1 => 0
      | 0 => 0
    end.Definition getLastId state client :=
    assoc clientId_eq_dec (clientCache state) client.Definition replicaMessage (state : raft_data) (me : name) (host : name) : (name * msg) :=
    let prevIndex := pred (getNextIndex state host) in
    let prevTerm := (match (findAtIndex (log state) prevIndex) with
                       | Some e => (eTerm e)
                       | None => 0
                     end) in
    let newEntries := findGtIndex (log state) prevIndex in
    (host, AppendEntries
             (currentTerm state) me prevIndex prevTerm newEntries (commitIndex state)).Definition haveQuorum (state : raft_data) (me : name) (N : logIndex) : bool :=
    Nat.ltb (div2 (length nodes)) (length (filter (fun h => leb N (assoc_default name_eq_dec (matchIndex state) h 0)) nodes)).Definition RaftNetHandler (me : name) (src : name) (m : msg)
             (state : raft_data) :=
    let (state, pkts) := handleMessage src me m state in
    let '(leaderOut, state, leaderPkts) := doLeader state me in
    let '(genericOut, state, genericPkts) := doGenericServer me state in
    (leaderOut ++ genericOut,
     state, pkts ++ leaderPkts ++ genericPkts).Definition handleInput (me : name) (inp : raft_input) (state : raft_data) :
    list raft_output * raft_data * list (name * msg) :=
    match inp with
      | ClientRequest client id c => handleClientRequest me state client id c
      | Timeout => handleTimeout me state
    end.Definition RaftInputHandler (me : name) (inp : raft_input)
             (state : raft_data) :=
    let '(handlerOut, state, pkts) := handleInput me inp state in
    let '(leaderOut, state, leaderPkts) := doLeader state me in
    let '(genericOut, state, genericPkts) := doGenericServer me state in
    (handlerOut ++ leaderOut ++ genericOut,
     state, pkts ++ leaderPkts ++ genericPkts).Instance base_params : BaseParams :=
    {
      data := raft_data ;
      input := raft_input ;
      output := raft_output
    }.Instance multi_params : MultiParams _ :=
    {
      name := name ;
      msg := msg ;
      msg_eq_dec := msg_eq_dec ;
      name_eq_dec := name_eq_dec ;
      nodes := nodes ;
      all_names_nodes := all_fin_all N ;
      no_dup_nodes := all_fin_NoDup N ;
      init_handlers := init_handlers ;
      net_handlers := RaftNetHandler ;
      input_handlers := RaftInputHandler
    }.Instance failure_params : FailureParams _ :=
    {
      reboot := reboot
    }.Inductive raft_intermediate_reachable : network -> Prop :=
  | RIR_init : raft_intermediate_reachable step_async_init
  | RIR_step_failure :
      forall failed net failed' net' out,
        raft_intermediate_reachable net ->
        step_failure (failed, net) (failed', net') out ->
        raft_intermediate_reachable net'
  | RIR_handleInput :
      forall net h inp out d l ps' st',
        raft_intermediate_reachable net ->
        handleInput h inp (nwState net h) = (out, d, l) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d h') ->
        (forall p', In p' ps' -> In p' (nwPackets net) \/
                           In p' (send_packets h l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_handleMessage :
      forall p net xs ys st' ps' d l,
        raft_intermediate_reachable net ->
        handleMessage (pSrc p) (pDst p) (pBody p) (nwState net (pDst p)) = (d, l) ->
        nwPackets net = xs ++ p :: ys ->
        (forall h, st' h = update name_eq_dec (nwState net) (pDst p) d h) ->
        (forall p', In p' ps' -> In p' (xs ++ ys) \/
                           In p' (send_packets (pDst p) l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doLeader :
      forall net st' ps' h os d' ms,
        raft_intermediate_reachable net ->
        doLeader (nwState net h) h = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doGenericServer :
      forall net st' ps' os d' ms h,
        raft_intermediate_reachable net ->
        doGenericServer h (nwState net h) = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st').Inductive raft_intermediate_reachable : network -> Prop :=
  | RIR_init : raft_intermediate_reachable step_async_init
  | RIR_step_failure :
      forall failed net failed' net' out,
        raft_intermediate_reachable net ->
        step_failure (failed, net) (failed', net') out ->
        raft_intermediate_reachable net'
  | RIR_handleInput :
      forall net h inp out d l ps' st',
        raft_intermediate_reachable net ->
        handleInput h inp (nwState net h) = (out, d, l) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d h') ->
        (forall p', In p' ps' -> In p' (nwPackets net) \/
                           In p' (send_packets h l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_handleMessage :
      forall p net xs ys st' ps' d l,
        raft_intermediate_reachable net ->
        handleMessage (pSrc p) (pDst p) (pBody p) (nwState net (pDst p)) = (d, l) ->
        nwPackets net = xs ++ p :: ys ->
        (forall h, st' h = update name_eq_dec (nwState net) (pDst p) d h) ->
        (forall p', In p' ps' -> In p' (xs ++ ys) \/
                           In p' (send_packets (pDst p) l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doLeader :
      forall net st' ps' h os d' ms,
        raft_intermediate_reachable net ->
        doLeader (nwState net h) h = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doGenericServer :
      forall net st' ps' os d' ms h,
        raft_intermediate_reachable net ->
        doGenericServer h (nwState net h) = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st').Inductive raft_intermediate_reachable : network -> Prop :=
  | RIR_init : raft_intermediate_reachable step_async_init
  | RIR_step_failure :
      forall failed net failed' net' out,
        raft_intermediate_reachable net ->
        step_failure (failed, net) (failed', net') out ->
        raft_intermediate_reachable net'
  | RIR_handleInput :
      forall net h inp out d l ps' st',
        raft_intermediate_reachable net ->
        handleInput h inp (nwState net h) = (out, d, l) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d h') ->
        (forall p', In p' ps' -> In p' (nwPackets net) \/
                           In p' (send_packets h l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_handleMessage :
      forall p net xs ys st' ps' d l,
        raft_intermediate_reachable net ->
        handleMessage (pSrc p) (pDst p) (pBody p) (nwState net (pDst p)) = (d, l) ->
        nwPackets net = xs ++ p :: ys ->
        (forall h, st' h = update name_eq_dec (nwState net) (pDst p) d h) ->
        (forall p', In p' ps' -> In p' (xs ++ ys) \/
                           In p' (send_packets (pDst p) l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doLeader :
      forall net st' ps' h os d' ms,
        raft_intermediate_reachable net ->
        doLeader (nwState net h) h = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doGenericServer :
      forall net st' ps' os d' ms h,
        raft_intermediate_reachable net ->
        doGenericServer h (nwState net h) = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st').Inductive raft_intermediate_reachable : network -> Prop :=
  | RIR_init : raft_intermediate_reachable step_async_init
  | RIR_step_failure :
      forall failed net failed' net' out,
        raft_intermediate_reachable net ->
        step_failure (failed, net) (failed', net') out ->
        raft_intermediate_reachable net'
  | RIR_handleInput :
      forall net h inp out d l ps' st',
        raft_intermediate_reachable net ->
        handleInput h inp (nwState net h) = (out, d, l) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d h') ->
        (forall p', In p' ps' -> In p' (nwPackets net) \/
                           In p' (send_packets h l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_handleMessage :
      forall p net xs ys st' ps' d l,
        raft_intermediate_reachable net ->
        handleMessage (pSrc p) (pDst p) (pBody p) (nwState net (pDst p)) = (d, l) ->
        nwPackets net = xs ++ p :: ys ->
        (forall h, st' h = update name_eq_dec (nwState net) (pDst p) d h) ->
        (forall p', In p' ps' -> In p' (xs ++ ys) \/
                           In p' (send_packets (pDst p) l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doLeader :
      forall net st' ps' h os d' ms,
        raft_intermediate_reachable net ->
        doLeader (nwState net h) h = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doGenericServer :
      forall net st' ps' os d' ms h,
        raft_intermediate_reachable net ->
        doGenericServer h (nwState net h) = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st').Inductive raft_intermediate_reachable : network -> Prop :=
  | RIR_init : raft_intermediate_reachable step_async_init
  | RIR_step_failure :
      forall failed net failed' net' out,
        raft_intermediate_reachable net ->
        step_failure (failed, net) (failed', net') out ->
        raft_intermediate_reachable net'
  | RIR_handleInput :
      forall net h inp out d l ps' st',
        raft_intermediate_reachable net ->
        handleInput h inp (nwState net h) = (out, d, l) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d h') ->
        (forall p', In p' ps' -> In p' (nwPackets net) \/
                           In p' (send_packets h l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_handleMessage :
      forall p net xs ys st' ps' d l,
        raft_intermediate_reachable net ->
        handleMessage (pSrc p) (pDst p) (pBody p) (nwState net (pDst p)) = (d, l) ->
        nwPackets net = xs ++ p :: ys ->
        (forall h, st' h = update name_eq_dec (nwState net) (pDst p) d h) ->
        (forall p', In p' ps' -> In p' (xs ++ ys) \/
                           In p' (send_packets (pDst p) l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doLeader :
      forall net st' ps' h os d' ms,
        raft_intermediate_reachable net ->
        doLeader (nwState net h) h = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doGenericServer :
      forall net st' ps' os d' ms h,
        raft_intermediate_reachable net ->
        doGenericServer h (nwState net h) = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st').Inductive raft_intermediate_reachable : network -> Prop :=
  | RIR_init : raft_intermediate_reachable step_async_init
  | RIR_step_failure :
      forall failed net failed' net' out,
        raft_intermediate_reachable net ->
        step_failure (failed, net) (failed', net') out ->
        raft_intermediate_reachable net'
  | RIR_handleInput :
      forall net h inp out d l ps' st',
        raft_intermediate_reachable net ->
        handleInput h inp (nwState net h) = (out, d, l) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d h') ->
        (forall p', In p' ps' -> In p' (nwPackets net) \/
                           In p' (send_packets h l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_handleMessage :
      forall p net xs ys st' ps' d l,
        raft_intermediate_reachable net ->
        handleMessage (pSrc p) (pDst p) (pBody p) (nwState net (pDst p)) = (d, l) ->
        nwPackets net = xs ++ p :: ys ->
        (forall h, st' h = update name_eq_dec (nwState net) (pDst p) d h) ->
        (forall p', In p' ps' -> In p' (xs ++ ys) \/
                           In p' (send_packets (pDst p) l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doLeader :
      forall net st' ps' h os d' ms,
        raft_intermediate_reachable net ->
        doLeader (nwState net h) h = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doGenericServer :
      forall net st' ps' os d' ms h,
        raft_intermediate_reachable net ->
        doGenericServer h (nwState net h) = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st').Inductive raft_intermediate_reachable : network -> Prop :=
  | RIR_init : raft_intermediate_reachable step_async_init
  | RIR_step_failure :
      forall failed net failed' net' out,
        raft_intermediate_reachable net ->
        step_failure (failed, net) (failed', net') out ->
        raft_intermediate_reachable net'
  | RIR_handleInput :
      forall net h inp out d l ps' st',
        raft_intermediate_reachable net ->
        handleInput h inp (nwState net h) = (out, d, l) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d h') ->
        (forall p', In p' ps' -> In p' (nwPackets net) \/
                           In p' (send_packets h l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_handleMessage :
      forall p net xs ys st' ps' d l,
        raft_intermediate_reachable net ->
        handleMessage (pSrc p) (pDst p) (pBody p) (nwState net (pDst p)) = (d, l) ->
        nwPackets net = xs ++ p :: ys ->
        (forall h, st' h = update name_eq_dec (nwState net) (pDst p) d h) ->
        (forall p', In p' ps' -> In p' (xs ++ ys) \/
                           In p' (send_packets (pDst p) l)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doLeader :
      forall net st' ps' h os d' ms,
        raft_intermediate_reachable net ->
        doLeader (nwState net h) h = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st')
  | RIR_doGenericServer :
      forall net st' ps' os d' ms h,
        raft_intermediate_reachable net ->
        doGenericServer h (nwState net h) = (os, d', ms) ->
        (forall h', st' h' = update name_eq_dec (nwState net) h d' h') ->
        (forall p, In p ps' -> In p (nwPackets net) \/
                         In p (send_packets h ms)) ->
        raft_intermediate_reachable (mkNetwork ps' st').

(* Specifications: *)
Lemma step_failure_star_raft_intermediate_reachable' : forall n' tr, step_failure_star step_failure_init n' tr -> raft_intermediate_reachable (snd n').
Lemma step_failure_star_raft_intermediate_reachable : forall failed net tr, step_failure_star step_failure_init (failed, net) tr -> raft_intermediate_reachable net.
Lemma step_failure_star_raft_intermediate_reachable_extend : forall f net f' net' tr, step_failure_star (f, net) (f', net') tr -> raft_intermediate_reachable net -> raft_intermediate_reachable net'.