(* *********************************************************************)
(*                                                                     *)
(*              The Compcert verified compiler                         *)
(*                                                                     *)
(*          Xavier Leroy, INRIA Paris-Rocquencourt                     *)
(*                                                                     *)
(*  Copyright Institut National de Recherche en Informatique et en     *)
(*  Automatique.  All rights reserved.  This file is distributed       *)
(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
(*                                                                     *)
(* *********************************************************************)

(** Recognition of combined operations, addressing modes and conditions
  during the [CSE] phase. *)

Require Import Coqlib.
Require Import Integers.
Require Import Values.
Require Import Memory.
Require Import Op.
Require Import RTL.
Require Import CSEdomain.
Require Import CombineOp.

(** [CompCertX:test-compcert-param-memory] We create section [WITHMEM] and associated
 contexts to parameterize the proof over the memory model. *)
Section WITHMEM.
Context `{memory_model: Mem.MemoryModel}.

Section COMBINE.

Variable ge: genv.
Variable sp: val.
Variable m: mem.
Variable get: valnum -> option rhs.
Variable valu: valnum -> val.
Hypothesis get_sound: forall v rhs, get v = Some rhs -> rhs_eval_to valu ge sp m rhs (valu v).

Lemma get_op_sound:
  forall v op vl, get v = Some (Op op vl) -> eval_operation ge sp op (map valu vl) m = Some (valu v).
Proof.
  intros. exploit get_sound; eauto. intros REV; inv REV; auto.
Qed.

Ltac UseGetSound :=
  match goal with
  | [ H: get _ = Some _ |- _ ] =>
      let x := fresh "EQ" in (generalize (get_op_sound _ _ _ H); intros x; simpl in x; FuncInv)
  end.

Lemma combine_compimm_ne_0_sound:
  forall x cond args,
  combine_compimm_ne_0 get x = Some(cond, args) ->
  eval_condition cond (map valu args) m = Val.cmp_bool Cne (valu x) (Vint Int.zero) /\
  eval_condition cond (map valu args) m = Val.cmpu_bool (Mem.valid_pointer m) Cne (valu x) (Vint Int.zero).
Proof.
  intros until args. functional induction (combine_compimm_ne_0 get x); intros EQ; inv EQ.
  (* of cmp *)
  UseGetSound. rewrite <- H.
  destruct (eval_condition cond (map valu args) m); simpl; auto. destruct b; auto.
  (* of and *)
  UseGetSound. rewrite <- H.
  destruct v; simpl; auto.
Qed.

Lemma combine_compimm_eq_0_sound:
  forall x cond args,
  combine_compimm_eq_0 get x = Some(cond, args) ->
  eval_condition cond (map valu args) m = Val.cmp_bool Ceq (valu x) (Vint Int.zero) /\
  eval_condition cond (map valu args) m = Val.cmpu_bool (Mem.valid_pointer m) Ceq (valu x) (Vint Int.zero).
Proof.
  intros until args. functional induction (combine_compimm_eq_0 get x); intros EQ; inv EQ.
  (* of cmp *)
  UseGetSound. rewrite <- H.
  rewrite eval_negate_condition.
  destruct (eval_condition c (map valu args) m); simpl; auto. destruct b; auto.
  (* of and *)
  UseGetSound. rewrite <- H. destruct v; auto.
Qed.

Lemma combine_compimm_eq_1_sound:
  forall x cond args,
  combine_compimm_eq_1 get x = Some(cond, args) ->
  eval_condition cond (map valu args) m = Val.cmp_bool Ceq (valu x) (Vint Int.one) /\
  eval_condition cond (map valu args) m = Val.cmpu_bool (Mem.valid_pointer m) Ceq (valu x) (Vint Int.one).
Proof.
  intros until args. functional induction (combine_compimm_eq_1 get x); intros EQ; inv EQ.
  (* of cmp *)
  UseGetSound. rewrite <- H.
  destruct (eval_condition cond (map valu args) m); simpl; auto. destruct b; auto.
Qed.

Lemma combine_compimm_ne_1_sound:
  forall x cond args,
  combine_compimm_ne_1 get x = Some(cond, args) ->
  eval_condition cond (map valu args) m = Val.cmp_bool Cne (valu x) (Vint Int.one) /\
  eval_condition cond (map valu args) m = Val.cmpu_bool (Mem.valid_pointer m) Cne (valu x) (Vint Int.one).
Proof.
  intros until args. functional induction (combine_compimm_ne_1 get x); intros EQ; inv EQ.
  (* of cmp *)
  UseGetSound. rewrite <- H.
  rewrite eval_negate_condition.
  destruct (eval_condition c (map valu args) m); simpl; auto. destruct b; auto.
Qed.

Theorem combine_cond_sound:
  forall cond args cond' args',
  combine_cond get cond args = Some(cond', args') ->
  eval_condition cond' (map valu args') m = eval_condition cond (map valu args) m.
Proof.
  intros. functional inversion H; subst.
  (* compimm ne zero *)
  simpl; eapply combine_compimm_ne_0_sound; eauto.
  (* compimm ne one *)
  simpl; eapply combine_compimm_ne_1_sound; eauto.
  (* compimm eq zero *)
  simpl; eapply combine_compimm_eq_0_sound; eauto.
  (* compimm eq one *)
  simpl; eapply combine_compimm_eq_1_sound; eauto.
  (* compuimm ne zero *)
  simpl; eapply combine_compimm_ne_0_sound; eauto.
  (* compuimm ne one *)
  simpl; eapply combine_compimm_ne_1_sound; eauto.
  (* compuimm eq zero *)
  simpl; eapply combine_compimm_eq_0_sound; eauto.
  (* compuimm eq one *)
  simpl; eapply combine_compimm_eq_1_sound; eauto.
Qed.

Theorem combine_addr_sound:
  forall addr args addr' args',
  combine_addr get addr args = Some(addr', args') ->
  eval_addressing ge sp addr' (map valu args') = eval_addressing ge sp addr (map valu args).
Proof.
  intros. functional inversion H; subst.
  (* indexed - lea *)
  UseGetSound. simpl. eapply eval_offset_addressing_total; eauto.
Qed.

Theorem combine_op_sound:
  forall op args op' args',
  combine_op get op args = Some(op', args') ->
  eval_operation ge sp op' (map valu args') m = eval_operation ge sp op (map valu args) m.
Proof.
  intros. functional inversion H; subst.
(* lea-lea *)
  simpl. eapply combine_addr_sound; eauto.
(* andimm - andimm *)
  UseGetSound; simpl. rewrite <- H0. rewrite Val.and_assoc. auto.
(* orimm - orimm *)
  UseGetSound; simpl. rewrite <- H0. rewrite Val.or_assoc. auto.
(* xorimm - xorimm *)
  UseGetSound; simpl. rewrite <- H0. rewrite Val.xor_assoc. auto.
(* cmp *)
  simpl. decEq; decEq. eapply combine_cond_sound; eauto.
Qed.

End COMBINE.

End WITHMEM.


Require Import String Omega List FunctionalExtensionality Ensembles
        Sorting.Permutation
        Computation ADT ADTRefinement ADTNotation BuildADTRefinements
        QueryStructureSchema QueryStructure
        EnsembleListEquivalence
        QueryQSSpecs InsertQSSpecs EmptyQSSpecs DeleteQSSpecs
        QueryStructureNotations
        GeneralQueryRefinements GeneralInsertRefinements GeneralDeleteRefinements.

Ltac subst_strings :=
  repeat match goal with
           | [ H : string |- _ ] => subst H
         end.

Ltac pose_string_ids :=
  subst_strings;
  repeat match goal with
           | |- context [String ?R ?R'] =>
             let str := fresh "StringId" in
             set (String R R') as str in *
         end.

Lemma Constructor_DropQSConstraints {MySchema} {Dom}
: forall oldConstructor (d : Dom),
    refine
      (or' <- oldConstructor d;
       {nr' |
          DropQSConstraints_AbsR (qsSchema := MySchema) or' nr'})
        (or' <- oldConstructor d;
         ret (DropQSConstraints or')).
Proof.
  unfold refine; intros; inversion_by computes_to_inv.
  repeat econstructor; eauto.
Qed.

(* Queries over an empty relation return empty lists. *)
Lemma refine_For_In_Empty  :
  forall ResultT MySchema R bod,
    refine (Query_For (@UnConstrQuery_In ResultT MySchema
                                   (DropQSConstraints (QSEmptySpec MySchema))
                                   R bod))
           (ret []).
Proof.
  intros; rewrite refine_For.
  simplify with monad laws.
  unfold In, DropQSConstraints, GetUnConstrRelation in *.
  rewrite <- ith_Bounded_imap.
  unfold QSEmptySpec; simpl rels.
  rewrite Build_EmptyRelation_IsEmpty; simpl.
  rewrite refine_pick_val with
  (A := list (IndexedTuple)) (a := [])
    by (repeat econstructor; eauto).
  simplify with monad laws.
  rewrite refine_pick_val with
  (A := list ResultT) (a := []); reflexivity.
Qed.

Lemma Ensemble_List_Equivalence_Insert {A}
: forall (a : A) (Ens : Ensemble A),
    ~ In _ Ens a ->
    refine {l |
            EnsembleListEquivalence (EnsembleInsert a Ens) l}
           (l <- { l |
                   EnsembleListEquivalence Ens l};
            ret (a :: l) ).
Proof.
  unfold EnsembleListEquivalence, refine, In,
  EnsembleInsert; intros.
  inversion_by computes_to_inv; subst; econstructor.
  simpl; intuition.
  econstructor; eauto.
  intuition; eapply H; eapply H3; eauto.
  right; eapply H3; eauto.
  right; eapply H3; eauto.
Qed.

Lemma refine_For_In_Insert
: forall ResultT MySchema R or a tup bod,
    ~ In _ (GetUnConstrRelation or R)
      {| tupleIndex := a;
         indexedTuple := tup |}
    -> refine (Query_For
                 (@UnConstrQuery_In
                    ResultT MySchema
                    (UpdateUnConstrRelation
                       or R
                       (EnsembleInsert {| tupleIndex := a;
                                          indexedTuple := tup |}
                                       (GetUnConstrRelation or R)))
                    R bod))
              (newResults <- bod tup;
               origResults <- (Query_For
                                 (@UnConstrQuery_In
                                    ResultT MySchema or R bod));
               {l | Permutation.Permutation (newResults ++ origResults) l}).
Proof.
  intros; rewrite refine_For.
  unfold UnConstrQuery_In,
  GetUnConstrRelation at 1, UpdateUnConstrRelation.
  rewrite ith_replace_BoundIndex_eq.
  unfold QueryResultComp; simplify with monad laws.
  rewrite Ensemble_List_Equivalence_Insert by eauto.
  setoid_rewrite refineEquiv_bind_bind.
  setoid_rewrite refineEquiv_bind_unit; simpl.
  simplify with monad laws.
  Transparent Query_For.
  unfold Query_For.
  repeat setoid_rewrite refineEquiv_bind_bind; simpl.
  unfold refine; intros; inversion_by computes_to_inv.
  econstructor; eauto.
  econstructor; eauto.
  econstructor; eauto.
  econstructor.
  rewrite Permutation.Permutation_app_head; eauto.
Qed.

Ltac start_honing_QueryStructure :=
  pose_string_ids;
  match goal with
      |- context [@BuildADT (QueryStructure ?Rep) _ _ _ _] =>
      hone representation using (@DropQSConstraints_AbsR Rep);
        match goal with
            |- context [Build_consDef (@Build_consSig ?Id _)
                                      (@absConstructor _ _ _ _ _)] =>
            hone constructor Id;
              [ etransitivity;
                [apply Constructor_DropQSConstraints |
                 simplify with monad laws; finish honing]
              | ]
        end; pose_string_ids;
        repeat (match goal with
                  | |- context [Build_methDef (@Build_methSig ?Id _ _)
                                              (absMethod _ (fun _ _ => Insert _ into _))] =>
                    drop constraints from insert Id
                  | |- context [Build_methDef (@Build_methSig ?Id _ _)
                                              (absMethod _ (fun _ _ => Delete _ from _ where _))] =>
                    drop constraints from delete Id
                  | |- context [Build_methDef (@Build_methSig ?Id _ _)
                                              (@absMethod _ _ _ _ _ _)] =>
                    drop constraints from query Id
                end; pose_string_ids)
  end.

Lemma refine_trivial_if_then_else :
  forall x,
    refine
      (If_Then_Else x (ret true) (ret false))
      (ret x).
Proof.
  destruct x; reflexivity.
Qed.

Tactic Notation "start" "honing" "QueryStructure" := start_honing_QueryStructure.


Definition person := Type.

Check person.
(* person : Type@{Top.1+1} *)

Definition out := Type.

Check out.
(* out : Type@{Top.2+1} *)

Definition x : person. Admitted.

Inductive W : person -> out :=.

Definition y : W x. Admitted.

Check y.
(* y : W x *)

Inductive F : person -> out :=.

Definition z : person. Admitted.

Check F z.

Definition x : F z := out.

(* The term "out" has type "Type@{Top.2+1}" while it is expected to have type
 "F z". *)


Load "foo_prot2".
 Section frame3.

(*******************************************************************************)
(* Theorem frame3ind : (phi3 0 1) ~ (phi3 1 0).
Proof. repeat unf. unfold phi3. simpl. unfold t1, t2. unfold q1_s, q2_s, q3_s; repeat unf.
       unfold q11, q12, q13, q21, q22, q23, q31, q32.
       repeat unfold admin, achecks.
       ufcma_pi1 x1.
ufcma_pi1 (x2t 0).
ufcma_pi2 (x2t 0).
ufcma_pi1 (x2ft 1).
ufcma_pi2 (x2ft 0).
ufcma_pi1 (x2t 1).
ufcma_pi2 (x2t 1).
ufcma_pi1 (x2ft 0).
repeat aply_andB_elm.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
ufcma_pi1 (x3tft 0 1).
ufcma_pi2 (x3tft 0 1).
ufcma_pi1 (x3ftt 1).
ufcma_pi1 (x3ftt 0).
ufcma_pi1 (x3ftft 0 1).
ufcma_pi2 (x3ftft 0 1).
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.

rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
rew_mupbver;aply_bver; rew_hyps; try split; try reflexivity.
(*
assert((ifb (eqm (pi1 (pi2 (pi1 (x3tft 0 1)))) (e (b 0 7) 8))
                     (ver (pk 1) (e (b 0 7) 8) (pi2 (pi2 (pi1 (x3tft 0 1)))))
                     FAlse) ## (eqm (pi1 (pi2 (pi1 (x3tft 0 1)))) (e (b 0 7) 8))).

Axiom eqbrmsg_bol :forall ( b1 b2: Bool) (n1 n2 n3 :nat ), (ifb (eqm  (Mvar n1)  (Mvar n2)) [[n3 := (Mvar n1)]]b1 b2) ## (ifb (eqm  (Mvar n1)(Mvar n2)) [[n3:= (Mvar n2)]] b1 b2).
pose proof(  eqbrmsg_bol (ver (pk 1) (e (b 0 7) 8) (Mvar 2) ) FAlse 0 1 2). simpl in H.
apply Forall_ELM_EVAL_B3 with (n:= 0) (b:= (pi1 (pi2 (pi1 (x3tft 0 1))))) in H. simpl in H.

apply Forall_ELM_EVAL_B3 with (n:= 1) (b:= (e (b 0 7) 8)) in H. simpl in H.
rewrite correctness with (n:= 1) (t:= (e (b 0 7) 8)) in H. *)
       apply IFBRANCH_M3 with (ml1:= phi0) (ml2:= phi0). simpl.
       apply IFBRANCH_M2 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
    msg (pk 1, (e (b 0 7) 8, sign (sk 1) (e (b 0 7) 8)))]) (ml2:=  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
   msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
   msg (pk 1, (e (b 1 7) 8, sign (sk 1) (e (b 1 7) 8)))]).
       simpl.
apply IFBRANCH_M1 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
    msg (pk 1, (e (b 0 7) 8, sign (sk 1) (e (b 0 7) 8)));
    bol (eqm (to (x2t 0)) (V 2));
    msg (pk 2, (e (b 1 11) 12, sign (sk 2) (e (b 1 11) 12)))]) (ml2:=  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
   msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
   msg (pk 1, (e (b 1 7) 8, sign (sk 1) (e (b 1 7) 8)));
   bol (eqm (to (x2t 1)) (V 2));
   msg (pk 2, (e (b 0 11) 12, sign (sk 2) (e (b 0 11) 12)))]). simpl.
ufcma_pi1 (x3tft 1 0).
ufcma_pi2 (x3tft 1 0).
apply IFBRANCH_M1 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
    msg (pk 1, (e (b 0 7) 8, sign (sk 1) (e (b 0 7) 8)));
    bol (eqm (to (x2t 0)) (V 2));
    msg (pk 2, (e (b 1 11) 12, sign (sk 2) (e (b 1 11) 12)));
    bol (eqm (to (x3tft 0 1)) (pk 3))]) (ml2:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
   msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
   msg (pk 1, (e (b 1 7) 8, sign (sk 1) (e (b 1 7) 8)));
   bol (eqm (to (x2t 1)) (V 2));
   msg (pk 2, (e (b 0 11) 12, sign (sk 2) (e (b 0 11) 12)));
   bol (eqm (to (x3tft 1 0)) (pk 3))]). simpl.
apply IFBRANCH_M1 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
    msg (pk 1, (e (b 0 7) 8, sign (sk 1) (e (b 0 7) 8)));
    bol (eqm (to (x2t 0)) (V 2));
    msg (pk 2, (e (b 1 11) 12, sign (sk 2) (e (b 1 11) 12)));
    bol (eqm (to (x3tft 0 1)) (pk 3));
    bol
      (ifb (eqm (pi1 (pi2 (pi1 (x3tft 0 1)))) (e (b 0 7) 8))
         (ver (pk 1) (e (b 0 7) 8) (pi2 (pi2 (pi1 (x3tft 0 1))))) FAlse)]) (ml2:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
   msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
   msg (pk 1, (e (b 1 7) 8, sign (sk 1) (e (b 1 7) 8)));
   bol (eqm (to (x2t 1)) (V 2));
   msg (pk 2, (e (b 0 11) 12, sign (sk 2) (e (b 0 11) 12)));
   bol (eqm (to (x3tft 1 0)) (pk 3));
   bol
     (ifb (eqm (pi1 (pi2 (pi1 (x3tft 1 0)))) (e (b 1 7) 8))
        (ver (pk 1) (e (b 1 7) 8) (pi2 (pi2 (pi1 (x3tft 1 0))))) FAlse)]). simpl.
aply_blindness 3 8 12 0 1 (b 0 7) (b 1 11)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] .
aplyprojn 1 16 H; try split; try reflexivity.
rep_commits 0 1 11 21 7 22 fr1 fr2 temp H H0.
rename H0 into H.
appconst H.
x1checks x1 x1 H.
funapp_vtrm 1 0 1 7 8 H.
x1checks (x2t 0 ) (x2t 1) H.
funapp_vtrm 2 1 0 11 12 H.
x1checks (x3tft 0 1) (x3tft 1 0) H.
adminchecks (x3tft 0 1) (x3tft 1 0) H.
ver_suc 1 (pi1 (x3tft 0 1)) (e (b 0 7) 8) (pi1 (x3tft 1 0)) (e (b 1 7) 8) H.
ver_suc 2 (pi2 (x3tft 0 1)) (e (b 1 11) 12) (pi2 (x3tft 1 0)) (e (b 0 11) 12) H.
restrsublis H.
(** subgoal 2 *)

simpl.
aply_blindness 3 8 12 0 1 (b 0 7) (b 1 11)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] .
aplyprojn 1 16 H; try split; try reflexivity.
rep_commits 0 1 11 21 7 22 fr1 fr2 temp H H0.
rename H0 into H.
appconst H.
x1checks x1 x1 H.
funapp_vtrm 1 0 1 7 8 H.
x1checks (x2t 0 ) (x2t 1) H.
funapp_vtrm 2 1 0 11 12 H.
x1checks (x3tft 0 1) (x3tft 1 0) H.
adminchecks (x3tft 0 1) (x3tft 1 0) H.
 ver_suc 1 (pi1 (x3tft 0 1)) (e (b 0 7) 8) (pi1 (x3tft 1 0)) (e (b 1 7) 8) H.
ver_suc 2 (pi2 (x3tft 0 1)) (e (b 1 11) 12) (pi2 (x3tft 1 0)) (e (b 0 11) 12) H.

restrsublis H.
(** subgoal 3*)
simpl.
simpl.
aply_blindness 3 8 12 0 1 (b 0 7) (b 1 11)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] .
aplyprojn 1 16 H; try split; try reflexivity.
rep_commits 0 1 11 21 7 22 fr1 fr2 temp H H0.
rename H0 into H.
appconst H.
x1checks x1 x1 H.
funapp_vtrm 1 0 1 7 8 H.
x1checks (x2t 0 ) (x2t 1) H.
funapp_vtrm 2 1 0 11 12 H.
x1checks (x3tft 0 1) (x3tft 1 0) H.
adminchecks (x3tft 0 1) (x3tft 1 0) H.
 ver_suc 1 (pi1 (x3tft 0 1)) (e (b 0 7) 8) (pi1 (x3tft 1 0)) (e (b 1 7) 8) H.
ver_suc 2 (pi2 (x3tft 0 1)) (e (b 1 11) 12) (pi2 (x3tft 1 0)) (e (b 0 11) 12) H.
restrsublis H.
(** subgola 4 *)
simpl.
aply_blindness 3 8 12 0 1 (b 0 7) (b 1 11)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] .
aplyprojn 1 16 H; try split; try reflexivity.
rep_commits 0 1 11 21 7 22 fr1 fr2 temp H H0.
rename H0 into H.
appconst H.
x1checks x1 x1 H.
funapp_vtrm 1 0 1 7 8 H.
x1checks (x2t 0 ) (x2t 1) H.
funapp_vtrm 2 1 0 11 12 H.
x1checks (x3tft 0 1) (x3tft 1 0) H.
adminchecks (x3tft 0 1) (x3tft 1 0) H.
restrsublis H.
(** subgoal *)

simpl.
aply_blindness 3 8 12 0 1 (b 0 7) (b 1 7)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] .
aplyprojn 2 15 H; try split; try reflexivity.
appconst H.
x1checks x1 x1 H.
funapp_vtrm 1 0 1 7 8 H.
x1checks (x2t 0 ) (x2t 1) H.
restrsublis H.
(** subgoal *)
simpl.
ufcma_pi1 (x3ftft 1 0).
ufcma_pi2 (x3ftft 1 0).
apply IFBRANCH_M3 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1))]) (ml2:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                             msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1))]).
simpl.
apply IFBRANCH_M2 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
    bol (eqm (to x1) (V 2));
    msg (pk 2, (e (b 1 9) 10, sign (sk 2) (e (b 1 9) 10)))]) (ml2:=  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
   msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
   bol (eqm (to x1) (V 2));
   msg (pk 2, (e (b 0 9) 10, sign (sk 2) (e (b 0 9) 10)))]).
simpl.
apply IFBRANCH_M1 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
    bol (eqm (to x1) (V 2));
    msg (pk 2, (e (b 1 9) 10, sign (sk 2) (e (b 1 9) 10)));
    bol (eqm (to (x2ft 1)) (V 1));
    msg (pk 1, (e (b 0 13) 14, sign (sk 1) (e (b 0 13) 14)))]) (ml2:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
   msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
   bol (eqm (to x1) (V 2));
   msg (pk 2, (e (b 0 9) 10, sign (sk 2) (e (b 0 9) 10)));
   bol (eqm (to (x2ft 0)) (V 1));
   msg (pk 1, (e (b 1 13) 14, sign (sk 1) (e (b 1 13) 14)))]).
simpl.
apply IFBRANCH_M1 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
    bol (eqm (to x1) (V 2));
    msg (pk 2, (e (b 1 9) 10, sign (sk 2) (e (b 1 9) 10)));
    bol (eqm (to (x2ft 1)) (V 1));
    msg (pk 1, (e (b 0 13) 14, sign (sk 1) (e (b 0 13) 14)));
    bol (eqm (to (x3ftft 0 1)) (pk 3))]) (ml2:=  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
   msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
   bol (eqm (to x1) (V 2));
   msg (pk 2, (e (b 0 9) 10, sign (sk 2) (e (b 0 9) 10)));
   bol (eqm (to (x2ft 0)) (V 1));
   msg (pk 1, (e (b 1 13) 14, sign (sk 1) (e (b 1 13) 14)));
   bol (eqm (to (x3ftft 1 0)) (pk 3))]).
simpl.
apply IFBRANCH_M1 with (ml1:= [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
    msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
    bol (eqm (to x1) (V 2));
    msg (pk 2, (e (b 1 9) 10, sign (sk 2) (e (b 1 9) 10)));
    bol (eqm (to (x2ft 1)) (V 1));
    msg (pk 1, (e (b 0 13) 14, sign (sk 1) (e (b 0 13) 14)));
    bol (eqm (to (x3ftft 0 1)) (pk 3));
    bol
      (ifb (eqm (pi1 (pi2 (pi1 (x3ftft 0 1)))) (e (b 0 13) 14))
         (ver (pk 1) (e (b 0 13) 14) (pi2 (pi2 (pi1 (x3ftft 0 1))))) FAlse)]) (ml2:=  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
   msg (nonce 4); msg (pk 5); bol (eqm (to x1) (V 1));
   bol (eqm (to x1) (V 2));
   msg (pk 2, (e (b 0 9) 10, sign (sk 2) (e (b 0 9) 10)));
   bol (eqm (to (x2ft 0)) (V 1));
   msg (pk 1, (e (b 1 13) 14, sign (sk 1) (e (b 1 13) 14)));
   bol (eqm (to (x3ftft 1 0)) (pk 3));
   bol
     (ifb (eqm (pi1 (pi2 (pi1 (x3ftft 1 0)))) (e (b 1 13) 14))
          (ver (pk 1) (e (b 1 13) 14) (pi2 (pi2 (pi1 (x3ftft 1 0))))) FAlse)]); try repeat
  (aply_blindness 3 10 14 0 1 (b 1 9) (b 0 13)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] ; simpl;
aplyprojn 1 16 H; try split; try reflexivity;
rep_commits 1 0 13 21 9 22 fr1 fr2 temp H H0;
rename H0 into H;
appconst H;
x1checks x1 x1 H;
funapp_vtrm 2 1 0 9 10 H;
funapp_vtrm 1 0 1 13 14 H;
x1checks (x2ft 1 ) (x2ft 0) H;
x1checks (x3ftft 0 1) (x3ftft 1 0) H;
adminchecks (x3ftft 0 1) (x3ftft 1 0) H;
ver_suc 1 (pi1 (x3ftft 0 1)) (e (b 0 13) 14) (pi1 (x3ftft 1 0)) (e (b 1 13) 14) H;
ver_suc 2 (pi2 (x3ftft 0 1)) (e (b 1 9) 10) (pi2 (x3ftft 1 0)) (e (b 0 9) 10) H;
restrsublis H).

(** subgoal *)
  (aply_blindness 3 10 14 0 1 (b 1 9) (b 0 13)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] ; simpl;
aplyprojn 1 16 H; try split; try reflexivity;
rep_commits 1 0 13 21 9 22 fr1 fr2 temp H H0;
rename H0 into H;
appconst H;
x1checks x1 x1 H;
funapp_vtrm 2 1 0 9 10 H;
funapp_vtrm 1 0 1 13 14 H;
x1checks (x2ft 1 ) (x2ft 0) H;
x1checks (x3ftft 0 1) (x3ftft 1 0) H;
adminchecks (x3ftft 0 1) (x3ftft 1 0) H;
ver_suc 1 (pi1 (x3ftft 0 1)) (e (b 0 13) 14) (pi1 (x3ftft 1 0)) (e (b 1 13) 14) H;
ver_suc 2 (pi2 (x3ftft 0 1)) (e (b 1 9) 10) (pi2 (x3ftft 1 0)) (e (b 0 9) 10) H;
restrsublis H). try  (aply_blindness 3 10 14 0 1 (b 1 9) (b 0 13)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] ; simpl;
aplyprojn 1 16 H; try split; try reflexivity;
rep_commits 1 0 13 21 9 22 fr1 fr2 temp H H0;
rename H0 into H;
appconst H;
x1checks x1 x1 H;
funapp_vtrm 2 1 0 9 10 H;
funapp_vtrm 1 0 1 13 14 H;
x1checks (x2ft 1 ) (x2ft 0) H;
x1checks (x3ftft 0 1) (x3ftft 1 0) H;
adminchecks (x3ftft 0 1) (x3ftft 1 0) H;
ver_suc 1 (pi1 (x3ftft 0 1)) (e (b 0 13) 14) (pi1 (x3ftft 1 0)) (e (b 1 13) 14) H;
ver_suc 2 (pi2 (x3ftft 0 1)) (e (b 1 9) 10) (pi2 (x3ftft 1 0)) (e (b 0 9) 10) H;
restrsublis H).

   (aply_blindness 3 10 14 0 1 (b 1 9) (b 0 13)  ((Mvar 0), (Mvar 1)) ((Mvar 0), (Mvar 1))  [msg (pk 0); msg (pk 1); msg (pk 2); msg (pk 3);
                                                                                msg (nonce 4); msg (pk 5); msg (sk 1); msg (sk 2); msg (sk 3) ] ; simpl;
aplyprojn 1 16 H; try split; try reflexivity;
rep_commits 1 0 13 21 9 22 fr1 fr2 temp H H0;
rename H0 into H;
appconst H;
x1checks x1 x1 H;
funapp_vtrm 2 1 0 9 10 H;
funapp_vtrm 1 0 1 13 14 H;
x1checks (x2ft 1 ) (x2ft 0) H;
x1checks (x3ftft 0 1) (x3ftft 1 0) H;
adminchecks (x3ftft 0 1) (x3ftft 1 0) H;
ver_suc 1 (pi1 (x3ftft 0 1)) (e (b 0 13) 14) (pi1 (x3ftft 1 0)) (e (b 1 13) 14) H;
ver_suc 2 (pi2 (x3ftft 0 1)) (e (b 1 9) 10) (pi2 (x3ftft 1 0)) (e (b 0 9) 10) H;
restrsublis H). reflexivity.
Qed. *)
End frame3.