diff --git a/thys/LambdaAuth/Agreement.thy b/thys/LambdaAuth/Agreement.thy --- a/thys/LambdaAuth/Agreement.thy +++ b/thys/LambdaAuth/Agreement.thy @@ -1,515 +1,515 @@ (* Author: Matthias Brun, ETH Zürich, 2019 *) (* Author: Dmitriy Traytel, ETH Zürich, 2019 *) section \Agreement Relation\ (*<*) theory Agreement imports Semantics begin (*>*) inductive agree :: "tyenv \ term \ term \ term \ ty \ bool" ("_ \ _, _, _ : _" [150,0,0,0,150] 149) where a_Unit: "\ \ Unit, Unit, Unit : One" | a_Var: "\ $$ x = Some \ \ \ \ Var x, Var x, Var x : \" | a_Lam: "\ atom x \ \; \(x $$:= \\<^sub>1) \ e, eP, eV : \\<^sub>2 \ \ \ \ Lam x e, Lam x eP, Lam x eV : Fun \\<^sub>1 \\<^sub>2" | a_App: "\ \ \ e\<^sub>1, eP\<^sub>1, eV\<^sub>1 : Fun \\<^sub>1 \\<^sub>2; \ \ e\<^sub>2, eP\<^sub>2, eV\<^sub>2 : \\<^sub>1 \ \ \ \ App e\<^sub>1 e\<^sub>2, App eP\<^sub>1 eP\<^sub>2, App eV\<^sub>1 eV\<^sub>2 : \\<^sub>2" | a_Let: "\ atom x \ (\, e\<^sub>1, eP\<^sub>1, eV\<^sub>1); \ \ e\<^sub>1, eP\<^sub>1, eV\<^sub>1 : \\<^sub>1; \(x $$:= \\<^sub>1) \ e\<^sub>2, eP\<^sub>2, eV\<^sub>2 : \\<^sub>2 \ \ \ \ Let e\<^sub>1 x e\<^sub>2, Let eP\<^sub>1 x eP\<^sub>2, Let eV\<^sub>1 x eV\<^sub>2 : \\<^sub>2" | a_Rec: "\ atom x \ \; atom y \ (\,x); \(x $$:= Fun \\<^sub>1 \\<^sub>2) \ Lam y e, Lam y eP, Lam y eV : Fun \\<^sub>1 \\<^sub>2 \ \ \ \ Rec x (Lam y e), Rec x (Lam y eP), Rec x (Lam y eV) : Fun \\<^sub>1 \\<^sub>2" | a_Inj1: "\ \ \ e, eP, eV : \\<^sub>1 \ \ \ \ Inj1 e, Inj1 eP, Inj1 eV : Sum \\<^sub>1 \\<^sub>2" | a_Inj2: "\ \ \ e, eP, eV : \\<^sub>2 \ \ \ \ Inj2 e, Inj2 eP, Inj2 eV : Sum \\<^sub>1 \\<^sub>2" | a_Case: "\ \ \ e, eP, eV : Sum \\<^sub>1 \\<^sub>2; \ \ e\<^sub>1, eP\<^sub>1, eV\<^sub>1 : Fun \\<^sub>1 \; \ \ e\<^sub>2, eP\<^sub>2, eV\<^sub>2 : Fun \\<^sub>2 \ \ \ \ \ Case e e\<^sub>1 e\<^sub>2, Case eP eP\<^sub>1 eP\<^sub>2, Case eV eV\<^sub>1 eV\<^sub>2 : \" | a_Pair: "\ \ \ e\<^sub>1, eP\<^sub>1, eV\<^sub>1 : \\<^sub>1; \ \ e\<^sub>2, eP\<^sub>2, eV\<^sub>2 : \\<^sub>2 \ \ \ \ Pair e\<^sub>1 e\<^sub>2, Pair eP\<^sub>1 eP\<^sub>2, Pair eV\<^sub>1 eV\<^sub>2 : Prod \\<^sub>1 \\<^sub>2" | a_Prj1: "\ \ \ e, eP, eV : Prod \\<^sub>1 \\<^sub>2 \ \ \ \ Prj1 e, Prj1 eP, Prj1 eV : \\<^sub>1" | a_Prj2: "\ \ \ e, eP, eV : Prod \\<^sub>1 \\<^sub>2 \ \ \ \ Prj2 e, Prj2 eP, Prj2 eV : \\<^sub>2" | a_Roll: "\ atom \ \ \; \ \ e, eP, eV : subst_type \ (Mu \ \) \ \ \ \ \ Roll e, Roll eP, Roll eV : Mu \ \" | a_Unroll: "\ atom \ \ \; \ \ e, eP, eV : Mu \ \ \ \ \ \ Unroll e, Unroll eP, Unroll eV : subst_type \ (Mu \ \) \" | a_Auth: "\ \ \ e, eP, eV : \ \ \ \ \ Auth e, Auth eP, Auth eV : AuthT \" | a_Unauth: "\ \ \ e, eP, eV : AuthT \ \ \ \ \ Unauth e, Unauth eP, Unauth eV : \" | a_HashI: "\ {$$} \ v, vP, \vP\ : \; hash \vP\ = h; value v; value vP \ \ \ \ v, Hashed h vP, Hash h : AuthT \" declare agree.intros[intro] equivariance agree nominal_inductive agree avoids a_Lam: x | a_Rec: x and y | a_Let: x | a_Roll: \ | a_Unroll: \ by (auto simp: fresh_Pair fresh_subst_type) lemma Abs_lst_eq_3tuple: fixes x x' :: var fixes e eP eV e' eP' eV' :: "term" assumes "[[atom x]]lst. e = [[atom x']]lst. e'" and "[[atom x]]lst. eP = [[atom x']]lst. eP'" and "[[atom x]]lst. eV = [[atom x']]lst. eV'" shows "[[atom x]]lst. (e, eP, eV) = [[atom x']]lst. (e', eP', eV')" using assms by (simp add: fresh_Pair) lemma agree_fresh_env_fresh_term: fixes a :: var assumes "\ \ e, eP, eV : \" "atom a \ \" shows "atom a \ (e, eP, eV)" using assms proof (nominal_induct \ e eP eV \ avoiding: a rule: agree.strong_induct) case (a_Var \ x \) then show ?case by (cases "a = x") (auto simp: fresh_tyenv_None) qed (simp_all add: fresh_Cons fresh_fmap_update fresh_Pair) lemma agree_empty_fresh[dest]: fixes a :: var assumes "{$$} \ e, eP, eV : \" shows "{atom a} \* {e, eP, eV}" using assms by (auto simp: fresh_Pair dest: agree_fresh_env_fresh_term) text \Inversion rules for agreement.\ declare [[simproc del: alpha_lst]] lemma a_Lam_inv_I[elim]: assumes "\ \ (Lam x e'), eP, eV : (Fun \\<^sub>1 \\<^sub>2)" and "atom x \ \" obtains eP' eV' where "eP = Lam x eP'" "eV = Lam x eV'" "\(x $$:= \\<^sub>1) \ e', eP', eV' : \\<^sub>2" using assms proof (atomize_elim, nominal_induct \ "Lam x e'" eP eV "Fun \\<^sub>1 \\<^sub>2" avoiding: x e' \\<^sub>1 \\<^sub>2 rule: agree.strong_induct) case (a_Lam x \ \\<^sub>1 e eP eV \\<^sub>2 y e') show ?case proof (intro exI conjI) from a_Lam show "Lam x eP = Lam y ((x \ y) \ eP)" by (auto intro!: Abs_lst_eq_flipI dest!: agree_fresh_env_fresh_term simp: fresh_fmap_update fresh_Pair) from a_Lam show "Lam x eV = Lam y ((x \ y) \ eV)" by (auto intro!: Abs_lst_eq_flipI dest!: agree_fresh_env_fresh_term simp: fresh_fmap_update fresh_Pair) from a_Lam(1-6,8,10) show "\(y $$:= \\<^sub>1) \ e', (x \ y) \ eP, (x \ y) \ eV : \\<^sub>2" by (auto simp: perm_supp_eq Abs1_eq_iff(3) dest!: agree.eqvt[where p = "(x \ y)", of "\(x $$:= \\<^sub>1)"]) qed qed lemma a_Lam_inv_P[elim]: assumes "{$$} \ v, (Lam x vP'), vV : (Fun \\<^sub>1 \\<^sub>2)" obtains v' vV' where "v = Lam x v'" "vV = Lam x vV'" "{$$}(x $$:= \\<^sub>1) \ v', vP', vV' : \\<^sub>2" - using assms + using assms proof (atomize_elim, nominal_induct "{$$}::tyenv" v "Lam x vP'" vV "Fun \\<^sub>1 \\<^sub>2" avoiding: x vP' rule: agree.strong_induct) case (a_Lam x' e eP eV) show ?case proof (intro exI conjI) from a_Lam show "Lam x' e = Lam x ((x' \ x) \ e)" by (auto intro!: Abs_lst_eq_flipI dest!: agree_fresh_env_fresh_term simp: fresh_fmap_update fresh_Pair) from a_Lam show "Lam x' eV = Lam x ((x' \ x) \ eV)" by (auto intro!: Abs_lst_eq_flipI dest!: agree_fresh_env_fresh_term simp: fresh_fmap_update fresh_Pair) from a_Lam(1-4,6) show "{$$}(x $$:= \\<^sub>1) \ (x' \ x) \ e, vP', (x' \ x) \ eV : \\<^sub>2" by (auto simp: perm_supp_eq Abs1_eq_iff(3) dest!: agree.eqvt[where p = "(x' \ x)", of "{$$}(x' $$:= \\<^sub>1)"]) qed qed lemma a_Lam_inv_V[elim]: assumes "{$$} \ v, vP, (Lam x vV') : (Fun \\<^sub>1 \\<^sub>2)" obtains v' vP' where "v = Lam x v'" "vP = Lam x vP'" "{$$}(x $$:= \\<^sub>1) \ v', vP', vV' : \\<^sub>2" using assms proof (atomize_elim, nominal_induct "{$$}::tyenv" v vP "Lam x vV'" "Fun \\<^sub>1 \\<^sub>2" avoiding: x vV' rule: agree.strong_induct) case (a_Lam x' e eP eV) show ?case proof (intro exI conjI) from a_Lam show "Lam x' e = Lam x ((x' \ x) \ e)" by (auto intro!: Abs_lst_eq_flipI dest!: agree_fresh_env_fresh_term simp: fresh_fmap_update fresh_Pair) from a_Lam show "Lam x' eP = Lam x ((x' \ x) \ eP)" by (auto intro!: Abs_lst_eq_flipI dest!: agree_fresh_env_fresh_term simp: fresh_fmap_update fresh_Pair) from a_Lam(1-4,6) show "{$$}(x $$:= \\<^sub>1) \ (x' \ x) \ e, (x' \ x) \ eP, vV' : \\<^sub>2" by (auto simp: perm_supp_eq Abs1_eq_iff(3) dest!: agree.eqvt[where p = "(x' \ x)", of "{$$}(x' $$:= \\<^sub>1)"]) qed qed lemma a_Rec_inv_I[elim]: assumes "\ \ Rec x e, eP, eV : Fun \\<^sub>1 \\<^sub>2" and "atom x \ \" obtains y e' eP' eV' where "e = Lam y e'" "eP = Rec x (Lam y eP')" "eV = Rec x (Lam y eV')" "atom y \ (\,x)" "\(x $$:= Fun \\<^sub>1 \\<^sub>2) \ Lam y e', Lam y eP', Lam y eV' : Fun \\<^sub>1 \\<^sub>2" using assms proof (atomize_elim, nominal_induct \ "Rec x e" eP eV "Fun \\<^sub>1 \\<^sub>2" avoiding: x e rule: agree.strong_induct) case (a_Rec x' \ y e' eP eV) then show ?case proof (nominal_induct e avoiding: x x' y rule: term.strong_induct) case Unit from Unit(9) show ?case by (simp add: Abs1_eq_iff) next case (Var x) from Var(9) show ?case by (simp add: Abs1_eq_iff) next case (Lam z ee) show ?case proof (intro conjI exI) from Lam(1-3,5-13,15) show "Lam z ee = Lam y ((z \ y) \ ee)" by (auto intro: Abs_lst_eq_flipI simp: fresh_fmap_update fresh_Pair) from Lam(1-3,5-13,15) show "Rec x' (Lam y eP) = Rec x (Lam y ((x' \ x) \ eP))" using Abs_lst_eq_flipI[of x "Lam y eP" x'] by (elim agree_fresh_env_fresh_term[where a = x, elim_format]) (simp_all add: fresh_fmap_update fresh_Pair) from Lam(1-3,5-13,15) show "Rec x' (Lam y eV) = Rec x (Lam y ((x' \ x) \ eV))" using Abs_lst_eq_flipI[of x "Lam y eV" x'] by (elim agree_fresh_env_fresh_term[where a = x, elim_format]) (simp_all add: fresh_fmap_update fresh_Pair) from Lam(7,10) show "atom y \ (\, x)" by simp from Lam(1-3,5-11,13) have "(x' \ x) \ e' = (z \ y) \ ee" by (simp add: Abs1_eq_iff flip_commute swap_permute_swap fresh_perm fresh_at_base) with Lam(1-2,7,9,11-12,15) show "\(x $$:= Fun \\<^sub>1 \\<^sub>2) \ Lam y ((z \ y) \ ee), Lam y ((x' \ x) \ eP), Lam y ((x' \ x) \ eV) : Fun \\<^sub>1 \\<^sub>2" by (elim agree.eqvt[of _ "Lam y e'" _ _ _ "(x' \ x)", elim_format]) (simp add: perm_supp_eq) qed next case (Rec x1 x2a) from Rec(13) show ?case by (simp add: Abs1_eq_iff) next case (Inj1 x) from Inj1(10) show ?case by (simp add: Abs1_eq_iff) next case (Inj2 x) from Inj2(10) show ?case by (simp add: Abs1_eq_iff) next case (Pair x1 x2a) from Pair(11) show ?case by (simp add: Abs1_eq_iff) next case (Roll x) from Roll(10) show ?case by (simp add: Abs1_eq_iff) next case (Let x1 x2a x3) from Let(14) show ?case by (simp add: Abs1_eq_iff) next case (App x1 x2a) from App(11) show ?case by (simp add: Abs1_eq_iff) next case (Case x1 x2a x3) from Case(12) show ?case by (simp add: Abs1_eq_iff) next case (Prj1 x) from Prj1(10) show ?case by (simp add: Abs1_eq_iff) next case (Prj2 x) from Prj2(10) show ?case by (simp add: Abs1_eq_iff) next case (Unroll x) from Unroll(10) show ?case by (simp add: Abs1_eq_iff) next case (Auth x) from Auth(10) show ?case by (simp add: Abs1_eq_iff) next case (Unauth x) from Unauth(10) show ?case by (simp add: Abs1_eq_iff) next case (Hash x) from Hash(9) show ?case by (simp add: Abs1_eq_iff) next case (Hashed x1 x2a) from Hashed(10) show ?case by (simp add: Abs1_eq_iff) qed qed lemma a_Rec_inv_P[elim]: assumes "\ \ e, Rec x eP, eV : Fun \\<^sub>1 \\<^sub>2" and "atom x \ \" obtains y e' eP' eV' where "e = Rec x (Lam y e')" "eP = Lam y eP'" "eV = Rec x (Lam y eV')" "atom y \ (\,x)" "\(x $$:= Fun \\<^sub>1 \\<^sub>2) \ Lam y e', Lam y eP', Lam y eV' : Fun \\<^sub>1 \\<^sub>2" using assms proof (atomize_elim,nominal_induct \ e "Rec x eP" eV "Fun \\<^sub>1 \\<^sub>2" avoiding: x eP rule: agree.strong_induct) case (a_Rec x \ y e eP eV x' eP') then show ?case proof (nominal_induct eP' avoiding: x' x y rule: term.strong_induct) case Unit from Unit(9) show ?case by (simp add: Abs1_eq_iff) next case (Var x) from Var(9) show ?case by (simp add: Abs1_eq_iff) next case (Lam ya eP') show ?case proof (intro conjI exI) from Lam(1-3,5-13,15) show "Rec x (Lam y e) = Rec x' (Lam y ((x \ x') \ e))" using Abs_lst_eq_flipI[of x' "Lam y e" x] by (elim agree_fresh_env_fresh_term[where a = x', elim_format]) (simp_all add: fresh_fmap_update fresh_Pair) from Lam(1-3,5-13,15) show "Lam ya eP' = Lam y ((x \ x') \ eP)" unfolding trans[OF eq_sym_conv Abs1_eq_iff(3)] by (simp add: flip_commute fresh_at_base) from Lam(1-3,5-13,15) show "Rec x (Lam y eV) = Rec x' (Lam y ((x \ x') \ eV))" using Abs_lst_eq_flipI[of x' "Lam y eV" x] by (elim agree_fresh_env_fresh_term[where a = x', elim_format]) (simp_all add: fresh_fmap_update fresh_Pair) from Lam(7,10) show "atom y \ (\, x')" by simp with Lam(1-2,7,9,11-12,15) show "\(x' $$:= Fun \\<^sub>1 \\<^sub>2) \ Lam y ((x \ x') \ e), Lam y ((x \ x') \ eP), Lam y ((x \ x') \ eV) : Fun \\<^sub>1 \\<^sub>2" by (elim agree.eqvt[of _ "Lam y _" _ _ _ "(x' \ x)", elim_format]) (simp add: perm_supp_eq flip_commute) qed next case (Rec x1 x2a) from Rec(13) show ?case by (simp add: Abs1_eq_iff) next case (Inj1 x) from Inj1(10) show ?case by (simp add: Abs1_eq_iff) next case (Inj2 x) from Inj2(10) show ?case by (simp add: Abs1_eq_iff) next case (Pair x1 x2a) from Pair(11) show ?case by (simp add: Abs1_eq_iff) next case (Roll x) from Roll(10) show ?case by (simp add: Abs1_eq_iff) next case (Let x1 x2a x3) from Let(14) show ?case by (simp add: Abs1_eq_iff) next case (App x1 x2a) from App(11) show ?case by (simp add: Abs1_eq_iff) next case (Case x1 x2a x3) from Case(12) show ?case by (simp add: Abs1_eq_iff) next case (Prj1 x) from Prj1(10) show ?case by (simp add: Abs1_eq_iff) next case (Prj2 x) from Prj2(10) show ?case by (simp add: Abs1_eq_iff) next case (Unroll x) from Unroll(10) show ?case by (simp add: Abs1_eq_iff) next case (Auth x) from Auth(10) show ?case by (simp add: Abs1_eq_iff) next case (Unauth x) from Unauth(10) show ?case by (simp add: Abs1_eq_iff) next case (Hash x) from Hash(9) show ?case by (simp add: Abs1_eq_iff) next case (Hashed x1 x2a) from Hashed(10) show ?case by (simp add: Abs1_eq_iff) qed qed lemma a_Rec_inv_V[elim]: assumes "\ \ e, eP, Rec x eV : Fun \\<^sub>1 \\<^sub>2" and "atom x \ \" obtains y e' eP' eV' where "e = Rec x (Lam y e')" "eP = Rec x (Lam y eP')" "eV = Lam y eV'" "atom y \ (\,x)" "\(x $$:= Fun \\<^sub>1 \\<^sub>2) \ Lam y e', Lam y eP', Lam y eV' : Fun \\<^sub>1 \\<^sub>2" using assms proof (atomize_elim, nominal_induct \ e eP "Rec x eV" "Fun \\<^sub>1 \\<^sub>2" avoiding: x eV rule: agree.strong_induct) case (a_Rec x \ y e eP eV x' eV') then show ?case proof (nominal_induct eV' avoiding: x' x y rule: term.strong_induct) case Unit from Unit(9) show ?case by (simp add: Abs1_eq_iff) next case (Var x) from Var(9) show ?case by (simp add: Abs1_eq_iff) next case (Lam ya eV') show ?case proof (intro conjI exI) from Lam(1-3,5-13,15) show "Rec x (Lam y e) = Rec x' (Lam y ((x \ x') \ e))" using Abs_lst_eq_flipI[of x' "Lam y e" x] by (elim agree_fresh_env_fresh_term[where a = x', elim_format]) (simp_all add: fresh_fmap_update fresh_Pair) from Lam(1-3,5-13,15) show "Lam ya eV' = Lam y ((x \ x') \ eV)" unfolding trans[OF eq_sym_conv Abs1_eq_iff(3)] by (simp add: flip_commute fresh_at_base) from Lam(1-3,5-13,15) show "Rec x (Lam y eP) = Rec x' (Lam y ((x \ x') \ eP))" using Abs_lst_eq_flipI[of x' "Lam y eP" x] by (elim agree_fresh_env_fresh_term[where a = x', elim_format]) (simp_all add: fresh_fmap_update fresh_Pair) from Lam(7,10) show "atom y \ (\, x')" by simp with Lam(1-2,7,9,11-12,15) show "\(x' $$:= Fun \\<^sub>1 \\<^sub>2) \ Lam y ((x \ x') \ e), Lam y ((x \ x') \ eP), Lam y ((x \ x') \ eV) : Fun \\<^sub>1 \\<^sub>2" by (elim agree.eqvt[of _ "Lam y _" _ _ _ "(x' \ x)", elim_format]) (simp add: perm_supp_eq flip_commute) qed next case (Rec x1 x2a) from Rec(13) show ?case by (simp add: Abs1_eq_iff) next case (Inj1 x) from Inj1(10) show ?case by (simp add: Abs1_eq_iff) next case (Inj2 x) from Inj2(10) show ?case by (simp add: Abs1_eq_iff) next case (Pair x1 x2a) from Pair(11) show ?case by (simp add: Abs1_eq_iff) next case (Roll x) from Roll(10) show ?case by (simp add: Abs1_eq_iff) next case (Let x1 x2a x3) from Let(14) show ?case by (simp add: Abs1_eq_iff) next case (App x1 x2a) from App(11) show ?case by (simp add: Abs1_eq_iff) next case (Case x1 x2a x3) from Case(12) show ?case by (simp add: Abs1_eq_iff) next case (Prj1 x) from Prj1(10) show ?case by (simp add: Abs1_eq_iff) next case (Prj2 x) from Prj2(10) show ?case by (simp add: Abs1_eq_iff) next case (Unroll x) from Unroll(10) show ?case by (simp add: Abs1_eq_iff) next case (Auth x) from Auth(10) show ?case by (simp add: Abs1_eq_iff) next case (Unauth x) from Unauth(10) show ?case by (simp add: Abs1_eq_iff) next case (Hash x) from Hash(9) show ?case by (simp add: Abs1_eq_iff) next case (Hashed x1 x2a) from Hashed(10) show ?case by (simp add: Abs1_eq_iff) qed qed inductive_cases a_Inj1_inv_I[elim]: "\ \ Inj1 e, eP, eV : Sum \\<^sub>1 \\<^sub>2" inductive_cases a_Inj1_inv_P[elim]: "\ \ e, Inj1 eP, eV : Sum \\<^sub>1 \\<^sub>2" inductive_cases a_Inj1_inv_V[elim]: "\ \ e, eP, Inj1 eV : Sum \\<^sub>1 \\<^sub>2" inductive_cases a_Inj2_inv_I[elim]: "\ \ Inj2 e, eP, eV : Sum \\<^sub>1 \\<^sub>2" inductive_cases a_Inj2_inv_P[elim]: "\ \ e, Inj2 eP, eV : Sum \\<^sub>1 \\<^sub>2" inductive_cases a_Inj2_inv_V[elim]: "\ \ e, eP, Inj2 eV : Sum \\<^sub>1 \\<^sub>2" inductive_cases a_Pair_inv_I[elim]: "\ \ Pair e\<^sub>1 e\<^sub>2, eP, eV : Prod \\<^sub>1 \\<^sub>2" inductive_cases a_Pair_inv_P[elim]: "\ \ e, Pair eP\<^sub>1 eP\<^sub>2, eV : Prod \\<^sub>1 \\<^sub>2" lemma a_Roll_inv_I[elim]: assumes "\ \ Roll e', eP, eV : Mu \ \" obtains eP' eV' where "eP = Roll eP'" "eV = Roll eV'" "\ \ e', eP', eV' : subst_type \ (Mu \ \) \" using assms by (nominal_induct \ "Roll e'" eP eV "Mu \ \" avoiding: \ \ rule: agree.strong_induct) (simp add: Abs1_eq(3) Abs_lst_eq_flipI subst_type_perm_eq) lemma a_Roll_inv_P[elim]: assumes "\ \ e, Roll eP', eV : Mu \ \" obtains e' eV' where "e = Roll e'" "eV = Roll eV'" "\ \ e', eP', eV' : subst_type \ (Mu \ \) \" using assms by (nominal_induct \ e "Roll eP'" eV "Mu \ \" avoiding: \ \ rule: agree.strong_induct) (simp add: Abs1_eq(3) Abs_lst_eq_flipI subst_type_perm_eq) lemma a_Roll_inv_V[elim]: assumes "\ \ e, eP, Roll eV' : Mu \ \" obtains e' eP' where "e = Roll e'" "eP = Roll eP'" "\ \ e', eP', eV' : subst_type \ (Mu \ \) \" using assms by (nominal_induct \ e eP "Roll eV'" "Mu \ \" avoiding: \ \ rule: agree.strong_induct) (simp add: Abs1_eq(3) Abs_lst_eq_flipI subst_type_perm_eq) inductive_cases a_HashI_inv[elim]: "\ \ v, Hashed (hash \vP\) vP, Hash (hash \vP\) : AuthT \" text \Inversion on types for agreement.\ lemma a_AuthT_value_inv: assumes "{$$} \ v, vP, vV : AuthT \" and "value v" "value vP" "value vV" obtains vP' where "vP = Hashed (hash \vP'\) vP'" "vV = Hash (hash \vP'\)" "value vP'" using assms by (atomize_elim, induct "{$$}::tyenv" v vP vV "AuthT \" rule: agree.induct) simp_all inductive_cases a_Mu_inv[elim]: "\ \ e, eP, eV : Mu \ \" inductive_cases a_Sum_inv[elim]: "\ \ e, eP, eV : Sum \\<^sub>1 \\<^sub>2" inductive_cases a_Prod_inv[elim]: "\ \ e, eP, eV : Prod \\<^sub>1 \\<^sub>2" inductive_cases a_Fun_inv[elim]: "\ \ e, eP, eV : Fun \\<^sub>1 \\<^sub>2" declare [[simproc add: alpha_lst]] lemma agree_weakening_1: assumes "\ \ e, eP, eV : \" "atom y \ e" "atom y \ eP" "atom y \ eV" shows "\(y $$:= \') \ e, eP, eV : \" using assms proof (nominal_induct \ e eP eV \ avoiding: y \' rule: agree.strong_induct) case (a_Lam x \ \\<^sub>1 e eP eV \\<^sub>2) then show ?case - by (force simp add: fresh_at_base fresh_fmap_update fmap_reorder_neq_updates) + by (force simp add: fresh_at_base fresh_fmap_update fmupd_reorder_neq) next case (a_App v\<^sub>1 v\<^sub>2 vP\<^sub>1 vP\<^sub>2 vV\<^sub>1 vV\<^sub>2 \ \\<^sub>1 \\<^sub>2) then show ?case using term.fresh(9) by blast next case (a_Let x \ e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2 \\<^sub>2) then show ?case - by (auto simp add: fresh_at_base fresh_Pair fresh_fmap_update fmap_reorder_neq_updates[of y x] + by (auto simp add: fresh_at_base fresh_Pair fresh_fmap_update fmupd_reorder_neq[of x y] intro!: a_Let(10) agree.a_Let[of x]) next case (a_Rec x \ z \\<^sub>1 \\<^sub>2 e eP eV) then show ?case - by (auto simp add: fresh_at_base fresh_Pair fresh_fmap_update fmap_reorder_neq_updates[of y x] + by (auto simp add: fresh_at_base fresh_Pair fresh_fmap_update fmupd_reorder_neq[of x y] intro!: a_Rec(9) agree.a_Rec[of x]) next case (a_Case v v\<^sub>1 v\<^sub>2 vP vP\<^sub>1 vP\<^sub>2 vV vV\<^sub>1 vV\<^sub>2 \ \\<^sub>1 \\<^sub>2 \) then show ?case by (fastforce simp: fresh_at_base) next case (a_Prj1 v vP vV \ \\<^sub>1 \\<^sub>2) then show ?case by (fastforce simp: fresh_at_base) next case (a_Prj2 v vP vV \ \\<^sub>1 \\<^sub>2) then show ?case by (fastforce simp: fresh_at_base) qed (auto simp: fresh_fmap_update) lemma agree_weakening_2: assumes "\ \ e, eP, eV : \" "atom y \ \" shows "\(y $$:= \') \ e, eP, eV : \" proof - from assms have "{atom y} \* {e, eP, eV}" by (auto simp: fresh_Pair dest: agree_fresh_env_fresh_term) with assms show "\(y $$:= \') \ e, eP, eV : \" by (simp add: agree_weakening_1) qed lemma agree_weakening_env: assumes "{$$} \ e, eP, eV : \" shows "\ \ e, eP, eV : \" using assms proof (induct \) case fmempty then show ?case by assumption next case (fmupd x y \) then show ?case by (simp add: fresh_tyenv_None agree_weakening_2) qed (*<*) end (*>*) \ No newline at end of file diff --git a/thys/LambdaAuth/FMap_Lemmas.thy b/thys/LambdaAuth/FMap_Lemmas.thy --- a/thys/LambdaAuth/FMap_Lemmas.thy +++ b/thys/LambdaAuth/FMap_Lemmas.thy @@ -1,197 +1,174 @@ (* Author: Matthias Brun, ETH Zürich, 2019 *) (* Author: Dmitriy Traytel, ETH Zürich, 2019 *) (*<*) theory FMap_Lemmas imports "HOL-Library.Finite_Map" Nominal2_Lemmas begin (*>*) text \Nominal setup for finite maps.\ abbreviation fmap_update ("_'(_ $$:= _')" [1000,0,0] 1000) where "fmap_update \ x \ \ fmupd x \ \" notation fmlookup (infixl "$$" 999) notation fmempty ("{$$}") instantiation fmap :: (pt, pt) pt begin unbundle fmap.lifting lift_definition permute_fmap :: "perm \ ('a, 'b) fmap \ ('a, 'b) fmap" is "permute :: perm \ ('a \ 'b) \ ('a \ 'b)" proof - fix p and f :: "'a \ 'b" assume "finite (dom f)" then show "finite (dom (p \ f))" proof (rule finite_surj[of _ _ "permute p"]; unfold dom_def, safe) fix x y assume some: "(p \ f) x = Some y" show "x \ permute p ` {a. f a \ None}" proof (rule image_eqI[of _ _ "- p \ x"]) from some show "- p \ x \ {a. f a \ None}" by (auto simp: permute_self pemute_minus_self dest: arg_cong[of _ _ "permute (- p)"] intro!: exI[of _ "- p \ y"]) qed (simp only: permute_minus_cancel) qed qed instance proof fix x :: "('a, 'b) fmap" show "0 \ x = x" by transfer simp next fix p q and x :: "('a, 'b) fmap" show "(p + q) \ x = p \ q \ x" by transfer simp qed end lemma fmempty_eqvt[eqvt]: shows "(p \ {$$}) = {$$}" by transfer simp lemma fmap_update_eqvt[eqvt]: shows "(p \ f(a $$:= b)) = (p \ f)((p \ a) $$:= (p \ b))" by transfer (simp add: map_upd_def) lemma fmap_apply_eqvt[eqvt]: shows "(p \ (f $$ b)) = (p \ f) $$ (p \ b)" by transfer simp lemma fresh_fmempty[simp]: shows "a \ {$$}" unfolding fresh_def supp_def by transfer simp lemma fresh_fmap_update: shows "\a \ f; a \ x; a \ y\ \ a \ f(x $$:= y)" unfolding fresh_conv_MOST by (elim MOST_rev_mp) simp lemma supp_fmempty[simp]: shows "supp {$$} = {}" by (simp add: supp_def) lemma supp_fmap_update: shows "supp (f(x $$:= y)) \ supp(f, x, y)" using fresh_fmap_update by (auto simp: fresh_def supp_Pair) instance fmap :: (fs, fs) fs proof fix x :: "('a, 'b) fmap" show "finite (supp x)" by (induct x rule: fmap_induct) (simp_all add: supp_Pair finite_supp finite_subset[OF supp_fmap_update]) qed -lemma fmap_reorder_neq_updates: - assumes "a \ b" - shows "\(a $$:= x)(b $$:= y) = \(b $$:= y)(a $$:= x)" - using assms by transfer (auto simp: map_upd_def) - -lemma fmap_upd_upd[simp]: "\(x $$:= y)(x $$:= z) = \(x $$:= z)" - by transfer (simp add: map_upd_def) - lemma fresh_transfer[transfer_rule]: "((=) ===> pcr_fmap (=) (=) ===> (=)) fresh fresh" unfolding fresh_def supp_def rel_fun_def pcr_fmap_def cr_fmap_def simp_thms option.rel_eq fun_eq_iff[symmetric] by (auto elim!: finite_subset[rotated] simp: fmap_ext) -lemma fmmap_fmupd: "fmmap f F(x $$:= y) = (fmmap f F)(x $$:= f y)" - by transfer (auto simp: fun_eq_iff map_upd_def) - lemma fmmap_eqvt[eqvt]: "p \ (fmmap f F) = fmmap (p \ f) (p \ F)" by (induct F arbitrary: f rule: fmap_induct) (auto simp add: fmap_update_eqvt fmmap_fmupd) lemma fmap_freshness_lemma: fixes h :: "('a::at,'b::pt) fmap" assumes a: "\a. atom a \ (h, h $$ a)" shows "\x. \a. atom a \ h \ h $$ a = x" using assms unfolding fresh_Pair by transfer (simp add: fresh_Pair freshness_lemma) lemma fmap_freshness_lemma_unique: fixes h :: "('a::at,'b::pt) fmap" assumes "\a. atom a \ (h, h $$ a)" shows "\!x. \a. atom a \ h \ h $$ a = x" using assms unfolding fresh_Pair by transfer (rule freshness_lemma_unique, auto simp: fresh_Pair) lemma fmdrop_fset_fmupd[simp]: "(fmdrop_fset A f)(x $$:= y) = fmdrop_fset (A |-| {|x|}) f(x $$:= y)" including fmap.lifting fset.lifting by transfer (auto simp: map_drop_set_def map_upd_def map_filter_def) lemma fresh_fset_fminus: assumes "atom x \ A" shows "A |-| {|x|} = A" using assms by (induct A) (simp_all add: finsert_fminus_if fresh_finsert) lemma fresh_fun_app: shows "atom x \ F \ x \ y \ F y = Some a \ atom x \ a" using supp_fun_app[of F y] by (auto simp: fresh_def supp_Some atom_not_fresh_eq) lemma fresh_fmap_fresh_Some: "atom x \ F \ x \ y \ F $$ y = Some a \ atom x \ a" including fmap.lifting by (transfer) (auto elim: fresh_fun_app) lemma fmdrop_eqvt: "p \ fmdrop x F = fmdrop (p \ x) (p \ F)" by transfer (auto simp: map_drop_def map_filter_def) lemma fmfilter_eqvt: "p \ fmfilter Q F = fmfilter (p \ Q) (p \ F)" by transfer (auto simp: map_filter_def) -lemma fmdrop_fmupd: "fmdrop x F(y $$:= z) = (if x = y then fmdrop x F else (fmdrop x F)(y $$:= z))" - by transfer (auto simp: map_drop_def map_filter_def map_upd_def) - lemma fmdrop_eq_iff: "fmdrop x B = fmdrop y B \ x = y \ (x \ fmdom' B \ y \ fmdom' B)" by transfer (auto simp: map_drop_def map_filter_def fun_eq_iff, metis) -lemma fmdrop_idle: "x \ fmdom' B \ fmdrop x B = B" - by transfer (auto simp: map_drop_def map_filter_def) - -lemma fmdrop_fmupd_same: "fmdrop x B(x $$:= y) = fmdrop x B" - by transfer (auto simp: map_drop_def map_filter_def map_upd_def) - lemma fresh_fun_upd: shows "\a \ f; a \ x; a \ y\ \ a \ f(x := y)" unfolding fresh_conv_MOST by (elim MOST_rev_mp) simp lemma supp_fun_upd: shows "supp (f(x := y)) \ supp(f, x, y)" using fresh_fun_upd by (auto simp: fresh_def supp_Pair) lemma map_drop_fun_upd: "map_drop x F = F(x := None)" unfolding map_drop_def map_filter_def by auto lemma fresh_fmdrop_in_fmdom: "\ x \ fmdom' B; y \ B; y \ x \ \ y \ fmdrop x B" by transfer (auto simp: map_drop_fun_upd fresh_None intro!: fresh_fun_upd) lemma fresh_fmdrop: assumes "x \ B" "x \ y" shows "x \ fmdrop y B" - using assms by (cases "y \ fmdom' B") (auto dest!: fresh_fmdrop_in_fmdom simp: fmdrop_idle) + using assms by (cases "y \ fmdom' B") (auto dest!: fresh_fmdrop_in_fmdom simp: fmdrop_idle') lemma fresh_fmdrop_fset: fixes x :: atom and A :: "(_ :: at_base) fset" assumes "x \ A" "x \ B" shows "x \ fmdrop_fset A B" using assms(1) by (induct A) (auto simp: fresh_fmdrop assms(2) fresh_finsert) -lemma fmdrop_fset_fmdom[simp]: "fmdrop_fset (fmdom A) A = {$$}" - by (induct A) (simp_all add: fmap_ext fmdom_notD) - (*<*) end (*>*) \ No newline at end of file diff --git a/thys/LambdaAuth/Results.thy b/thys/LambdaAuth/Results.thy --- a/thys/LambdaAuth/Results.thy +++ b/thys/LambdaAuth/Results.thy @@ -1,1557 +1,1557 @@ (* Author: Matthias Brun, ETH Zürich, 2019 *) (* Author: Dmitriy Traytel, ETH Zürich, 2019 *) section \Formalization of Miller et al.'s~\cite{adsg} Main Results\ (*<*) theory Results imports Agreement begin (*>*) lemma judge_imp_agree: assumes "\ \ e : \" shows "\ \ e, e, e : \" using assms by (induct \ e \) (auto simp: fresh_Pair) subsection \Lemma 2.1\ lemma lemma2_1: assumes "\ \ e, eP, eV : \" shows "\eP\ = eV" using assms by (induct \ e eP eV \) (simp_all add: Abs1_eq) subsection \Counterexample to Lemma 2.2\ lemma lemma2_2_false: fixes x :: var assumes "\\ e eP eV \ eP' eV'. \ \ \ e, eP, eV : \; \ \ e, eP', eV' : \ \ \ eP = eP' \ eV = eV'" shows False proof - have a1: "{$$} \ Prj1 (Pair Unit Unit), Prj1 (Pair Unit Unit), Prj1 (Pair Unit Unit) : One" by fastforce also have a2: "{$$} \ Prj1 (Pair Unit Unit), Prj1 (Pair Unit (Hashed (hash Unit) Unit)), Prj1 (Pair Unit (Hash (hash Unit))) : One" by fastforce from a1 a2 have "Prj1 (Pair Unit Unit) = Prj1 (Pair Unit (Hash (hash Unit)))" by (auto dest: assms) then show False by simp qed lemma smallstep_ideal_deterministic: "\[], t\ I\ \[], u\ \ \[], t\ I\ \[], u'\ \ u = u'" proof (nominal_induct "[]::proofstream" t I "[]::proofstream" u avoiding: u' rule: smallstep.strong_induct) case (s_App1 e\<^sub>1 e\<^sub>1' e\<^sub>2) from s_App1(3) value_no_step[OF s_App1(1)] show ?case by (auto dest!: s_App1(2)) next case (s_App2 v\<^sub>1 e\<^sub>2 e\<^sub>2') from s_App2(4) value_no_step[OF s_App2(2)] value_no_step[OF _ s_App2(1)] show ?case by (force dest!: s_App2(3)) next case (s_AppLam v x e) from s_AppLam(5,1,3) value_no_step[OF _ s_AppLam(2)] show ?case proof (cases rule: s_App_inv) case (AppLam y e') obtain z :: var where "atom z \ (x, e, y, e')" by (metis obtain_fresh) with AppLam s_AppLam(1,3) show ?thesis by (auto simp: fresh_Pair intro: box_equals[OF _ subst_term_perm[symmetric, of z] subst_term_perm[symmetric, of z]]) qed (auto dest: value_no_step) next case (s_AppRec v x e) from s_AppRec(5,1,3) value_no_step[OF _ s_AppRec(2)] show ?case proof (cases rule: s_App_inv) case (AppRec y e') obtain z :: var where "atom z \ (x, e, y, e')" by (metis obtain_fresh) with AppRec(1-4) AppRec(5)[simplified] s_AppRec(1,3) show ?thesis by (auto simp: fresh_Pair AppRec(5) intro: box_equals[OF _ subst_term_perm[symmetric, of z] subst_term_perm[symmetric, of z]]) qed (auto dest: value_no_step) next case (s_Let1 x e\<^sub>1 e\<^sub>1' e\<^sub>2) from s_Let1(1,2,3,8) value_no_step[OF s_Let1(6)] show ?case by (auto dest: s_Let1(7)) next case (s_Let2 v x e) from s_Let2(1,3,5) value_no_step[OF _ s_Let2(2)] show ?case by force next case (s_Inj1 e e') from s_Inj1(2,3) show ?case by auto next case (s_Inj2 e e') from s_Inj2(2,3) show ?case by auto next case (s_Case e e' e\<^sub>1 e\<^sub>2) from s_Case(2,3) value_no_step[OF s_Case(1)] show ?case by auto next case (s_Pair1 e\<^sub>1 e\<^sub>1' e\<^sub>2) from s_Pair1(2,3) value_no_step[OF s_Pair1(1)] show ?case by auto next case (s_Pair2 v\<^sub>1 e\<^sub>2 e\<^sub>2') from s_Pair2(3,4) value_no_step[OF _ s_Pair2(1)] value_no_step[OF s_Pair2(2)] show ?case by force next case (s_Prj1 e e') from s_Prj1(2,3) value_no_step[OF s_Prj1(1)] show ?case by auto next case (s_Prj2 e e') from s_Prj2(2,3) value_no_step[OF s_Prj2(1)] show ?case by auto next case (s_Unroll e e') from s_Unroll(2,3) value_no_step[OF s_Unroll(1)] show ?case by auto next case (s_Roll e e') from s_Roll(2,3) show ?case by auto next case (s_Auth e e') from s_Auth(2,3) value_no_step[OF s_Auth(1)] show ?case by auto next case (s_Unauth e e') from s_Unauth(2,3) value_no_step[OF s_Unauth(1)] show ?case by auto qed (auto 0 3 dest: value_no_step) lemma smallsteps_ideal_deterministic: "\[], t\ I\i \[], u\ \ \[], t\ I\i \[], u'\ \ u = u'" proof (induct "[]::proofstream" t I i "[]::proofstream" u arbitrary: u' rule: smallsteps.induct) case (s_Tr e\<^sub>1 i \\<^sub>2 e\<^sub>2 e\<^sub>3) from s_Tr(4) show ?case proof (cases rule: smallsteps.cases) case _: (s_Tr i \\<^sub>4 e\<^sub>4) with s_Tr(1,3) s_Tr(2)[of e\<^sub>4] show ?thesis using smallstepsI_ps_emptyD(2)[of e\<^sub>1 i \\<^sub>4 e\<^sub>4] smallstepI_ps_eq[of \\<^sub>2 e\<^sub>2 "[]" e\<^sub>3] by (auto intro!: smallstep_ideal_deterministic elim!: smallstepI_ps_emptyD) qed simp qed auto subsection \Lemma 2.3\ lemma lemma2_3: assumes "\ \ e, eP, eV : \" shows "erase_env \ \\<^sub>W e : erase \" using assms unfolding erase_env_def proof (nominal_induct \ e eP eV \ rule: agree.strong_induct) case (a_HashI v vP \ h \) then show ?case by (induct \) (auto simp: judge_weak_weakening_2 fmmap_fmupd judge_weak_fresh_env_fresh_term fresh_tyenv_None) qed (simp_all add: fresh_fmmap_erase_fresh fmmap_fmupd judge_weak_fresh_env_fresh_term) subsection \Lemma 2.4\ lemma lemma2_4[dest]: assumes "\ \ e, eP, eV : \" shows "value e \ value eP \ value eV \ \ value e \ \ value eP \ \ value eV" using assms by (nominal_induct \ e eP eV \ rule: agree.strong_induct) auto subsection \Lemma 3\ lemma lemma3_general: fixes \ :: tyenv and vs vPs vVs :: tenv assumes "\ \ e : \" "A |\| fmdom \" and "fmdom vs = A" "fmdom vPs = A" "fmdom vVs = A" and "\x. x |\| A \ (\\' v vP h. \ $$ x = Some (AuthT \') \ vs $$ x = Some v \ vPs $$ x = Some (Hashed h vP) \ vVs $$ x = Some (Hash h) \ {$$} \ v, Hashed h vP, Hash h : (AuthT \'))" shows "fmdrop_fset A \ \ psubst_term e vs, psubst_term e vPs, psubst_term e vVs : \" using assms proof (nominal_induct \ e \ avoiding: vs vPs vVs A rule: judge.strong_induct) case (j_Unit \) then show ?case by auto next case (j_Var \ x \) with j_Var show ?case proof (cases "x |\| A") case True with j_Var show ?thesis by (fastforce dest!: spec[of _ x] intro: agree_weakening_env) next case False with j_Var show ?thesis by (auto simp add: a_Var dest!: fmdomI split: option.splits) qed next case (j_Lam x \ \\<^sub>1 e \\<^sub>2) from j_Lam(4) have [simp]: "A |-| {|x|} = A" by (simp add: fresh_fset_fminus) from j_Lam(5,8-) have "fmdrop_fset A \(x $$:= \\<^sub>1) \ psubst_term e vs, psubst_term e vPs, psubst_term e vVs : \\<^sub>2" by (intro j_Lam(7)[of A vs vPs vVs]) (auto simp: fresh_tyenv_None) with j_Lam(1-5) show ?case by (auto simp: fresh_fmdrop_fset) next case (j_App \ e \\<^sub>1 \\<^sub>2 e') then have "fmdrop_fset A \ \ psubst_term e vs, psubst_term e vPs, psubst_term e vVs : Fun \\<^sub>1 \\<^sub>2" and "fmdrop_fset A \ \ psubst_term e' vs, psubst_term e' vPs, psubst_term e' vVs : \\<^sub>1" by simp_all then show ?case by auto next case (j_Let x \ e\<^sub>1 \\<^sub>1 e\<^sub>2 \\<^sub>2) from j_Let(4) have [simp]: "A |-| {|x|} = A" by (simp add: fresh_fset_fminus) from j_Let(8,11-) have "fmdrop_fset A \ \ psubst_term e\<^sub>1 vs, psubst_term e\<^sub>1 vPs, psubst_term e\<^sub>1 vVs : \\<^sub>1" by simp moreover from j_Let(4,5,11-) have "fmdrop_fset A \(x $$:= \\<^sub>1) \ psubst_term e\<^sub>2 vs, psubst_term e\<^sub>2 vPs, psubst_term e\<^sub>2 vVs : \\<^sub>2" by (intro j_Let(10)) (auto simp: fresh_tyenv_None) ultimately show ?case using j_Let(1-6) by (auto simp: fresh_fmdrop_fset fresh_Pair fresh_psubst) next case (j_Rec x \ y \\<^sub>1 \\<^sub>2 e') from j_Rec(4) have [simp]: "A |-| {|x|} = A" by (simp add: fresh_fset_fminus) from j_Rec(9,14-) have "fmdrop_fset A \(x $$:= Fun \\<^sub>1 \\<^sub>2) \ psubst_term (Lam y e') vs, psubst_term (Lam y e') vPs, psubst_term (Lam y e') vVs : Fun \\<^sub>1 \\<^sub>2" by (intro j_Rec(13)) (auto simp: fresh_tyenv_None) with j_Rec(1-11) show ?case by (auto simp: fresh_fmdrop_fset) next case (j_Case \ e \\<^sub>1 \\<^sub>2 e\<^sub>1 \ e\<^sub>2) then have "fmdrop_fset A \ \ psubst_term e vs, psubst_term e vPs, psubst_term e vVs : Sum \\<^sub>1 \\<^sub>2" and "fmdrop_fset A \ \ psubst_term e\<^sub>1 vs, psubst_term e\<^sub>1 vPs, psubst_term e\<^sub>1 vVs : Fun \\<^sub>1 \" and "fmdrop_fset A \ \ psubst_term e\<^sub>2 vs, psubst_term e\<^sub>2 vPs, psubst_term e\<^sub>2 vVs : Fun \\<^sub>2 \" by simp_all then show ?case by auto next case (j_Prj1 \ e \\<^sub>1 \\<^sub>2) then have "fmdrop_fset A \ \ psubst_term e vs, psubst_term e vPs, psubst_term e vVs : Prod \\<^sub>1 \\<^sub>2" by simp then show ?case by auto next case (j_Prj2 \ e \\<^sub>1 \\<^sub>2) then have "fmdrop_fset A \ \ psubst_term e vs, psubst_term e vPs, psubst_term e vVs : Prod \\<^sub>1 \\<^sub>2" by simp then show ?case by auto next case (j_Roll \ \ e \) then have "fmdrop_fset A \ \ psubst_term e vs, psubst_term e vPs, psubst_term e vVs : subst_type \ (Mu \ \) \" by simp with j_Roll(4,5) show ?case by (auto simp: fresh_fmdrop_fset) next case (j_Unroll \ \ e \) then have "fmdrop_fset A \ \ psubst_term e vs, psubst_term e vPs, psubst_term e vVs : Mu \ \" by simp with j_Unroll(4,5) show ?case by (auto simp: fresh_fmdrop_fset) qed auto lemmas lemma3 = lemma3_general[where A = "fmdom \" and \ = \, simplified] for \ subsection \Lemma 4\ lemma lemma4: assumes "\(x $$:= \') \ e, eP, eV : \" and "{$$} \ v, vP, vV : \'" and "value v" "value vP" "value vV" shows "\ \ e[v / x], eP[vP / x], eV[vV / x] : \" using assms proof (nominal_induct "\(x $$:= \')" e eP eV \ avoiding: x \ rule: agree.strong_induct) case a_Unit then show ?case by auto next case (a_Var y \) then show ?case proof (induct \) case fmempty then show ?case by (metis agree.a_Var fmupd_lookup option.sel subst_term.simps(2)) next case (fmupd x y \) then show ?case using agree_weakening_2 fresh_tyenv_None by auto qed next case (a_Lam y \\<^sub>1 e eP eV \\<^sub>2) from a_Lam(1,2,5,6,7-) show ?case - using agree_empty_fresh by (auto simp: fmap_reorder_neq_updates) + using agree_empty_fresh by (auto simp: fmupd_reorder_neq) next case (a_App v\<^sub>1 v\<^sub>2 v\<^sub>1P v\<^sub>2P v\<^sub>1V v\<^sub>2V \\<^sub>1 \\<^sub>2) from a_App(5-) show ?case by (auto intro: a_App(2,4)) next case (a_Let y e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2 \\<^sub>2) then show ?case - using agree_empty_fresh by (auto simp: fmap_reorder_neq_updates intro!: agree.a_Let[where x=y]) + using agree_empty_fresh by (auto simp: fmupd_reorder_neq intro!: agree.a_Let[where x=y]) next case (a_Rec y z \\<^sub>1 \\<^sub>2 e eP eV) from a_Rec(10) have "\a::var. atom a \ v" "\a::var. atom a \ vP" "\a::var. atom a \ vV" by auto with a_Rec(1-8,10-) show ?case - using a_Rec(9)[OF fmap_reorder_neq_updates] - by (auto simp: fmap_reorder_neq_updates intro!: agree.a_Rec[where x=y]) + using a_Rec(9)[OF fmupd_reorder_neq] + by (auto simp: fmupd_reorder_neq intro!: agree.a_Rec[where x=y]) next case (a_Case v v\<^sub>1 v\<^sub>2 vP v\<^sub>1P v\<^sub>2P vV v\<^sub>1V v\<^sub>2V \\<^sub>1 \\<^sub>2 \) from a_Case(7-) show ?case by (auto intro: a_Case(2,4,6)) next case (a_HashI v vP \ h) then have "atom x \ v" "atom x \ vP" by auto with a_HashI show ?case by auto qed auto subsection \Lemma 5: Single-Step Correctness\ lemma lemma5: assumes "{$$} \ e, eP, eV : \" and "\ [], e \ I\ \ [], e' \" obtains eP' eV' \ where "{$$} \ e', eP', eV' : \" "\\\<^sub>P. \ \\<^sub>P, eP \ P\ \ \\<^sub>P @ \, eP' \" "\\'. \ \ @ \', eV \ V\ \ \', eV' \" proof (atomize_elim, insert assms, nominal_induct "{$$}::tyenv" e eP eV \ avoiding: e' rule: agree.strong_induct) case (a_App e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 \\<^sub>2 e\<^sub>2 eP\<^sub>2 eV\<^sub>2) from a_App(5) show ?case proof (cases rule: s_App_inv) case (App1 e\<^sub>1') with a_App(2) obtain eP\<^sub>1' eV\<^sub>1' \ where *: "{$$} \ e\<^sub>1', eP\<^sub>1', eV\<^sub>1' : Fun \\<^sub>1 \\<^sub>2" "\\\<^sub>P. \\\<^sub>P, eP\<^sub>1\ P\ \\\<^sub>P @ \, eP\<^sub>1'\" "\\'. \\ @ \', eV\<^sub>1\ V\ \\', eV\<^sub>1'\" by blast show ?thesis proof (intro exI conjI) from * App1 a_App(1,3,5-) show "{$$} \ e', App eP\<^sub>1' eP\<^sub>2, App eV\<^sub>1' eV\<^sub>2 : \\<^sub>2" "\\\<^sub>P. \\\<^sub>P, App eP\<^sub>1 eP\<^sub>2\ P\ \\\<^sub>P @ \, App eP\<^sub>1' eP\<^sub>2\" "\\'. \\ @ \', App eV\<^sub>1 eV\<^sub>2\ V\ \\', App eV\<^sub>1' eV\<^sub>2\" by auto qed next case (App2 e\<^sub>2') with a_App(4) obtain eP\<^sub>2' eV\<^sub>2' \ where *: "{$$} \ e\<^sub>2', eP\<^sub>2', eV\<^sub>2' : \\<^sub>1" "\\\<^sub>P. \\\<^sub>P, eP\<^sub>2\ P\ \\\<^sub>P @ \, eP\<^sub>2'\" "\\'. \\ @ \', eV\<^sub>2\ V\ \\', eV\<^sub>2'\" by blast show ?thesis proof (intro exI conjI) from * App2 a_App(1,3,5-) show "{$$} \ e', App eP\<^sub>1 eP\<^sub>2', App eV\<^sub>1 eV\<^sub>2' : \\<^sub>2" "\\\<^sub>P. \\\<^sub>P, App eP\<^sub>1 eP\<^sub>2\ P\ \\\<^sub>P @ \, App eP\<^sub>1 eP\<^sub>2'\" "\\'. \\ @ \', App eV\<^sub>1 eV\<^sub>2\ V\ \\', App eV\<^sub>1 eV\<^sub>2'\" by auto qed next case (AppLam x e) from a_App(1)[unfolded \e\<^sub>1 = Lam x e\] show ?thesis proof (cases rule: a_Lam_inv_I[case_names _ Lam]) case (Lam eP eV) show ?thesis proof (intro exI conjI) from Lam a_App(3,5) AppLam show "{$$} \ e', eP[eP\<^sub>2 / x], eV[eV\<^sub>2 / x] : \\<^sub>2" by (auto intro: lemma4) from Lam a_App(3,5) AppLam show "\\\<^sub>P. \\\<^sub>P, App eP\<^sub>1 eP\<^sub>2\ P\ \\\<^sub>P @ [], eP[eP\<^sub>2 / x]\" by (intro allI iffD1[OF smallstepP_ps_prepend[where \ = "[]", simplified]]) (auto simp: fresh_Pair intro!: s_AppLam[where v=eP\<^sub>2]) from Lam a_App(3,5) AppLam show "\\'. \[] @ \', App eV\<^sub>1 eV\<^sub>2\ V\ \\', eV[eV\<^sub>2 / x]\" by (intro allI iffD1[OF smallstepV_ps_append[where \' = "[]", simplified]]) (auto simp: fresh_Pair intro!: s_AppLam[where v=eV\<^sub>2]) qed qed simp next case (AppRec x e) from a_App(1)[unfolded \e\<^sub>1 = Rec x e\] show ?thesis proof (cases rule: a_Rec_inv_I[consumes 1, case_names _ Rec]) case (Rec y e'' eP' eV') from Rec(5,4) show ?thesis proof (cases rule: a_Lam_inv_I[consumes 1, case_names _ Lam]) case (Lam eP'' eV'') show ?thesis proof (intro conjI exI[of _ "[]"] exI) let ?eP = "App (Lam y eP''[Rec x (Lam y eP'') / x]) eP\<^sub>2" let ?eV = "App (Lam y eV''[Rec x (Lam y eV'') / x]) eV\<^sub>2" from a_App(3) AppRec have [simp]: "value eP\<^sub>2" "atom x \ eP\<^sub>2" "value eV\<^sub>2" "atom x \ eV\<^sub>2" by (auto simp: fresh_Pair) from Lam a_App(3,5-) AppRec Rec show "{$$} \ e', ?eP, ?eV : \\<^sub>2" unfolding term.eq_iff Abs1_eq(3) - by (auto simp: fmap_reorder_neq_updates + by (auto simp: fmupd_reorder_neq intro!: agree.a_App[where \="{$$}"] a_Lam[where x=y] lemma4) from Lam a_App(3,5-) AppRec Rec show "\\\<^sub>P. \\\<^sub>P, App eP\<^sub>1 eP\<^sub>2\ P\ \\\<^sub>P @ [], ?eP\" unfolding term.eq_iff Abs1_eq(3) using s_AppRec[where v=eP\<^sub>2 and x=x and \="[]" and e="Lam y eP''" and uv=P] by (intro allI iffD1[OF smallstepP_ps_prepend[of "[]", simplified]]) (auto simp: fresh_Pair simp del: s_AppRec) from Lam a_App(3,5-) AppRec Rec show "\\'. \[] @ \', App eV\<^sub>1 eV\<^sub>2\ V\ \\', ?eV\" unfolding term.eq_iff Abs1_eq(3) using s_AppRec[where v=eV\<^sub>2 and x=x and \="[]" and e="Lam y eV''" and uv=V] by (intro allI iffD1[OF smallstepV_ps_append[of _ _ "[]", simplified]]) (auto simp: fresh_Pair simp del: s_AppRec) qed qed (simp add: fresh_fmap_update) qed simp qed next case (a_Let x e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2 \\<^sub>2) then have "atom x \ (e\<^sub>1, [])" by auto with a_Let(10) show ?case proof (cases rule: s_Let_inv) case Let1 show ?thesis proof (intro conjI exI[of _ "[]"] exI) from a_Let(6,8) Let1 show "{$$} \ e', eP\<^sub>2[eP\<^sub>1 / x], eV\<^sub>2[eV\<^sub>1 / x] : \\<^sub>2" by (auto intro: lemma4) from a_Let(4,6) Let1 show "\\\<^sub>P. \\\<^sub>P, Let eP\<^sub>1 x eP\<^sub>2\ P\ \\\<^sub>P @ [], eP\<^sub>2[eP\<^sub>1 / x]\" by (intro allI iffD1[OF smallstepP_ps_prepend[of "[]", simplified]] s_Let2) auto from a_Let(5,6) Let1 show "\\'. \[] @ \', Let eV\<^sub>1 x eV\<^sub>2\ V\ \\', eV\<^sub>2[eV\<^sub>1 / x]\" by (intro allI iffD1[OF smallstepV_ps_append[of _ _ "[]", simplified]] s_Let2) auto qed next case (Let2 e\<^sub>1') moreover from Let2 a_Let(7) obtain eP\<^sub>1' eV\<^sub>1' \ where ih: "{$$} \ e\<^sub>1', eP\<^sub>1', eV\<^sub>1' : \\<^sub>1" "\\\<^sub>P. \\\<^sub>P, eP\<^sub>1\ P\ \\\<^sub>P @ \, eP\<^sub>1'\" "\\'. \\ @ \', eV\<^sub>1\ V\ \\', eV\<^sub>1'\" by (blast dest: spec[of _ "[]"]) then have [simp]: "atom x \ ({$$}, e\<^sub>1', eP\<^sub>1', eV\<^sub>1')" using agree_empty_fresh by auto from ih a_Let(4) have [simp]: "atom x \ \" using fresh_Nil fresh_append fresh_ps_smallstep_P by blast from a_Let ih have agree: "{$$} \ Let e\<^sub>1' x e\<^sub>2, Let eP\<^sub>1' x eP\<^sub>2, Let eV\<^sub>1' x eV\<^sub>2 : \\<^sub>2" by auto moreover from a_Let(4,5) ih(1) spec[OF ih(2), of "[]", simplified] have "\\', Let eP\<^sub>1 x eP\<^sub>2\ P\ \\' @ \, Let eP\<^sub>1' x eP\<^sub>2\" for \' by (intro iffD1[OF smallstepP_ps_prepend[of "[]", simplified]] s_Let1) (auto simp: fresh_Pair) moreover from a_Let(4,5) ih(1) spec[OF ih(3), of "[]", simplified] have "\\ @ \', Let eV\<^sub>1 x eV\<^sub>2\ V\ \\', Let eV\<^sub>1' x eV\<^sub>2\" for \' by (intro iffD1[OF smallstepV_ps_append[of \ _ "[]", simplified]] s_Let1) (auto simp: fresh_Pair) ultimately show ?thesis by blast qed next case (a_Case e eP eV \\<^sub>1 \\<^sub>2 e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \ e\<^sub>2 eP\<^sub>2 eV\<^sub>2) from a_Case(7) show ?case proof (cases rule: s_Case_inv) case (Case e'') with a_Case(2)[of e''] obtain eP'' eV'' \ where ih: "{$$} \ e'', eP'', eV'' : Syntax.Sum \\<^sub>1 \\<^sub>2" "\\\<^sub>P. \\\<^sub>P, eP\ P\ \\\<^sub>P @ \, eP''\" "\\'. \\ @ \', eV\ V\ \\', eV''\" by blast show ?thesis proof (intro conjI exI[of _ \] exI) from ih(1) a_Case(3,5) Case show "{$$} \ e', Case eP'' eP\<^sub>1 eP\<^sub>2, Case eV'' eV\<^sub>1 eV\<^sub>2 : \" by auto from a_Case(5) spec[OF ih(2), of "[]", simplified] show "\\\<^sub>P. \\\<^sub>P, Case eP eP\<^sub>1 eP\<^sub>2\ P\ \\\<^sub>P @ \, Case eP'' eP\<^sub>1 eP\<^sub>2\" by (intro allI iffD1[OF smallstepP_ps_prepend[of "[]", simplified]] s_Case) auto from a_Case(5) spec[OF ih(3), of "[]", simplified] show "\\'. \\ @ \', Case eV eV\<^sub>1 eV\<^sub>2\ V\ \\', Case eV'' eV\<^sub>1 eV\<^sub>2\" by (intro allI iffD1[OF smallstepV_ps_append[of _ _ "[]", simplified]] s_Case) auto qed next case (Inj1 v) from a_Case(1)[unfolded \e = Inj1 v\] show ?thesis proof (cases rule: a_Inj1_inv_I[consumes 1, case_names Case]) case (Case vP vV) with a_Case(3,5) Inj1 show ?thesis proof (intro conjI exI[of _ "[]"] exI) from Case a_Case(3,5) Inj1 show "{$$} \ e', App eP\<^sub>1 vP, App eV\<^sub>1 vV : \" by auto qed auto qed next case (Inj2 v) from a_Case(1)[unfolded \e = Inj2 v\] show ?thesis proof (cases rule: a_Inj2_inv_I[consumes 1, case_names Case]) case (Case vP vV) with a_Case(3,5) Inj2 show ?thesis proof (intro conjI exI[of _ "[]"] exI) from Case a_Case(3,5) Inj2 show "{$$} \ e', App eP\<^sub>2 vP, App eV\<^sub>2 vV : \" by auto qed auto qed qed next case (a_Prj1 e eP eV \\<^sub>1 \\<^sub>2) from a_Prj1(3) show ?case proof (cases rule: s_Prj1_inv) case (Prj1 e'') then show ?thesis by (blast dest!: a_Prj1(2)) next case (PrjPair1 v\<^sub>2) from a_Prj1(1)[unfolded \e = Syntax.Pair e' v\<^sub>2\] show ?thesis proof (cases rule: a_Pair_inv_I[consumes 1, case_names Pair]) case (Pair eP\<^sub>1 eV\<^sub>1 eP\<^sub>2 eV\<^sub>2) with PrjPair1 show ?thesis proof (intro conjI exI[of _ "[]"] exI) show "{$$} \ e', eP\<^sub>1, eV\<^sub>1 : \\<^sub>1" by (rule Pair) qed auto qed qed next case (a_Prj2 e eP eV \\<^sub>1 \\<^sub>2) from a_Prj2(3) show ?case proof (cases rule: s_Prj2_inv) case (Prj2 e'') then show ?thesis by (blast dest!: a_Prj2(2)) next case (PrjPair2 v\<^sub>1) from a_Prj2(1)[unfolded \e = Syntax.Pair v\<^sub>1 e'\] show ?thesis proof (cases rule: a_Pair_inv_I[consumes 1, case_names Pair]) case (Pair eP\<^sub>1 eV\<^sub>1 eP\<^sub>2 eV\<^sub>2) with PrjPair2 show ?thesis proof (intro conjI exI[of _ "[]"] exI) show "{$$} \ e', eP\<^sub>2, eV\<^sub>2 : \\<^sub>2" by (rule Pair) qed auto qed qed next case (a_Roll \ e eP eV \) from a_Roll(5) show ?case proof (cases rule: s_Roll_inv) case (Roll e'') with a_Roll(4) obtain eP'' eV'' \ where *: "{$$} \ e'', eP'', eV'' : subst_type \ (Mu \ \) \" "\\\<^sub>P. \\\<^sub>P, eP\ P\ \\\<^sub>P @ \, eP''\" "\\'. \\ @ \', eV\ V\ \\', eV''\" by blast show ?thesis proof (intro exI conjI) from * Roll show "{$$} \ e', Roll eP'', Roll eV'' : Mu \ \" "\\\<^sub>P. \\\<^sub>P, Roll eP\ P\ \\\<^sub>P @ \, Roll eP''\" "\\'. \\ @ \', Roll eV\ V\ \\', Roll eV''\" by auto qed qed next case (a_Unroll \ e eP eV \) from a_Unroll(5) show ?case proof (cases rule: s_Unroll_inv) case (Unroll e'') with a_Unroll(4) obtain eP'' eV'' \ where *: "{$$} \ e'', eP'', eV'' : Mu \ \" "\\\<^sub>P. \\\<^sub>P, eP\ P\ \\\<^sub>P @ \, eP''\" "\\'. \\ @ \', eV\ V\ \\', eV''\" by blast show ?thesis proof (intro exI conjI) from * Unroll show "{$$} \ e', Unroll eP'', Unroll eV'' : subst_type \ (Mu \ \) \" "\\\<^sub>P. \\\<^sub>P, Unroll eP\ P\ \\\<^sub>P @ \, Unroll eP''\" "\\'. \\ @ \', Unroll eV\ V\ \\', Unroll eV''\" by auto qed next case UnrollRoll with a_Unroll(3)[unfolded \e = Roll e'\] show ?thesis proof (cases rule: a_Roll_inv_I[case_names Roll]) case (Roll eP' eV') with UnrollRoll show ?thesis proof (intro conjI exI[of _ "[]"] exI) show "{$$} \ e', eP', eV' : subst_type \ (Mu \ \) \" by fact qed auto qed qed next case (a_Auth e eP eV \) from a_Auth(1) have [simp]: "atom x \ eP" for x :: var using agree_empty_fresh by simp from a_Auth(3) show ?case proof (cases rule: s_AuthI_inv) case (Auth e'') then show ?thesis by (blast dest!: a_Auth(2)) next case AuthI with a_Auth(1) have "value eP" "value eV" by auto with a_Auth(1) AuthI(2) show ?thesis proof (intro conjI exI[of _ "[]"] exI) from a_Auth(1) AuthI(2) \value eP\ show "{$$} \ e', Hashed (hash \eP\) eP, Hash (hash \eP\) : AuthT \" by (auto dest: lemma2_1 simp: fresh_shallow) qed (auto dest: lemma2_1 simp: fresh_shallow) qed next case (a_Unauth e eP eV \) from a_Unauth(1) have eP_closed: "closed eP" using agree_empty_fresh by simp from a_Unauth(3) show ?case proof (cases rule: s_UnauthI_inv) case (Unauth e') then show ?thesis by (blast dest!: a_Unauth(2)) next case UnauthI with a_Unauth(1) have "value eP" "value eV" by auto from a_Unauth(1) show ?thesis proof (cases rule: a_AuthT_value_inv[case_names _ _ _ Unauth]) case (Unauth vP') show ?thesis proof (intro conjI exI[of _ "[\vP'\]"] exI) from Unauth(1,2) UnauthI(2) a_Unauth(1) show "{$$} \ e', vP', \vP'\ : \" by (auto simp: fresh_shallow) then have "closed vP'" by auto with Unauth(1,2) a_Unauth(1) show "\\\<^sub>P. \\\<^sub>P, Unauth eP\ P\ \\\<^sub>P @ [\vP'\], vP'\" "\\'. \[\vP'\] @ \', Unauth eV\ V\ \\', \vP'\\" by (auto simp: fresh_shallow) qed qed (auto simp: \value e\ \value eP\ \value eV\) qed next case (a_Pair e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2 \\<^sub>2) from a_Pair(5) show ?case proof (cases rule: s_Pair_inv) case (Pair1 e\<^sub>1') with a_Pair(1,3) show ?thesis by (blast dest!: a_Pair(2)) next case (Pair2 e\<^sub>2') with a_Pair(1,3) show ?thesis by (blast dest!: a_Pair(4)) qed next case (a_Inj1 e eP eV \\<^sub>1 \\<^sub>2) from a_Inj1(3) show ?case proof (cases rule: s_Inj1_inv) case (Inj1 e') with a_Inj1(1) show ?thesis by (blast dest!: a_Inj1(2)) qed next case (a_Inj2 e eP eV \\<^sub>2 \\<^sub>1) from a_Inj2(3) show ?case proof (cases rule: s_Inj2_inv) case (Inj2 e'') with a_Inj2(1) show ?thesis by (blast dest!: a_Inj2(2)) qed qed (simp, meson value.intros value_no_step)+ subsection \Lemma 6: Single-Step Security\ lemma lemma6: assumes "{$$} \ e, eP, eV : \" and "\ \\<^sub>A, eV \ V\ \ \', eV' \" obtains e' eP' \ where "\ [], e \ I\ \ [], e' \" "\\\<^sub>P. \ \\<^sub>P, eP \ P\ \ \\<^sub>P @ \, eP' \" and "{$$} \ e', eP', eV' : \ \ \\<^sub>A = \ @ \' \ (\s s'. closed s \ closed s' \ \ = [s] \ \\<^sub>A = [s'] @ \' \ s \ s' \ hash s = hash s')" proof (atomize_elim, insert assms, nominal_induct "{$$}::tyenv" e eP eV \ avoiding: \\<^sub>A \' eV' rule: agree.strong_induct) case (a_App e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 \\<^sub>2 e\<^sub>2 eP\<^sub>2 eV\<^sub>2) from a_App(5) show ?case proof (cases rule: s_App_inv) case (App1 eV\<^sub>1') with a_App(1,3) show ?thesis by (blast dest!: a_App(2)) next case (App2 e\<^sub>2') with a_App(1,3) show ?thesis by (blast dest!: a_App(4)) next case (AppLam x eV'') from a_App(1)[unfolded \eV\<^sub>1 = Lam x eV''\] show ?thesis proof (cases rule: a_Lam_inv_V[case_names Lam]) case (Lam e'' eP'') with a_App(3) AppLam show ?thesis proof (intro conjI exI[of _ "[]"] exI disjI1) from Lam a_App(3) AppLam show "{$$} \ e''[e\<^sub>2 / x], eP''[eP\<^sub>2 / x], eV' : \\<^sub>2" by (auto intro: lemma4) qed (auto 0 3 simp: fresh_Pair intro!: s_AppLam[where \="[]"] intro: iffD1[OF smallstepP_ps_prepend[of "[]" _ "[]", simplified]]) qed next case (AppRec x eV'') from a_App(1)[unfolded \eV\<^sub>1 = Rec x eV''\] show ?thesis proof (cases rule: a_Rec_inv_V[case_names _ Rec]) case (Rec y e''' eP''' eV''') with a_App(1,3) AppRec show ?thesis proof (intro conjI exI[of _ "[]"] exI disjI1) let ?e = "App (Lam y e'''[Rec x (Lam y e''') / x]) e\<^sub>2" let ?eP = "App (Lam y eP'''[Rec x (Lam y eP''') / x]) eP\<^sub>2" from Rec a_App(3) AppRec show "{$$} \ ?e, ?eP, eV' : \\<^sub>2" by (auto simp del: subst_term.simps(3) intro!: agree.a_App[where \="{$$}"] lemma4) qed (auto 0 3 simp del: subst_term.simps(3) simp: fresh_Pair intro!: s_AppRec[where \="[]"] intro: iffD1[OF smallstepP_ps_prepend[of "[]" _ "[]", simplified]]) qed simp qed next case (a_Let x e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2 \\<^sub>2) then have "atom x \ (eV\<^sub>1, \\<^sub>A)" by auto with a_Let(12) show ?case proof (cases rule: s_Let_inv) case Let1 with a_Let(5,6,8,10) show ?thesis proof (intro conjI exI[of _ "[]"] exI disjI1) from Let1 a_Let(5,6,8,10) show "{$$} \ e\<^sub>2[e\<^sub>1 / x], eP\<^sub>2[eP\<^sub>1 / x], eV' : \\<^sub>2" by (auto intro: lemma4) qed (auto 0 3 intro: iffD1[OF smallstepP_ps_prepend[of "[]" _ "[]", simplified]]) next case (Let2 eV\<^sub>1') with a_Let(9)[of \\<^sub>A \' eV\<^sub>1'] obtain e\<^sub>1' \ eP\<^sub>1' s s' where ih: "\[], e\<^sub>1\ I\ \[], e\<^sub>1'\" "\\\<^sub>P. \\\<^sub>P, eP\<^sub>1\ P\ \\\<^sub>P @ \, eP\<^sub>1'\" "{$$} \ e\<^sub>1', eP\<^sub>1', eV\<^sub>1' : \\<^sub>1 \ \\<^sub>A = \ @ \' \ closed s \ closed s' \ \ = [s] \ \\<^sub>A = [s'] @ \' \ s \ s' \ hash s = hash s'" by blast with a_Let(5,6) have fresh: "atom x \ e\<^sub>1'" "atom x \ eP\<^sub>1'" using fresh_smallstep_I fresh_smallstep_P by blast+ from ih a_Let(2,6) have "atom x \ \" using fresh_append fresh_ps_smallstep_P by blast with Let2 a_Let(1-8,10,12-) fresh ih show ?thesis proof (intro conjI exI[of _ "\"] exI) from \atom x \ \\ Let2 a_Let(1-8,10,12-) fresh ih show "{$$} \ Let e\<^sub>1' x e\<^sub>2, Let eP\<^sub>1' x eP\<^sub>2, eV' : \\<^sub>2 \ \\<^sub>A = \ @ \' \ (\s s'. closed s \ closed s' \ \ = [s] \ \\<^sub>A = [s'] @ \' \ s \ s' \ hash s = hash s')" by auto qed (auto dest: spec[of _ "[]"] intro!: iffD1[OF smallstepP_ps_prepend, of "[]", simplified]) qed next case (a_Case e eP eV \\<^sub>1 \\<^sub>2 e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \ e\<^sub>2 eP\<^sub>2 eV\<^sub>2) from a_Case(7) show ?case proof (cases rule: s_Case_inv) case (Case eV'') from a_Case(2)[OF Case(2)] show ?thesis proof (elim exE disjE conjE, goal_cases ok collision) case (ok e'' \ eP'') with Case a_Case(3,5) show ?case by blast next case (collision e'' \ eP'' s s') with Case a_Case(3,5) show ?case proof (intro exI[of _ "[s]"] exI conjI disjI2) from Case a_Case(3,5) collision show "\[], Case e e\<^sub>1 e\<^sub>2\ I\ \[], Case e'' e\<^sub>1 e\<^sub>2\" "\\\<^sub>P. \\\<^sub>P, Case eP eP\<^sub>1 eP\<^sub>2\ P\ \\\<^sub>P @ [s], Case eP'' eP\<^sub>1 eP\<^sub>2\" by auto from collision show "closed s" "closed s'" "s \ s'" "hash s = hash s'" by auto qed simp qed next case (Inj1 vV) from a_Case(1)[unfolded \eV = Inj1 vV\] show ?thesis proof (cases rule: a_Inj1_inv_V[consumes 1, case_names Inj]) case (Inj v' vP') with Inj1 show ?thesis proof (intro conjI exI[of _ "[]"] exI disjI1) from a_Case(3) Inj Inj1 show "{$$} \ App e\<^sub>1 v', App eP\<^sub>1 vP', eV' : \" by auto qed auto qed next case (Inj2 vV) from a_Case(1)[unfolded \eV = Inj2 vV\] show ?thesis proof (cases rule: a_Inj2_inv_V[consumes 1, case_names Inj]) case (Inj v' vP') with Inj2 show ?thesis proof (intro conjI exI[of _ "[]"] exI disjI1) from a_Case(5) Inj Inj2 show "{$$} \ App e\<^sub>2 v', App eP\<^sub>2 vP', eV' : \" by auto qed auto qed qed next case (a_Prj1 e eP eV \\<^sub>1 \\<^sub>2) from a_Prj1(3) show ?case proof (cases rule: s_Prj1_inv) case (Prj1 eV'') then show ?thesis by (blast dest!: a_Prj1(2)) next case (PrjPair1 v\<^sub>2) with a_Prj1(1) show ?thesis proof (cases rule: a_Prod_inv[consumes 1, case_names _ _ _ _ Pair]) case (Pair e\<^sub>1 eP\<^sub>1 eV\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2) with PrjPair1 a_Prj1(1) show ?thesis proof (intro conjI exI[of _ "[]"] exI disjI1) from Pair PrjPair1 a_Prj1(1) show "{$$} \ e\<^sub>1, eP\<^sub>1, eV' : \\<^sub>1" by auto qed auto qed simp_all qed next case (a_Prj2 e eP eV \\<^sub>1 \\<^sub>2) from a_Prj2(3) show ?case proof (cases rule: s_Prj2_inv) case (Prj2 eV'') then show ?thesis by (blast dest!: a_Prj2(2)) next case (PrjPair2 v\<^sub>2) with a_Prj2(1) show ?thesis proof (cases rule: a_Prod_inv[consumes 1, case_names _ _ _ _ Pair]) case (Pair e\<^sub>1 eP\<^sub>1 eV\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2) with PrjPair2 a_Prj2(1) show ?thesis proof (intro conjI exI[of _ "[]"] exI disjI1) from Pair PrjPair2 a_Prj2(1) show "{$$} \ e\<^sub>2, eP\<^sub>2, eV' : \\<^sub>2" by auto qed auto qed simp_all qed next case (a_Roll \ e eP eV \) from a_Roll(7) show ?case proof (cases rule: s_Roll_inv) case (Roll eV'') from a_Roll(6)[OF Roll(2)] obtain e'' \ eP'' where ih: "\[], e\ I\ \[], e''\" "\\\<^sub>P. \\\<^sub>P, eP\ P\ \\\<^sub>P @ \, eP''\" "{$$} \ e'', eP'', eV'' : subst_type \ (Mu \ \) \ \ \\<^sub>A = \ @ \' \ (\s s'. closed s \ closed s' \ \ = [s] \ \\<^sub>A = [s'] @ \' \ s \ s' \ hash s = hash s')" by blast with Roll show ?thesis proof (intro exI[of _ "\"] exI conjI) from ih Roll show "{$$} \ Roll e'', Roll eP'', eV' : Mu \ \ \ \\<^sub>A = \ @ \' \ (\s s'. closed s \ closed s' \ \ = [s] \ \\<^sub>A = [s'] @ \' \ s \ s' \ hash s = hash s')" by auto qed auto qed next case (a_Unroll \ e eP eV \) from a_Unroll(7) show ?case proof (cases rule: s_Unroll_inv) case (Unroll eV'') from a_Unroll(6)[OF Unroll(2)] obtain e'' \ eP'' where ih: "\[], e\ I\ \[], e''\" "\\\<^sub>P. \\\<^sub>P, eP\ P\ \\\<^sub>P @ \, eP''\" "{$$} \ e'', eP'', eV'' : Mu \ \ \ \\<^sub>A = \ @ \' \ (\s s'. closed s \ closed s' \ \ = [s] \ \\<^sub>A = [s'] @ \' \ s \ s' \ hash s = hash s')" by blast with Unroll show ?thesis proof (intro exI[of _ "\"] exI conjI) from ih Unroll show "{$$} \ Unroll e'', Unroll eP'', eV' : subst_type \ (Mu \ \) \ \ \\<^sub>A = \ @ \' \ (\s s'. closed s \ closed s' \ \ = [s] \ \\<^sub>A = [s'] @ \' \ s \ s' \ hash s = hash s')" by auto qed auto next case UnrollRoll with a_Unroll(5) show ?thesis by fastforce qed next case (a_Auth e eP eV \) from a_Auth(1) have [simp]: "atom x \ eP" for x :: var using agree_empty_fresh by simp from a_Auth(3) show ?case proof (cases rule: s_AuthV_inv) case (Auth eV'') from a_Auth(2)[OF Auth(2)] show ?thesis proof (elim exE disjE conjE, goal_cases ok collision) case (ok e'' \ eP'') with Auth show ?case proof (intro conjI exI[of _ "\"] exI disjI1) from ok Auth show "{$$} \ Auth e'', Auth eP'', eV' : AuthT \" by auto qed auto next case (collision e'' \ eP'' s s') then show ?case by blast qed next case AuthV with a_Auth(1) show ?thesis proof (intro exI[of _ "[]"] exI conjI disjI1) from a_Auth(1) AuthV show "{$$} \ e, Hashed (hash \eP\) eP, eV' : AuthT \" by (auto dest: lemma2_1) qed (auto simp: fresh_shallow) qed next case (a_Unauth e eP eV \) from a_Unauth(3) show ?case proof (cases rule: s_UnauthV_inv) case (Unauth e') then show ?thesis by (blast dest!: a_Unauth(2)) next case UnauthV from a_Unauth(1)[unfolded \eV = Hash (hash eV')\] UnauthV a_Unauth(1) show ?thesis proof (cases rule: a_AuthT_value_inv[consumes 1, case_names _ _ _ Hashed]) case (Hashed vP') with UnauthV a_Unauth(1) show ?thesis proof (intro exI[of _ "[\vP'\]"] exI conjI) from Hashed UnauthV a_Unauth(1) show "{$$} \ e, vP', eV' : \ \ \\<^sub>A = [\vP'\] @ \' \ (\s s'. closed s \ closed s' \ [\vP'\] = [s] \ \\<^sub>A = [s'] @ \' \ s \ s' \ hash s = hash s')" by (fastforce elim: a_HashI_inv[where \="{$$}"]) qed auto qed auto qed next case (a_Pair e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2 \\<^sub>2) from a_Pair(5) show ?case proof (cases rule: s_Pair_inv) case (Pair1 eV\<^sub>1') with a_Pair(3) show ?thesis using a_Pair(2)[of \\<^sub>A \' eV\<^sub>1'] by blast next case (Pair2 eV\<^sub>2') with a_Pair(1) show ?thesis using a_Pair(4)[of \\<^sub>A \' eV\<^sub>2'] by blast qed next case (a_Inj1 e eP eV \\<^sub>1 \\<^sub>2) from a_Inj1(3) show ?case proof (cases rule: s_Inj1_inv) case (Inj1 eV'') then show ?thesis using a_Inj1(2)[of \\<^sub>A \' eV''] by blast qed next case (a_Inj2 e eP eV \\<^sub>2 \\<^sub>1) from a_Inj2(3) show ?case proof (cases rule: s_Inj2_inv) case (Inj2 eV'') with a_Inj2(1) show ?thesis using a_Inj2(2)[of \\<^sub>A \' eV''] by blast qed qed (simp, meson value.intros value_no_step)+ subsection \Theorem 1: Correctness\ lemma theorem1_correctness: assumes "{$$} \ e, eP, eV : \" and "\ [], e \ I\i \ [], e' \" obtains eP' eV' \ where "\ [], eP \ P\i \ \, eP' \" "\ \, eV \ V\i \ [], eV' \" "{$$} \ e', eP', eV' : \" using assms(2,1) proof (atomize_elim, induct "[]::proofstream" e I i "[]::proofstream" e' rule: smallsteps.induct) case (s_Id e) then show ?case by auto next case (s_Tr e\<^sub>1 i \\<^sub>2 e\<^sub>2 e\<^sub>3) then have "\\<^sub>2 = []" by (auto dest: smallstepI_ps_eq) with s_Tr obtain eP\<^sub>2 \ eV\<^sub>2 where ih: "\[], eP\ P\i \\, eP\<^sub>2\" "\\, eV\ V\i \[], eV\<^sub>2\" "{$$} \ e\<^sub>2, eP\<^sub>2, eV\<^sub>2 : \" by (atomize_elim, intro s_Tr(2)) auto moreover obtain eP\<^sub>3 eV\<^sub>3 \' where agree: "{$$} \ e\<^sub>3, eP\<^sub>3, eV\<^sub>3 : \" and "\\\<^sub>P, eP\<^sub>2\ P\ \\\<^sub>P @ \', eP\<^sub>3\" "\\' @ \'', eV\<^sub>2\ V\ \\'', eV\<^sub>3\" for \\<^sub>P \'' using lemma5[OF ih(3) s_Tr(3)[unfolded \\\<^sub>2 = []\], of thesis] by blast ultimately have "\[], eP\ P\i + 1 \\ @ \', eP\<^sub>3\" "\\ @ \', eV\ V\i + 1 \[], eV\<^sub>3\" by (auto simp: smallstepsV_ps_append[of _ _ _ "[]", simplified, symmetric] intro!: smallsteps.s_Tr[of "\ @ \'"]) with agree show ?case by blast qed subsection \Counterexamples to Theorem 1: Security\ text \Counterexample using administrative normal form.\ lemma security_false: assumes agree: "\e eP eV \ \A i \' eV'. \ {$$} \ e, eP, eV : \; \ \A, eV \ V\i \ \', eV' \ \ \ \e' eP' \ j \0 s s'. (\ [], e \ I\i \ [], e' \ \ \ [], eP \ P\i \ \, eP' \ \ (\A = \ @ \') \ {$$} \ e', eP', eV' : \) \ (j \ i \ \ [], eP \ P\j \ \0 @ [s], eP' \ \ (\A = \0 @ [s'] @ \') \ s \ s' \ hash s = hash s')" and collision: "hash (Inj1 Unit) = hash (Inj2 Unit)" and no_collision_with_Unit: "\t. hash Unit = hash t \ t = Unit" shows False proof - define i where "i = Suc (Suc (Suc (Suc (Suc (Suc (Suc (Suc 0)))))))" obtain x y z :: var where fresh: "atom y \ x" "atom z \ (x, y)" by (metis obtain_fresh) define t where "t = Let (Let (Auth (Inj1 Unit)) y (Unauth (Var y))) x (Let (Let (Auth Unit) z (Unauth (Var z))) y (Var x))" note fresh_Cons[simp] have prover: "\ [], t \ P\i \ [Inj1 Unit, Unit], Inj1 Unit \" \ \prover execution\ unfolding i_def t_def Suc_eq_plus1 using fresh apply - apply (rule smallsteps.intros)+ apply (rule s_Let1[rotated]) apply (rule s_Let1[rotated]) apply (rule s_AuthP[rotated]) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let2) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthP) apply simp apply simp apply simp apply (rule s_Let2) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let1[rotated]) apply (rule s_AuthP[rotated]) apply simp apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let2) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthP) apply simp apply simp apply simp apply (rule s_Let2[of Unit y _ "Inj1 Unit", simplified]) apply simp done have verifier1: "\ [Inj1 Unit, Unit], t \ V\i \ [], Inj1 Unit \" \ \verifier execution\ unfolding i_def t_def Suc_eq_plus1 using fresh apply - apply (rule smallsteps.intros)+ apply (rule s_Let1[rotated]) apply (rule s_Let1[rotated]) apply (rule s_AuthV[rotated]) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let2) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthV) apply simp apply simp apply simp apply (rule s_Let2) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let1[rotated]) apply (rule s_AuthV[rotated]) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let2) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthV) apply simp apply simp apply simp apply (rule s_Let2[of Unit y _ "Inj1 Unit", simplified]) apply simp done have verifier2: "\ [Inj2 Unit, Unit], t \ V\i \ [], Inj2 Unit \" \ \verifier execution with proofstream containing collision\ unfolding i_def t_def Suc_eq_plus1 using fresh apply - apply (rule smallsteps.intros)+ apply (rule s_Let1[rotated]) apply (rule s_Let1[rotated]) apply (rule s_AuthV[rotated]) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let2) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthV) apply simp apply (simp add: collision) apply simp apply (rule s_Let2) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let1[rotated]) apply (rule s_AuthV[rotated]) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let2) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthV) apply simp apply simp apply simp apply (rule s_Let2[of Unit y _ "Inj2 Unit", simplified]) apply simp done have judge: "{$$} \ t : Sum One One" unfolding t_def using fresh by (force simp: fresh_Pair fresh_fmap_update) have ideal_deterministic: "e = Inj1 Unit" if "\[], t\ I\i \[], e\" for e apply (rule smallsteps_ideal_deterministic[OF that]) unfolding i_def t_def Suc_eq_plus1 using fresh apply - apply (rule smallsteps.intros)+ apply (rule s_Let1[rotated]) apply (rule s_Let1[rotated]) apply (rule s_AuthI[rotated]) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let2) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthI) apply simp apply simp apply (rule s_Let2) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let1[rotated]) apply (rule s_AuthI[rotated]) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Let2) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthI) apply simp apply simp apply (rule s_Let2[of Unit y _ "Inj1 Unit", simplified]) apply simp done from agree[OF judge_imp_agree[OF judge] verifier2] collision prover verifier1 show False proof safe fix e' eP' assume agree: "{$$} \ e', eP', Inj2 Unit : Sum One One" assume assm: "\[], t\ I\i \[], e'\" then have "e' = Inj1 Unit" by (simp add: ideal_deterministic) with agree show False by auto qed (auto dest!: no_collision_with_Unit[OF sym]) qed text \Alternative, shorter counterexample not in administrative normal form.\ lemma security_false_alt: assumes agree: "\e eP eV \ \A i \' eV'. \ {$$} \ e, eP, eV : \; \ \A, eV \ V\i \ \', eV' \ \ \ \e' eP' \ j \0 s s'. (\ [], e \ I\i \ [], e' \ \ \ [], eP \ P\i \ \, eP' \ \ (\A = \ @ \') \ {$$} \ e', eP', eV' : \) \ (j \ i \ \ [], eP \ P\j \ \0 @ [s], eP' \ \ (\A = \0 @ [s'] @ \') \ s \ s' \ hash s = hash s')" and collision: "hash (Inj1 Unit) = hash (Inj2 Unit)" and no_collision_with_Unit: "\t. hash Unit = hash t \ t = Unit" shows False proof - define i where "i = Suc (Suc (Suc (Suc (Suc (Suc 0)))))" obtain x y z :: var where fresh: "atom y \ x" "atom z \ (x, y)" by (metis obtain_fresh) define t where "t = Let (Unauth (Auth (Inj1 Unit))) x (Let (Unauth (Auth Unit)) y (Var x))" note fresh_Cons[simp] have prover: "\ [], t \ P\i \ [Inj1 Unit, Unit], Inj1 Unit \" \ \prover execution\ unfolding i_def t_def Suc_eq_plus1 using fresh apply - apply (rule smallsteps.intros)+ apply (rule s_Let1[rotated]) apply (rule s_Unauth) apply (rule s_AuthP[rotated]) apply simp apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthP) apply simp apply simp apply simp apply (rule s_Let2) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Unauth) apply (rule s_AuthP[rotated]) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthP) apply simp apply simp apply simp apply (rule s_Let2[of Unit y _ "Inj1 Unit", simplified]) apply simp done have verifier1: "\ [Inj1 Unit, Unit], t \ V\i \ [], Inj1 Unit \" \ \verifier execution\ unfolding i_def t_def Suc_eq_plus1 using fresh apply - apply (rule smallsteps.intros)+ apply (rule s_Let1[rotated]) apply (rule s_Unauth) apply (rule s_AuthV[rotated]) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthV) apply simp apply simp apply simp apply (rule s_Let2) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Unauth) apply (rule s_AuthV[rotated]) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthV) apply simp apply simp apply simp apply (rule s_Let2[of Unit y _ "Inj1 Unit", simplified]) apply simp done have verifier2: "\ [Inj2 Unit, Unit], t \ V\i \ [], Inj2 Unit \" \ \verifier execution with proofstream containing collision\ unfolding i_def t_def Suc_eq_plus1 using fresh apply - apply (rule smallsteps.intros)+ apply (rule s_Let1[rotated]) apply (rule s_Unauth) apply (rule s_AuthV[rotated]) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthV) apply simp apply (simp add: collision) apply simp apply (rule s_Let2) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Unauth) apply (rule s_AuthV[rotated]) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthV) apply simp apply simp apply simp apply (rule s_Let2[of Unit y _ "Inj2 Unit", simplified]) apply simp done have judge: "{$$} \ t : Sum One One" unfolding t_def using fresh by (force simp: fresh_Pair fresh_fmap_update) have ideal_deterministic: "e = Inj1 Unit" if "\[], t\ I\i \[], e\" for e apply (rule smallsteps_ideal_deterministic[OF that]) unfolding i_def t_def Suc_eq_plus1 using fresh apply - apply (rule smallsteps.intros)+ apply (rule s_Let1[rotated]) apply (rule s_Unauth) apply (rule s_AuthI[rotated]) apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthI) apply simp apply simp apply (rule s_Let2) apply simp apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_Unauth) apply (rule s_AuthI[rotated]) apply simp apply simp apply (rule s_Let1[rotated]) apply (rule s_UnauthI) apply simp apply simp apply (rule s_Let2[of Unit y _ "Inj1 Unit", simplified]) apply simp done from agree[OF judge_imp_agree[OF judge] verifier2] collision prover verifier1 show False proof safe fix e' eP' assume agree: "{$$} \ e', eP', Inj2 Unit : Sum One One" assume assm: "\[], t\ I\i \[], e'\" then have "e' = Inj1 Unit" by (simp add: ideal_deterministic) with agree show False by auto qed (auto dest!: no_collision_with_Unit[OF sym]) qed subsection \Corrected Theorem 1: Security\ lemma theorem1_security: assumes "{$$} \ e, eP, eV : \" and "\ \\<^sub>A, eV \ V\i \ \', eV' \" shows "(\e' eP' \. \ [], e \ I\i \ [], e' \ \ \ [], eP \ P\i \ \, eP' \ \ \\<^sub>A = \ @ \' \ {$$} \ e', eP', eV' : \) \ (\eP' j \\<^sub>0 \\<^sub>0' s s'. j \ i \ \ [], eP \ P\j \ \\<^sub>0 @ [s], eP' \ \ \\<^sub>A = \\<^sub>0 @ [s'] @ \\<^sub>0' @ \' \ s \ s' \ hash s = hash s' \ closed s \ closed s')" using assms(2,1) proof (induct \\<^sub>A eV V i \' eV' rule: smallsteps.induct) case (s_Id \ e) then show ?case by blast next case (s_Tr \\<^sub>1 eV\<^sub>1 i \\<^sub>2 eV\<^sub>2 \\<^sub>3 eV\<^sub>3) then obtain e\<^sub>2 \ eP\<^sub>2 j \\<^sub>0 \\<^sub>0' s s' where "\[], e\ I\i \[], e\<^sub>2\ \ \[], eP\ P\i \\, eP\<^sub>2\ \ \\<^sub>1 = \ @ \\<^sub>2 \ {$$} \ e\<^sub>2, eP\<^sub>2, eV\<^sub>2 : \ \ j \ i \ \[], eP\ P\j \\\<^sub>0 @ [s], eP\<^sub>2\ \ closed s \ closed s' \ \\<^sub>1 = \\<^sub>0 @ [s'] @ \\<^sub>0' @ \\<^sub>2 \ s \ s' \ hash s = hash s'" by blast then show ?case proof (elim disjE conjE, goal_cases ok collision) case ok obtain e\<^sub>3 eP\<^sub>3 \' where "\[], e\<^sub>2\ I\ \[], e\<^sub>3\" "\\\<^sub>P, eP\<^sub>2\ P\ \\\<^sub>P @ \', eP\<^sub>3\" "{$$} \ e\<^sub>3, eP\<^sub>3, eV\<^sub>3 : \ \ \\<^sub>2 = \' @ \\<^sub>3 \ (\s s'. closed s \ closed s' \ \' = [s] \ \\<^sub>2 = [s'] @ \\<^sub>3 \ s \ s' \ hash s = hash s')" for \\<^sub>P using lemma6[OF ok(4) s_Tr(3), of thesis] by blast then show ?case proof (elim disjE conjE exE, goal_cases ok2 collision) case ok2 with s_Tr(1,3-) ok show ?case by auto next case (collision s s') then show ?case proof (intro disjI2 exI conjI) from ok collision show "\[], eP\ P\i + 1 \\ @ [s], eP\<^sub>3\" by (elim smallsteps.s_Tr) auto from ok collision show "\\<^sub>1 = \ @ [s'] @ [] @ \\<^sub>3" by simp qed simp_all qed next case collision from s_Tr(3) collision show ?case proof (elim smallstepV_consumes_proofstream, intro disjI2 exI conjI) fix \\<^sub>0'' assume *: "\\<^sub>2 = \\<^sub>0'' @ \\<^sub>3" from collision * show "\\<^sub>1 = \\<^sub>0 @ [s'] @ (\\<^sub>0' @ \\<^sub>0'') @ \\<^sub>3" by simp qed simp_all qed qed subsection \Remark 1\ lemma remark1_single: assumes "{$$} \ e, eP, eV : \" and "\ \P, eP \ P\ \ \P @ \, eP' \" obtains e' eV' where "{$$} \ e', eP', eV' : \ \ \ [], e \ I\ \ [], e' \ \ \ \, eV \ V\ \ [], eV' \" proof (atomize_elim, insert assms, nominal_induct "{$$}::tyenv" e eP eV \ avoiding: \P \ eP' rule: agree.strong_induct) case (a_App e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 \\<^sub>2 e\<^sub>2 eP\<^sub>2 eV\<^sub>2) from a_App(5) show ?case proof (cases rule: s_App_inv) case (App1 eP\<^sub>1') with a_App(2,3) show ?thesis by blast next case (App2 eP\<^sub>2') with a_App(1,4) show ?thesis by blast next case (AppLam x eP) from a_App(1)[unfolded \eP\<^sub>1 = Lam x eP\] show ?thesis proof (cases rule: a_Lam_inv_P[case_names Lam]) case (Lam v' vV') with a_App(3) AppLam show ?thesis by (auto 0 4 simp: fresh_Pair del: s_AppLam intro!: s_AppLam lemma4) qed next case (AppRec x e) from a_App(1)[unfolded \eP\<^sub>1 = Rec x e\] show ?thesis proof (cases rule: a_Rec_inv_P[case_names _ Rec]) case (Rec y e'' eP'' eV'') show ?thesis proof (intro exI conjI) let ?e = "App (Lam y (e''[Rec x (Lam y e'') / x])) e\<^sub>2" let ?eV = "App (Lam y (eV''[Rec x (Lam y eV'') / x])) eV\<^sub>2" from a_App(3) Rec AppRec show "{$$} \ ?e, eP', ?eV : \\<^sub>2" by (auto intro!: agree.a_App[where \="{$$}"] lemma4 simp del: subst_term.simps(3) simp: subst_term.simps(3)[symmetric]) from a_App(3) Rec AppRec show "\[], App e\<^sub>1 e\<^sub>2\ I\ \[], ?e\" by (auto intro!: s_AppRec[where v=e\<^sub>2] simp del: subst_term.simps(3) simp: subst_term.simps(3)[symmetric] fresh_Pair) from a_App(3) Rec AppRec show "\\, App eV\<^sub>1 eV\<^sub>2\ V\ \[], ?eV\" by (auto intro!: s_AppRec[where v=eV\<^sub>2] simp del: subst_term.simps(3) simp: subst_term.simps(3)[symmetric] fresh_Pair) qed qed simp qed next case (a_Let x e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2 \\<^sub>2) then have "atom x \ (eP\<^sub>1, \P)" by auto with a_Let(12) show ?case proof (cases rule: s_Let_inv) case Let1 with a_Let show ?thesis by (intro exI[where P = "\x. \y. (Q x y)" for Q, OF exI, of _ "e\<^sub>2[e\<^sub>1 / x]" "eV\<^sub>2[eV\<^sub>1 / x]"]) (auto intro!: lemma4) next case (Let2 eP\<^sub>1') with a_Let(9) obtain e\<^sub>1' eV\<^sub>1' where ih: "{$$} \ e\<^sub>1', eP\<^sub>1', eV\<^sub>1' : \\<^sub>1" "\[], e\<^sub>1\ I\ \[], e\<^sub>1'\" "\\, eV\<^sub>1\ V\ \[], eV\<^sub>1'\" by blast from a_Let Let2 have "\ value e\<^sub>1" "\ value eP\<^sub>1" "\ value eV\<^sub>1" by auto with Let2 a_Let(2,5,7,10) ih show ?thesis by (intro exI[where P = "\x. \y. (Q x y)" for Q, OF exI, of _ "Let e\<^sub>1' x e\<^sub>2" "Let eV\<^sub>1' x eV\<^sub>2"]) (fastforce simp: fresh_Pair del: agree.a_Let intro!: agree.a_Let) qed next case (a_Case e eP eV \\<^sub>1 \\<^sub>2 e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \ e\<^sub>2 eP\<^sub>2 eV\<^sub>2) from a_Case(7) show ?case proof (cases rule: s_Case_inv) case (Case eP'') with a_Case(2,3,5) show ?thesis by blast next case (Inj1 v) with a_Case(1,3,5) show ?thesis by blast next case (Inj2 v) with a_Case(1,3,5) show ?thesis by blast qed next case (a_Prj1 e eP eV \\<^sub>1 \\<^sub>2 \P \ eP') from a_Prj1(3) show ?case proof (cases rule: s_Prj1_inv) case (Prj1 eP'') with a_Prj1(2) show ?thesis by blast next case (PrjPair1 v\<^sub>2) with a_Prj1(1) show ?thesis by fastforce qed next case (a_Prj2 v vP vV \\<^sub>1 \\<^sub>2) from a_Prj2(3) show ?case proof (cases rule: s_Prj2_inv) case (Prj2 eP'') with a_Prj2(2) show ?thesis by blast next case (PrjPair2 v\<^sub>2) with a_Prj2(1) show ?thesis by fastforce qed next case (a_Roll \ e eP eV \) from a_Roll(7) show ?case proof (cases rule: s_Roll_inv) case (Roll eP'') with a_Roll(4,5,6) show ?thesis by blast qed next case (a_Unroll \ e eP eV \) from a_Unroll(7) show ?case proof (cases rule: s_Unroll_inv) case (Unroll eP'') with a_Unroll(5,6) show ?thesis by fastforce next case UnrollRoll with a_Unroll(5) show ?thesis by blast qed next case (a_Auth e eP eV \) from a_Auth(3) show ?case proof (cases rule: s_AuthP_inv) case (Auth eP'') with a_Auth(3) show ?thesis by (auto dest!: a_Auth(2)[of \P \ eP'']) next case AuthP with a_Auth(1) show ?thesis by (auto 0 4 simp: lemma2_1 intro: exI[of _ "Hash (hash \eP\)"] exI[of _ e]) qed next case (a_Unauth e eP eV \) from a_Unauth(1) have eP_closed: "closed eP" using agree_empty_fresh by simp from a_Unauth(3) show ?case proof (cases rule: s_UnauthP_inv) case (Unauth e') with a_Unauth(2) show ?thesis by blast next case (UnauthP h) with a_Unauth(1,3) eP_closed show ?thesis by (force intro: a_AuthT_value_inv[OF a_Unauth(1)] simp: fresh_shallow) qed next case (a_Inj1 e eP eV \\<^sub>1 \\<^sub>2) from a_Inj1(3) show ?case proof (cases rule: s_Inj1_inv) case (Inj1 eP'') with a_Inj1(1,2) show ?thesis by blast qed next case (a_Inj2 e eP eV \\<^sub>2 \\<^sub>1) from a_Inj2(3) show ?case proof (cases rule: s_Inj2_inv) case (Inj2 eP'') with a_Inj2(1,2) show ?thesis by blast qed next case (a_Pair e\<^sub>1 eP\<^sub>1 eV\<^sub>1 \\<^sub>1 e\<^sub>2 eP\<^sub>2 eV\<^sub>2 \\<^sub>2) from a_Pair(5) show ?case proof (cases rule: s_Pair_inv) case (Pair1 eP\<^sub>1') with a_Pair(1,2,3) show ?thesis by blast next case (Pair2 eP\<^sub>2') with a_Pair(1,3,4) show ?thesis by blast qed qed (auto dest: value_no_step) lemma remark1: assumes "{$$} \ e, eP, eV : \" and "\ \\<^sub>P, eP \ P\i \ \\<^sub>P @ \, eP' \" obtains e' eV' where "{$$} \ e', eP', eV' : \" "\ [], e \ I\i \ [], e' \" "\ \, eV \ V\i \ [], eV' \" using assms(2,1) proof (atomize_elim, nominal_induct \\<^sub>P eP P i "\\<^sub>P @ \" eP' arbitrary: \ rule: smallsteps.strong_induct) case (s_Id e \P) then show ?case using s_Id_inv by blast next case (s_Tr \\<^sub>1 eP\<^sub>1 i \\<^sub>2 eP\<^sub>2 eP\<^sub>3) from s_Tr obtain \' \'' where ps: "\\<^sub>2 = \\<^sub>1 @ \'" "\ = \' @ \''" by (force elim: smallstepP_generates_proofstream smallstepsP_generates_proofstream) with s_Tr obtain e\<^sub>2 eV\<^sub>2 where ih: "{$$} \ e\<^sub>2, eP\<^sub>2, eV\<^sub>2 : \" "\[], e\ I\i \[], e\<^sub>2\" "\\', eV\ V\i \[], eV\<^sub>2\" by atomize_elim (auto elim: s_Tr(2)[of \']) moreover obtain e\<^sub>3 eV\<^sub>3 where agree: "{$$} \ e\<^sub>3, eP\<^sub>3, eV\<^sub>3 : \" and "\[], e\<^sub>2\ I\ \[], e\<^sub>3\" "\\'', eV\<^sub>2\ V\ \[], eV\<^sub>3\" by (rule remark1_single[OF ih(1) iffD2[OF smallstepP_ps_prepend s_Tr(3)[unfolded ps]]]) blast ultimately have "\[], e\ I\i + 1 \[], e\<^sub>3\" "\\, eV\ V\i + 1 \[], eV\<^sub>3\" by (auto simp: smallstepsV_ps_append[of _ _ _ "[]", simplified, symmetric] ps intro!: smallsteps.s_Tr[where m=V and \\<^sub>1="\' @ \''" and \\<^sub>2=\'']) with agree show ?case by blast qed (*<*) end (*>*) \ No newline at end of file diff --git a/thys/LambdaAuth/Semantics.thy b/thys/LambdaAuth/Semantics.thy --- a/thys/LambdaAuth/Semantics.thy +++ b/thys/LambdaAuth/Semantics.thy @@ -1,1140 +1,1140 @@ (* Author: Matthias Brun, ETH Zürich, 2019 *) (* Author: Dmitriy Traytel, ETH Zürich, 2019 *) section \Semantics of $\lambda\bullet$\ (*<*) theory Semantics imports FMap_Lemmas Syntax begin (*>*) text \Avoid clash with substitution notation.\ no_notation inverse_divide (infixl "'/" 70) text \Help automated provers with smallsteps.\ declare One_nat_def[simp del] subsection \Equivariant Hash Function\ consts hash_real :: "term \ hash" nominal_function map_fixed :: "var \ var list \ term \ term" where "map_fixed fp l Unit = Unit" | "map_fixed fp l (Var y) = (if y \ set l then (Var y) else (Var fp))" | "atom y \ (fp, l) \ map_fixed fp l (Lam y t) = (Lam y ((map_fixed fp (y # l) t)))" | "atom y \ (fp, l) \ map_fixed fp l (Rec y t) = (Rec y ((map_fixed fp (y # l) t)))" | "map_fixed fp l (Inj1 t) = (Inj1 ((map_fixed fp l t)))" | "map_fixed fp l (Inj2 t) = (Inj2 ((map_fixed fp l t)))" | "map_fixed fp l (Pair t1 t2) = (Pair ((map_fixed fp l t1)) ((map_fixed fp l t2)))" | "map_fixed fp l (Roll t) = (Roll ((map_fixed fp l t)))" | "atom y \ (fp, l) \ map_fixed fp l (Let t1 y t2) = (Let ((map_fixed fp l t1)) y ((map_fixed fp (y # l) t2)))" | "map_fixed fp l (App t1 t2) = (App ((map_fixed fp l t1)) ((map_fixed fp l t2)))" | "map_fixed fp l (Case t1 t2 t3) = (Case ((map_fixed fp l t1)) ((map_fixed fp l t2)) ((map_fixed fp l t3)))" | "map_fixed fp l (Prj1 t) = (Prj1 ((map_fixed fp l t)))" | "map_fixed fp l (Prj2 t) = (Prj2 ((map_fixed fp l t)))" | "map_fixed fp l (Unroll t) = (Unroll ((map_fixed fp l t)))" | "map_fixed fp l (Auth t) = (Auth ((map_fixed fp l t)))" | "map_fixed fp l (Unauth t) = (Unauth ((map_fixed fp l t)))" | "map_fixed fp l (Hash h) = (Hash h)" | "map_fixed fp l (Hashed h t) = (Hashed h ((map_fixed fp l t)))" using [[simproc del: alpha_lst]] subgoal by (simp add: eqvt_def map_fixed_graph_aux_def) subgoal by (erule map_fixed_graph.induct) (auto simp: fresh_star_def fresh_at_base) apply clarify subgoal for P fp l t by (rule term.strong_exhaust[of t P "(fp, l)"]) (auto simp: fresh_star_def fresh_Pair) apply (simp_all add: fresh_star_def fresh_at_base) subgoal for y fp l t ya fpa la ta apply (erule conjE)+ apply (erule Abs_lst1_fcb2'[where c = "(fp, l)"]) apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff fresh_Pair) done subgoal for y fp l t ya fpa la ta apply (erule conjE)+ apply (erule Abs_lst1_fcb2'[where c = "(fp, l)"]) apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff fresh_Pair) done subgoal for y fp l t ya fpa la ta apply (erule conjE)+ apply (erule Abs_lst1_fcb2'[where c = "(fp, l)"]) apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff fresh_Pair) done done nominal_termination (eqvt) by lexicographic_order definition hash where "hash t = hash_real (map_fixed undefined [] t)" lemma permute_map_list: "p \ l = map (\x. p \ x) l" by (induct l) auto lemma map_fixed_eqvt: "p \ l = l \ map_fixed v l (p \ t) = map_fixed v l t" proof (nominal_induct t avoiding: v l p rule: term.strong_induct) case (Var x) then show ?case by (auto simp: term.supp supp_at_base permute_map_list list_eq_iff_nth_eq in_set_conv_nth) next case (Lam y e) from Lam(1,2,3,5) Lam(4)[of p "y # l" v] show ?case by (auto simp: fresh_perm) next case (Rec y e) from Rec(1,2,3,5) Rec(4)[of p "y # l" v] show ?case by (auto simp: fresh_perm) next case (Let e' y e) from Let(1,2,3,6) Let(4)[of p l v] Let(5)[of p "y # l" v] show ?case by (auto simp: fresh_perm) qed (auto simp: permute_pure) lemma hash_eqvt[eqvt]: "p \ hash t = hash (p \ t)" unfolding permute_pure hash_def by (auto simp: map_fixed_eqvt) lemma map_fixed_idle: "{x. \ atom x \ t} \ set l \ map_fixed v l t = t" proof (nominal_induct t avoiding: v l rule: term.strong_induct) case (Var x) then show ?case by (auto simp: subset_iff fresh_at_base) next case (Lam y e) from Lam(1,2,4) Lam(3)[of "y # l" v] show ?case by (auto simp: fresh_Pair Abs1_eq) next case (Rec y e) from Rec(1,2,4) Rec(3)[of "y # l" v] show ?case by (auto simp: fresh_Pair Abs1_eq) next case (Let e' y e) from Let(1,2,5) Let(3)[of l v] Let(4)[of "y # l" v] show ?case by (auto simp: fresh_Pair Abs1_eq) qed (auto simp: subset_iff) lemma map_fixed_inj_closed: "closed t \ closed u \ map_fixed undefined [] t = map_fixed undefined [] u \ t = u" by (erule box_equals[OF _ map_fixed_idle map_fixed_idle]) auto subsection \Substitution\ nominal_function subst_term :: "term \ term \ var \ term" ("_[_ '/ _]" [250, 200, 200] 250) where "Unit[t' / x] = Unit" | "(Var y)[t' / x] = (if x = y then t' else Var y)" | "atom y \ (x, t') \ (Lam y t)[t' / x] = Lam y (t[t' / x])" | "atom y \ (x, t') \ (Rec y t)[t' / x] = Rec y (t[t' / x])" | "(Inj1 t)[t' / x] = Inj1 (t[t' / x])" | "(Inj2 t)[t' / x] = Inj2 (t[t' / x])" | "(Pair t1 t2)[t' / x] = Pair (t1[t' / x]) (t2[t' / x]) " | "(Roll t)[t' / x] = Roll (t[t' / x])" | "atom y \ (x, t') \ (Let t1 y t2)[t' / x] = Let (t1[t' / x]) y (t2[t' / x])" | "(App t1 t2)[t' / x] = App (t1[t' / x]) (t2[t' / x])" | "(Case t1 t2 t3)[t' / x] = Case (t1[t' / x]) (t2[t' / x]) (t3[t' / x])" | "(Prj1 t)[t' / x] = Prj1 (t[t' / x])" | "(Prj2 t)[t' / x] = Prj2 (t[t' / x])" | "(Unroll t)[t' / x] = Unroll (t[t' / x])" | "(Auth t)[t' / x] = Auth (t[t' / x])" | "(Unauth t)[t' / x] = Unauth (t[t' / x])" | "(Hash h)[t' / x] = Hash h" | "(Hashed h t)[t' / x] = Hashed h (t[t' / x])" using [[simproc del: alpha_lst]] subgoal by (simp add: eqvt_def subst_term_graph_aux_def) subgoal by (erule subst_term_graph.induct) (auto simp: fresh_star_def fresh_at_base) apply clarify subgoal for P a b t by (rule term.strong_exhaust[of a P "(b, t)"]) (auto simp: fresh_star_def fresh_Pair) apply (simp_all add: fresh_star_def fresh_at_base) subgoal apply (erule conjE) apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff fresh_Pair) done subgoal apply (erule conjE) apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff fresh_Pair) done subgoal apply (erule conjE) apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff fresh_Pair) done done nominal_termination (eqvt) by lexicographic_order type_synonym tenv = "(var, term) fmap" nominal_function psubst_term :: "term \ tenv \ term" where "psubst_term Unit f = Unit" | "psubst_term (Var y) f = (case f $$ y of Some t \ t | None \ Var y)" | "atom y \ f \ psubst_term (Lam y t) f = Lam y (psubst_term t f)" | "atom y \ f \ psubst_term (Rec y t) f = Rec y (psubst_term t f)" | "psubst_term (Inj1 t) f = Inj1 (psubst_term t f)" | "psubst_term (Inj2 t) f = Inj2 (psubst_term t f)" | "psubst_term (Pair t1 t2) f = Pair (psubst_term t1 f) (psubst_term t2 f) " | "psubst_term (Roll t) f = Roll (psubst_term t f)" | "atom y \ f \ psubst_term (Let t1 y t2) f = Let (psubst_term t1 f) y (psubst_term t2 f)" | "psubst_term (App t1 t2) f = App (psubst_term t1 f) (psubst_term t2 f)" | "psubst_term (Case t1 t2 t3) f = Case (psubst_term t1 f) (psubst_term t2 f) (psubst_term t3 f)" | "psubst_term (Prj1 t) f = Prj1 (psubst_term t f)" | "psubst_term (Prj2 t) f = Prj2 (psubst_term t f)" | "psubst_term (Unroll t) f = Unroll (psubst_term t f)" | "psubst_term (Auth t) f = Auth (psubst_term t f)" | "psubst_term (Unauth t) f = Unauth (psubst_term t f)" | "psubst_term (Hash h) f = Hash h" | "psubst_term (Hashed h t) f = Hashed h (psubst_term t f)" using [[simproc del: alpha_lst]] subgoal by (simp add: eqvt_def psubst_term_graph_aux_def) subgoal by (erule psubst_term_graph.induct) (auto simp: fresh_star_def fresh_at_base) apply clarify subgoal for P a b by (rule term.strong_exhaust[of a P b]) (auto simp: fresh_star_def fresh_Pair) apply (simp_all add: fresh_star_def fresh_at_base) subgoal by clarify subgoal apply (erule conjE) apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff) done subgoal apply (erule conjE) apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff) done subgoal apply (erule conjE) apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff) done done nominal_termination (eqvt) by lexicographic_order nominal_function subst_type :: "ty \ ty \ tvar \ ty" where "subst_type One t' x = One" | "subst_type (Fun t1 t2) t' x = Fun (subst_type t1 t' x) (subst_type t2 t' x)" | "subst_type (Sum t1 t2) t' x = Sum (subst_type t1 t' x) (subst_type t2 t' x)" | "subst_type (Prod t1 t2) t' x = Prod (subst_type t1 t' x) (subst_type t2 t' x)" | "atom y \ (t', x) \ subst_type (Mu y t) t' x = Mu y (subst_type t t' x)" | "subst_type (Alpha y) t' x = (if y = x then t' else Alpha y)" | "subst_type (AuthT t) t' x = AuthT (subst_type t t' x)" using [[simproc del: alpha_lst]] subgoal by (simp add: eqvt_def subst_type_graph_aux_def) subgoal by (erule subst_type_graph.induct) (auto simp: fresh_star_def fresh_at_base) apply clarify subgoal for P a by (rule ty.strong_exhaust[of a P]) (auto simp: fresh_star_def) apply (simp_all add: fresh_star_def fresh_at_base) subgoal apply (erule conjE) apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff fresh_Pair) done done nominal_termination (eqvt) by lexicographic_order lemma fresh_subst_term: "atom x \ t[t' / x'] \ (x = x' \ atom x \ t) \ (atom x' \ t \ atom x \ t')" by (nominal_induct t avoiding: t' x x' rule: term.strong_induct) (auto simp add: fresh_at_base) lemma term_fresh_subst[simp]: "atom x \ t \ atom x \ s \ (atom (x::var)) \ t[s / y]" by (nominal_induct t avoiding: s y rule: term.strong_induct) (auto) lemma term_subst_idle[simp]: "atom y \ t \ t[s / y] = t" by (nominal_induct t avoiding: s y rule: term.strong_induct) (auto simp: fresh_Pair fresh_at_base) lemma term_subst_subst: "atom y1 \ atom y2 \ atom y1 \ s2 \ t[s1 / y1][s2 / y2] = t[s2 / y2][s1[s2 / y2] / y1]" by (nominal_induct t avoiding: y1 y2 s1 s2 rule: term.strong_induct) auto lemma fresh_psubst: fixes x :: var assumes "atom x \ e" "atom x \ vs" shows "atom x \ psubst_term e vs" using assms by (induct e vs rule: psubst_term.induct) (auto simp: fresh_at_base elim: fresh_fmap_fresh_Some split: option.splits) lemma fresh_subst_type: "atom \ \ subst_type \ \' \' \ ((\ = \' \ atom \ \ \) \ (atom \' \ \ \ atom \ \ \'))" by (nominal_induct \ avoiding: \ \' \' rule: ty.strong_induct) (auto simp add: fresh_at_base) lemma type_fresh_subst[simp]: "atom x \ t \ atom x \ s \ (atom (x::tvar)) \ subst_type t s y" by (nominal_induct t avoiding: s y rule: ty.strong_induct) (auto) lemma type_subst_idle[simp]: "atom y \ t \ subst_type t s y = t" by (nominal_induct t avoiding: s y rule: ty.strong_induct) (auto simp: fresh_Pair fresh_at_base) -lemma type_subst_subst: "atom y1 \ atom y2 \ atom y1 \ s2 \ +lemma type_subst_subst: "atom y1 \ atom y2 \ atom y1 \ s2 \ subst_type (subst_type t s1 y1) s2 y2 = subst_type (subst_type t s2 y2) (subst_type s1 s2 y2) y1" by (nominal_induct t avoiding: y1 y2 s1 s2 rule: ty.strong_induct) auto subsection \Weak Typing Judgement\ type_synonym tyenv = "(var, ty) fmap" inductive judge_weak :: "tyenv \ term \ ty \ bool" ("_ \\<^sub>W _ : _" [150,0,150] 149) where jw_Unit: "\ \\<^sub>W Unit : One" | jw_Var: "\ \ $$ x = Some \ \ \ \ \\<^sub>W Var x : \" | jw_Lam: "\ atom x \ \; \(x $$:= \\<^sub>1) \\<^sub>W e : \\<^sub>2 \ \ \ \\<^sub>W Lam x e : Fun \\<^sub>1 \\<^sub>2" | jw_App: "\ \ \\<^sub>W e : Fun \\<^sub>1 \\<^sub>2; \ \\<^sub>W e' : \\<^sub>1 \ \ \ \\<^sub>W App e e' : \\<^sub>2" | jw_Let: "\ atom x \ (\, e\<^sub>1); \ \\<^sub>W e\<^sub>1 : \\<^sub>1; \(x $$:= \\<^sub>1) \\<^sub>W e\<^sub>2 : \\<^sub>2 \ \ \ \\<^sub>W Let e\<^sub>1 x e\<^sub>2 : \\<^sub>2" | jw_Rec: "\ atom x \ \; atom y \ (\,x); \(x $$:= Fun \\<^sub>1 \\<^sub>2) \\<^sub>W Lam y e : Fun \\<^sub>1 \\<^sub>2 \ \ \ \\<^sub>W Rec x (Lam y e) : Fun \\<^sub>1 \\<^sub>2" | jw_Inj1: "\ \ \\<^sub>W e : \\<^sub>1 \ \ \ \\<^sub>W Inj1 e : Sum \\<^sub>1 \\<^sub>2" | jw_Inj2: "\ \ \\<^sub>W e : \\<^sub>2 \ \ \ \\<^sub>W Inj2 e : Sum \\<^sub>1 \\<^sub>2" | jw_Case: "\ \ \\<^sub>W e : Sum \\<^sub>1 \\<^sub>2; \ \\<^sub>W e\<^sub>1 : Fun \\<^sub>1 \; \ \\<^sub>W e\<^sub>2 : Fun \\<^sub>2 \ \ \ \ \\<^sub>W Case e e\<^sub>1 e\<^sub>2 : \" | jw_Pair: "\ \ \\<^sub>W e\<^sub>1 : \\<^sub>1; \ \\<^sub>W e\<^sub>2 : \\<^sub>2 \ \ \ \\<^sub>W Pair e\<^sub>1 e\<^sub>2 : Prod \\<^sub>1 \\<^sub>2" | jw_Prj1: "\ \ \\<^sub>W e : Prod \\<^sub>1 \\<^sub>2 \ \ \ \\<^sub>W Prj1 e : \\<^sub>1" | jw_Prj2: "\ \ \\<^sub>W e : Prod \\<^sub>1 \\<^sub>2 \ \ \ \\<^sub>W Prj2 e : \\<^sub>2" | jw_Roll: "\ atom \ \ \; \ \\<^sub>W e : subst_type \ (Mu \ \) \ \ \ \ \\<^sub>W Roll e : Mu \ \" | jw_Unroll: "\ atom \ \ \; \ \\<^sub>W e : Mu \ \ \ \ \ \\<^sub>W Unroll e : subst_type \ (Mu \ \) \" | jw_Auth: "\ \ \\<^sub>W e : \ \ \ \ \\<^sub>W Auth e : \" | jw_Unauth: "\ \ \\<^sub>W e : \ \ \ \ \\<^sub>W Unauth e : \" declare judge_weak.intros[simp] declare judge_weak.intros[intro] equivariance judge_weak nominal_inductive judge_weak avoids jw_Lam: x | jw_Rec: x and y | jw_Let: x | jw_Roll: \ | jw_Unroll: \ by (auto simp: fresh_subst_type fresh_Pair) text \Inversion rules for typing judgment.\ inductive_cases jw_Unit_inv[elim]: "\ \\<^sub>W Unit : \" inductive_cases jw_Var_inv[elim]: "\ \\<^sub>W Var x : \" lemma jw_Lam_inv[elim]: assumes "\ \\<^sub>W Lam x e : \" and "atom x \ \" obtains \\<^sub>1 \\<^sub>2 where "\ = Fun \\<^sub>1 \\<^sub>2" "(\(x $$:= \\<^sub>1)) \\<^sub>W e : \\<^sub>2" using assms proof (atomize_elim, nominal_induct \ "Lam x e" \ avoiding: x e rule: judge_weak.strong_induct) case (jw_Lam x \ \\<^sub>1 t \\<^sub>2 y u) then show ?case by (auto simp: perm_supp_eq elim!: iffD1[OF Abs_lst1_fcb2'[where f = "\x t (\, \\<^sub>1, \\<^sub>2). (\(x $$:= \\<^sub>1)) \\<^sub>W t : \\<^sub>2" and c = "(\, \\<^sub>1, \\<^sub>2)" and a = x and b = y and x = t and y = u, unfolded prod.case], rotated -1]) qed lemma swap_permute_swap: "atom x \ \ \ atom y \ \ \ (x \ y) \ \ \ (x \ y) \ t = \ \ t" by (subst permute_eqvt) (auto simp: flip_fresh_fresh) lemma jw_Rec_inv[elim]: assumes "\ \\<^sub>W Rec x t : \" and "atom x \ \" obtains y e \\<^sub>1 \\<^sub>2 where "atom y \ (\,x)" "t = Lam y e" "\ = Fun \\<^sub>1 \\<^sub>2" "\(x $$:= Fun \\<^sub>1 \\<^sub>2) \\<^sub>W Lam y e : Fun \\<^sub>1 \\<^sub>2" using [[simproc del: alpha_lst]] assms proof (atomize_elim, nominal_induct \ "Rec x t" \ avoiding: x t rule: judge_weak.strong_induct) case (jw_Rec x \ y \\<^sub>1 \\<^sub>2 e z t) then show ?case proof (nominal_induct t avoiding: y x z rule: term.strong_induct) case (Lam y' e') show ?case proof (intro exI conjI) from Lam.prems show "atom y \ (\, z)" by simp from Lam.hyps(1-3) Lam.prems show "Lam y' e' = Lam y ((y' \ y) \ e')" by (subst term.eq_iff(3), intro Abs_lst_eq_flipI) (simp add: fresh_at_base) from Lam.hyps(1-3) Lam.prems show "\(z $$:= Fun \\<^sub>1 \\<^sub>2) \\<^sub>W Lam y ((y' \ y) \ e') : Fun \\<^sub>1 \\<^sub>2" by (elim judge_weak.eqvt[of "\(x $$:= Fun \\<^sub>1 \\<^sub>2)" "Lam y e" "Fun \\<^sub>1 \\<^sub>2" "(x \ z)", elim_format]) (simp add: perm_supp_eq Abs1_eq_iff fresh_at_base swap_permute_swap fresh_perm flip_commute) qed simp qed (simp_all add: Abs1_eq_iff) qed inductive_cases jw_Inj1_inv[elim]: "\ \\<^sub>W Inj1 e : \" inductive_cases jw_Inj2_inv[elim]: "\ \\<^sub>W Inj2 e : \" inductive_cases jw_Pair_inv[elim]: "\ \\<^sub>W Pair e\<^sub>1 e\<^sub>2 : \" lemma jw_Let_inv[elim]: assumes "\ \\<^sub>W Let e\<^sub>1 x e\<^sub>2 : \\<^sub>2" and "atom x \ (e\<^sub>1, \)" obtains \\<^sub>1 where "\ \\<^sub>W e\<^sub>1 : \\<^sub>1" "\(x $$:= \\<^sub>1) \\<^sub>W e\<^sub>2 : \\<^sub>2" using assms proof (atomize_elim, nominal_induct \ "Let e\<^sub>1 x e\<^sub>2" \\<^sub>2 avoiding: e\<^sub>1 x e\<^sub>2 rule: judge_weak.strong_induct) case (jw_Let x \ e\<^sub>1 \\<^sub>1 e\<^sub>2 \\<^sub>2 x' e\<^sub>2') then show ?case by (auto simp: fresh_Pair perm_supp_eq elim!: iffD1[OF Abs_lst1_fcb2'[where f = "\x t (\, \\<^sub>1, \\<^sub>2). \(x $$:= \\<^sub>1) \\<^sub>W t : \\<^sub>2" and c = "(\, \\<^sub>1, \\<^sub>2)" and a = x and b = x' and x = e\<^sub>2 and y = e\<^sub>2', unfolded prod.case], rotated -1]) qed inductive_cases jw_Prj1_inv[elim]: "\ \\<^sub>W Prj1 e : \\<^sub>1" inductive_cases jw_Prj2_inv[elim]: "\ \\<^sub>W Prj2 e : \\<^sub>2" inductive_cases jw_App_inv[elim]: "\ \\<^sub>W App e e' : \\<^sub>2" inductive_cases jw_Case_inv[elim]: "\ \\<^sub>W Case e e\<^sub>1 e\<^sub>2 : \" inductive_cases jw_Auth_inv[elim]: "\ \\<^sub>W Auth e : \" inductive_cases jw_Unauth_inv[elim]: "\ \\<^sub>W Unauth e : \" lemma subst_type_perm_eq: assumes "atom b \ t" shows "subst_type t (Mu a t) a = subst_type ((a \ b) \ t) (Mu b ((a \ b) \ t)) b" using assms proof - have f: "atom a \ subst_type t (Mu a t) a" by (rule iffD2[OF fresh_subst_type]) simp have "atom b \ subst_type t (Mu a t) a" by (auto simp: assms) with f have "subst_type t (Mu a t) a = (a \ b) \ subst_type t (Mu a t) a" by (simp add: flip_fresh_fresh) then show "subst_type t (Mu a t) a = subst_type ((a \ b) \ t) (Mu b ((a \ b) \ t)) b" by simp qed lemma jw_Roll_inv[elim]: assumes "\ \\<^sub>W Roll e : \" and "atom \ \ (\, \)" obtains \' where "\ = Mu \ \'" "\ \\<^sub>W e : subst_type \' (Mu \ \') \" using assms [[simproc del: alpha_lst]] proof (atomize_elim, nominal_induct \ "Roll e" \ avoiding: e \ rule: judge_weak.strong_induct) case (jw_Roll \ \ e \ \') then show ?case by (auto simp: perm_supp_eq fresh_Pair fresh_at_base subst_type.eqvt intro!: exI[of _ "(\ \ \') \ \"] Abs_lst_eq_flipI dest: judge_weak.eqvt[of _ _ _ "(\ \ \')"]) qed lemma jw_Unroll_inv[elim]: assumes "\ \\<^sub>W Unroll e : \" and "atom \ \ (\, \)" obtains \' where "\ = subst_type \' (Mu \ \') \" "\ \\<^sub>W e : Mu \ \'" using assms proof (atomize_elim, nominal_induct \ "Unroll e" \ avoiding: e \ rule: judge_weak.strong_induct) case (jw_Unroll \ \ e \ \') then show ?case by (auto simp: perm_supp_eq fresh_Pair subst_type_perm_eq fresh_subst_type intro!: exI[of _ "(\ \ \') \ \"] dest: judge_weak.eqvt[of _ _ _ "(\ \ \')"]) qed text \Additional inversion rules based on type rather than term.\ inductive_cases jw_Prod_inv[elim]: "{$$} \\<^sub>W e : Prod \\<^sub>1 \\<^sub>2" inductive_cases jw_Sum_inv[elim]: "{$$} \\<^sub>W e : Sum \\<^sub>1 \\<^sub>2" lemma jw_Fun_inv[elim]: assumes "{$$} \\<^sub>W v : Fun \\<^sub>1 \\<^sub>2" "value v" obtains e x where "v = Lam x e \ v = Rec x e" "atom x \ (c::term)" using assms [[simproc del: alpha_lst]] proof (atomize_elim, nominal_induct "{$$} :: tyenv" v "Fun \\<^sub>1 \\<^sub>2" avoiding: \\<^sub>1 \\<^sub>2 rule: judge_weak.strong_induct) case (jw_Lam x \\<^sub>1 e \\<^sub>2) then obtain x' where "atom (x'::var) \ (c, e)" using finite_supp obtain_fresh' by blast then have "[[atom x]]lst. e = [[atom x']]lst. (x \ x') \ e \ atom x' \ c" by (simp add: Abs_lst_eq_flipI fresh_Pair) then show ?case by auto next case (jw_Rec x y \\<^sub>1 \\<^sub>2 e') obtain x' where "atom (x'::var) \ (c, Lam y e')" using finite_supp obtain_fresh by blast then have "[[atom x]]lst. Lam y e' = [[atom x']]lst. (x \ x') \ (Lam y e') \ atom x' \ c" using Abs_lst_eq_flipI fresh_Pair by blast then show ?case by auto qed simp_all lemma jw_Mu_inv[elim]: assumes "{$$} \\<^sub>W v : Mu \ \" "value v" obtains v' where "v = Roll v'" using assms by (atomize_elim, nominal_induct "{$$} :: tyenv" v "Mu \ \" rule: judge_weak.strong_induct) simp_all subsection \Erasure of Authenticated Types\ nominal_function erase :: "ty \ ty" where "erase One = One" | "erase (Fun \\<^sub>1 \\<^sub>2) = Fun (erase \\<^sub>1) (erase \\<^sub>2)" | "erase (Sum \\<^sub>1 \\<^sub>2) = Sum (erase \\<^sub>1) (erase \\<^sub>2)" | "erase (Prod \\<^sub>1 \\<^sub>2) = Prod (erase \\<^sub>1) (erase \\<^sub>2)" | "erase (Mu \ \) = Mu \ (erase \)" | "erase (Alpha \) = Alpha \" | "erase (AuthT \) = erase \" using [[simproc del: alpha_lst]] subgoal by (simp add: eqvt_def erase_graph_aux_def) subgoal by (erule erase_graph.induct) (auto simp: fresh_star_def fresh_at_base) subgoal for P x by (rule ty.strong_exhaust[of x P x]) (auto simp: fresh_star_def) apply (simp_all add: fresh_star_def fresh_at_base) subgoal apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff) done done nominal_termination (eqvt) by lexicographic_order lemma fresh_erase_fresh: assumes "atom x \ \" shows "atom x \ erase \" using assms by (induct \ rule: ty.induct) auto lemma fresh_fmmap_erase_fresh: assumes "atom x \ \" shows "atom x \ fmmap erase \" using assms by transfer simp lemma erase_subst_type_shift[simp]: "erase (subst_type \ \' \) = subst_type (erase \) (erase \') \" by (induct \ \' \ rule: subst_type.induct) (auto simp: fresh_Pair fresh_erase_fresh) definition erase_env :: "tyenv \ tyenv" where "erase_env = fmmap erase" subsection \Strong Typing Judgement\ inductive judge :: "tyenv \ term \ ty \ bool" ("_ \ _ : _" [150,0,150] 149) where j_Unit: "\ \ Unit : One" | j_Var: "\ \ $$ x = Some \ \ \ \ \ Var x : \" | j_Lam: "\ atom x \ \; \(x $$:= \\<^sub>1) \ e : \\<^sub>2 \ \ \ \ Lam x e : Fun \\<^sub>1 \\<^sub>2" | j_App: "\ \ \ e : Fun \\<^sub>1 \\<^sub>2; \ \ e' : \\<^sub>1 \ \ \ \ App e e' : \\<^sub>2" | j_Let: "\ atom x \ (\, e\<^sub>1); \ \ e\<^sub>1 : \\<^sub>1; \(x $$:= \\<^sub>1) \ e\<^sub>2 : \\<^sub>2 \ \ \ \ Let e\<^sub>1 x e\<^sub>2 : \\<^sub>2" | j_Rec: "\ atom x \ \; atom y \ (\,x); \(x $$:= Fun \\<^sub>1 \\<^sub>2) \ Lam y e' : Fun \\<^sub>1 \\<^sub>2 \ \ \ \ Rec x (Lam y e') : Fun \\<^sub>1 \\<^sub>2" | j_Inj1: "\ \ \ e : \\<^sub>1 \ \ \ \ Inj1 e : Sum \\<^sub>1 \\<^sub>2" | j_Inj2: "\ \ \ e : \\<^sub>2 \ \ \ \ Inj2 e : Sum \\<^sub>1 \\<^sub>2" | j_Case: "\ \ \ e : Sum \\<^sub>1 \\<^sub>2; \ \ e\<^sub>1 : Fun \\<^sub>1 \; \ \ e\<^sub>2 : Fun \\<^sub>2 \ \ \ \ \ Case e e\<^sub>1 e\<^sub>2 : \" | j_Pair: "\ \ \ e\<^sub>1 : \\<^sub>1; \ \ e\<^sub>2 : \\<^sub>2 \ \ \ \ Pair e\<^sub>1 e\<^sub>2 : Prod \\<^sub>1 \\<^sub>2" | j_Prj1: "\ \ \ e : Prod \\<^sub>1 \\<^sub>2 \ \ \ \ Prj1 e : \\<^sub>1" | j_Prj2: "\ \ \ e : Prod \\<^sub>1 \\<^sub>2 \ \ \ \ Prj2 e : \\<^sub>2" | j_Roll: "\ atom \ \ \; \ \ e : subst_type \ (Mu \ \) \ \ \ \ \ Roll e : Mu \ \" | j_Unroll: "\ atom \ \ \; \ \ e : Mu \ \ \ \ \ \ Unroll e : subst_type \ (Mu \ \) \" | j_Auth: "\ \ \ e : \ \ \ \ \ Auth e : AuthT \" | j_Unauth: "\ \ \ e : AuthT \ \ \ \ \ Unauth e : \" declare judge.intros[intro] equivariance judge nominal_inductive judge avoids j_Lam: x | j_Rec: x and y | j_Let: x | j_Roll: \ | j_Unroll: \ by (auto simp: fresh_subst_type fresh_Pair) lemma judge_imp_judge_weak: assumes "\ \ e : \" shows "erase_env \ \\<^sub>W e : erase \" using assms unfolding erase_env_def by (induct \ e \ rule: judge.induct) (simp_all add: fresh_Pair fresh_fmmap_erase_fresh fmmap_fmupd) subsection \Shallow Projection\ nominal_function shallow :: "term \ term" ("\_\") where "\Unit\ = Unit" | "\Var v\ = Var v" | "\Lam x e\ = Lam x \e\" | "\Rec x e\ = Rec x \e\" | "\Inj1 e\ = Inj1 \e\" | "\Inj2 e\ = Inj2 \e\" | "\Pair e\<^sub>1 e\<^sub>2\ = Pair \e\<^sub>1\ \e\<^sub>2\" | "\Roll e\ = Roll \e\" | "\Let e\<^sub>1 x e\<^sub>2\ = Let \e\<^sub>1\ x \e\<^sub>2\" | "\App e\<^sub>1 e\<^sub>2\ = App \e\<^sub>1\ \e\<^sub>2\" | "\Case e e\<^sub>1 e\<^sub>2\ = Case \e\ \e\<^sub>1\ \e\<^sub>2\" | "\Prj1 e\ = Prj1 \e\" | "\Prj2 e\ = Prj2 \e\" | "\Unroll e\ = Unroll \e\" | "\Auth e\ = Auth \e\" | "\Unauth e\ = Unauth \e\" | \ \No rule is defined for Hash, but: "[..] preserving that structure in every case but that of [..]"\ "\Hash h\ = Hash h" | "\Hashed h e\ = Hash h" using [[simproc del: alpha_lst]] subgoal by (simp add: eqvt_def shallow_graph_aux_def) subgoal by (erule shallow_graph.induct) (auto simp: fresh_star_def fresh_at_base) subgoal for P a by (rule term.strong_exhaust[of a P a]) (auto simp: fresh_star_def) apply (simp_all add: fresh_star_def fresh_at_base) subgoal apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff) done subgoal apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff) done subgoal apply (erule conjE) apply (erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: perm_supp_eq Abs_fresh_iff) done done nominal_termination (eqvt) by lexicographic_order lemma fresh_shallow: "atom x \ e \ atom x \ \e\" by (induct e rule: term.induct) auto subsection \Small-step Semantics\ datatype mode = I | P | V \ \Ideal, Prover and Verifier modes\ instantiation mode :: pure begin definition permute_mode :: "perm \ mode \ mode" where "permute_mode \ h = h" instance proof qed (auto simp: permute_mode_def) end type_synonym proofstream = "term list" inductive smallstep :: "proofstream \ term \ mode \ proofstream \ term \ bool" ("\_, _\ _\ \_, _\") where s_App1: "\ \ \, e\<^sub>1 \ m\ \ \', e\<^sub>1' \ \ \ \ \, App e\<^sub>1 e\<^sub>2 \ m\ \ \', App e\<^sub>1' e\<^sub>2 \" | s_App2: "\ value v\<^sub>1; \ \, e\<^sub>2 \ m\ \ \', e\<^sub>2' \ \ \ \ \, App v\<^sub>1 e\<^sub>2 \ m\ \ \', App v\<^sub>1 e\<^sub>2' \" | s_AppLam: "\ value v; atom x \ (v,\) \ \ \ \, App (Lam x e) v \ _\ \ \, e[v / x] \" | s_AppRec: "\ value v; atom x \ (v,\) \ \ \ \, App (Rec x e) v \ _\ \ \, App (e[(Rec x e) / x]) v \" | s_Let1: "\ atom x \ (e\<^sub>1,e\<^sub>1',\,\'); \ \, e\<^sub>1 \ m\ \ \', e\<^sub>1' \ \ \ \ \, Let e\<^sub>1 x e\<^sub>2 \ m\ \ \', Let e\<^sub>1' x e\<^sub>2 \" | s_Let2: "\ value v; atom x \ (v,\) \ \ \ \, Let v x e \ _\ \ \, e[v / x] \" | s_Inj1: "\ \ \, e \ m\ \ \', e' \ \ \ \ \, Inj1 e \ m\ \ \', Inj1 e' \" | s_Inj2: "\ \ \, e \ m\ \ \', e' \ \ \ \ \, Inj2 e \ m\ \ \', Inj2 e' \" | s_Case: "\ \ \, e \ m\ \ \', e' \ \ \ \ \, Case e e\<^sub>1 e\<^sub>2 \ m\ \ \', Case e' e\<^sub>1 e\<^sub>2 \" | \ \Case rules are different from paper to account for recursive functions.\ s_CaseInj1: "\ value v \ \ \ \, Case (Inj1 v) e\<^sub>1 e\<^sub>2 \ _\ \ \, App e\<^sub>1 v \" | s_CaseInj2: "\ value v \ \ \ \, Case (Inj2 v) e\<^sub>1 e\<^sub>2 \ _\ \ \, App e\<^sub>2 v \" | s_Pair1: "\ \ \, e\<^sub>1 \ m\ \ \', e\<^sub>1' \ \ \ \ \, Pair e\<^sub>1 e\<^sub>2 \ m\ \ \', Pair e\<^sub>1' e\<^sub>2 \" | s_Pair2: "\ value v\<^sub>1; \ \, e\<^sub>2 \ m\ \ \', e\<^sub>2' \ \ \ \ \, Pair v\<^sub>1 e\<^sub>2 \ m\ \ \', Pair v\<^sub>1 e\<^sub>2' \" | s_Prj1: "\ \ \, e \ m\ \ \', e' \ \ \ \ \, Prj1 e \ m\ \ \', Prj1 e' \" | s_Prj2: "\ \ \, e \ m\ \ \', e' \ \ \ \ \, Prj2 e \ m\ \ \', Prj2 e' \" | s_PrjPair1: "\ value v\<^sub>1; value v\<^sub>2 \ \ \ \, Prj1 (Pair v\<^sub>1 v\<^sub>2) \ _\ \ \, v\<^sub>1 \" | s_PrjPair2: "\ value v\<^sub>1; value v\<^sub>2 \ \ \ \, Prj2 (Pair v\<^sub>1 v\<^sub>2) \ _\ \ \, v\<^sub>2 \" | s_Unroll: "\ \, e \ m\ \ \', e' \ \ \ \, Unroll e \ m\ \ \', Unroll e' \" | s_Roll: "\ \, e \ m\ \ \', e' \ \ \ \, Roll e \ m\ \ \', Roll e' \" | s_UnrollRoll:"\ value v \ \ \ \, Unroll (Roll v) \ _\ \ \, v \" | \ \Mode-specific rules\ s_Auth: "\ \, e \ m\ \ \', e' \ \ \ \, Auth e \ m\ \ \', Auth e' \" | s_Unauth: "\ \, e \ m\ \ \', e' \ \ \ \, Unauth e \ m\ \ \', Unauth e' \" | s_AuthI: "\ value v \ \ \ \, Auth v \ I\ \ \, v \" | s_UnauthI: "\ value v \ \ \ \, Unauth v \ I\ \ \, v \" | s_AuthP: "\ closed \v\; value v \ \ \ \, Auth v \ P\ \ \, Hashed (hash \v\) v \" | s_UnauthP: "\ value v \ \ \ \, Unauth (Hashed h v) \ P\ \ \ @ [\v\], v \" | s_AuthV: "\ closed v; value v \ \ \ \, Auth v \ V\ \ \, Hash (hash v) \" | s_UnauthV: "\ closed s\<^sub>0; hash s\<^sub>0 = h \ \ \ s\<^sub>0#\, Unauth (Hash h) \ V\ \ \, s\<^sub>0 \" declare smallstep.intros[simp] declare smallstep.intros[intro] equivariance smallstep nominal_inductive smallstep avoids s_AppLam: x | s_AppRec: x | s_Let1: x | s_Let2: x by (auto simp add: fresh_Pair fresh_subst_term) inductive smallsteps :: "proofstream \ term \ mode \ nat \ proofstream \ term \ bool" ("\_, _\ _\_ \_, _\") where s_Id: "\ \, e \ _\0 \ \, e \" | s_Tr: "\ \ \\<^sub>1, e\<^sub>1 \ m\i \ \\<^sub>2, e\<^sub>2 \; \ \\<^sub>2, e\<^sub>2 \ m\ \ \\<^sub>3, e\<^sub>3 \ \ \ \ \\<^sub>1, e\<^sub>1 \ m\(i+1) \ \\<^sub>3, e\<^sub>3 \" declare smallsteps.intros[simp] declare smallsteps.intros[intro] equivariance smallsteps nominal_inductive smallsteps . lemma steps_1_step[simp]: "\ \, e \ m\1 \ \', e' \ = \ \, e \ m\ \ \', e' \" (is "?L \ ?R") proof assume ?L then show ?R proof (induct \ e m "1::nat" \' e' rule: smallsteps.induct) case (s_Tr \\<^sub>1 e\<^sub>1 m i \\<^sub>2 e\<^sub>2 \\<^sub>3 e\<^sub>3) then show ?case by (induct \\<^sub>1 e\<^sub>1 m i \\<^sub>2 e\<^sub>2 rule: smallsteps.induct) auto qed simp qed (auto intro: s_Tr[where i=0, simplified]) text \Inversion rules for smallstep(s) predicates.\ lemma value_no_step[intro]: assumes "\ \\<^sub>1, v \ m\ \ \\<^sub>2, t \" "value v" shows "False" using assms by (induct \\<^sub>1 v m \\<^sub>2 t rule: smallstep.induct) auto lemma subst_term_perm: assumes "atom x' \ (x, e)" shows "e[v / x] = ((x \ x') \ e)[v / x']" using assms [[simproc del: alpha_lst]] by (nominal_induct e avoiding: x x' v rule: term.strong_induct) (auto simp: fresh_Pair fresh_at_base(2) permute_hash_def) inductive_cases s_Unit_inv[elim]: "\ \\<^sub>1, Unit \ m\ \ \\<^sub>2, v \" inductive_cases s_App_inv[consumes 1, case_names App1 App2 AppLam AppRec, elim]: "\ \, App v\<^sub>1 v\<^sub>2 \ m\ \ \', e \" lemma s_Let_inv': assumes "\ \, Let e\<^sub>1 x e\<^sub>2 \ m\ \ \', e' \" and "atom x \ (e\<^sub>1,\)" obtains e\<^sub>1' where "(e' = e\<^sub>2[e\<^sub>1 / x] \ value e\<^sub>1 \ \ = \') \ (\ \, e\<^sub>1 \ m\ \ \', e\<^sub>1' \ \ e' = Let e\<^sub>1' x e\<^sub>2 \ \ value e\<^sub>1)" using assms [[simproc del: alpha_lst]] by (atomize_elim, induct \ "Let e\<^sub>1 x e\<^sub>2" m \' e' rule: smallstep.induct) (auto simp: fresh_Pair fresh_subst_term perm_supp_eq elim: Abs_lst1_fcb2') lemma s_Let_inv[consumes 2, case_names Let1 Let2, elim]: assumes "\ \, Let e\<^sub>1 x e\<^sub>2 \ m\ \ \', e' \" and "atom x \ (e\<^sub>1,\)" and "e' = e\<^sub>2[e\<^sub>1 / x] \ value e\<^sub>1 \ \ = \' \ Q" and "\e\<^sub>1'. \ \, e\<^sub>1 \ m\ \ \', e\<^sub>1' \ \ e' = Let e\<^sub>1' x e\<^sub>2 \ \ value e\<^sub>1 \ Q" shows "Q" using assms by (auto elim: s_Let_inv') inductive_cases s_Case_inv[consumes 1, case_names Case Inj1 Inj2, elim]: "\ \, Case e e\<^sub>1 e\<^sub>2 \ m\ \ \', e' \" inductive_cases s_Prj1_inv[consumes 1, case_names Prj1 PrjPair1, elim]: "\ \, Prj1 e \ m\ \ \', v \" inductive_cases s_Prj2_inv[consumes 1, case_names Prj2 PrjPair2, elim]: "\ \, Prj2 e \ m\ \ \', v \" inductive_cases s_Pair_inv[consumes 1, case_names Pair1 Pair2, elim]: "\ \, Pair e\<^sub>1 e\<^sub>2 \ m\ \ \', e' \" inductive_cases s_Inj1_inv[consumes 1, case_names Inj1, elim]: "\ \, Inj1 e \ m\ \ \', e' \" inductive_cases s_Inj2_inv[consumes 1, case_names Inj2, elim]: "\ \, Inj2 e \ m\ \ \', e' \" inductive_cases s_Roll_inv[consumes 1, case_names Roll, elim]: "\ \, Roll e \ m\ \ \', e' \" inductive_cases s_Unroll_inv[consumes 1, case_names Unroll UnrollRoll, elim]: "\ \, Unroll e \ m\ \ \', e' \" inductive_cases s_AuthI_inv[consumes 1, case_names Auth AuthI, elim]: "\ \, Auth e \ I\ \ \', e' \" inductive_cases s_UnauthI_inv[consumes 1, case_names Unauth UnauthI, elim]: "\ \, Unauth e \ I\ \ \', e' \" inductive_cases s_AuthP_inv[consumes 1, case_names Auth AuthP, elim]: "\ \, Auth e \ P\ \ \', e' \" inductive_cases s_UnauthP_inv[consumes 1, case_names Unauth UnauthP, elim]: "\ \, Unauth e \ P\ \ \', e' \" inductive_cases s_AuthV_inv[consumes 1, case_names Auth AuthV, elim]: "\ \, Auth e \ V\ \ \', e' \" inductive_cases s_UnauthV_inv[consumes 1, case_names Unauth UnauthV, elim]: "\ \, Unauth e \ V\ \ \', e' \" inductive_cases s_Id_inv[elim]: "\ \\<^sub>1, e\<^sub>1 \ m\0 \ \\<^sub>2, e\<^sub>2 \" inductive_cases s_Tr_inv[elim]: "\ \\<^sub>1, e\<^sub>1 \ m\i \ \\<^sub>3, e\<^sub>3 \" text \Freshness with smallstep.\ lemma fresh_smallstep_I: fixes x :: var assumes "\ \, e \ I\ \ \', e' \" "atom x \ e" shows "atom x \ e'" using assms by (induct \ e I \' e' rule: smallstep.induct) (auto simp: fresh_subst_term) lemma fresh_smallstep_P: fixes x :: var assumes "\ \, e \ P\ \ \', e' \" "atom x \ e" shows "atom x \ e'" using assms by (induct \ e P \' e' rule: smallstep.induct) (auto simp: fresh_subst_term) lemma fresh_smallsteps_I: fixes x :: var assumes "\ \, e \ I\i \ \', e' \" "atom x \ e" shows "atom x \ e'" using assms by (induct \ e I i \' e' rule: smallsteps.induct) (simp_all add: fresh_smallstep_I) lemma fresh_ps_smallstep_P: fixes x :: var assumes "\ \, e \ P\ \ \', e' \" "atom x \ e" "atom x \ \" shows "atom x \ \'" using assms proof (induct \ e P \' e' rule: smallstep.induct) case (s_UnauthP v \ h) then show ?case by (simp add: fresh_Cons fresh_append fresh_shallow) qed auto text \Proofstream lemmas.\ lemma smallstepI_ps_eq: assumes "\ \, e \ I\ \ \', e' \" shows "\ = \'" using assms by (induct \ e I \' e' rule: smallstep.induct) auto lemma smallstepI_ps_emptyD: "\\, e\ I\ \[], e'\ \ \[], e\ I\ \[], e'\" "\[], e\ I\ \\, e'\ \ \[], e\ I\ \[], e'\" using smallstepI_ps_eq by force+ lemma smallstepsI_ps_eq: assumes "\\, e\ I\i \\', e'\" shows "\ = \'" using assms by (induct \ e I i \' e' rule: smallsteps.induct) (auto dest: smallstepI_ps_eq) lemma smallstepsI_ps_emptyD: "\\, e\ I\i \[], e'\ \ \[], e\ I\i \[], e'\" "\[], e\ I\i \\, e'\ \ \[], e\ I\i \[], e'\" using smallstepsI_ps_eq by force+ lemma smallstepV_consumes_proofstream: assumes "\ \\<^sub>1, eV \ V\ \ \\<^sub>2, eV' \" obtains \ where "\\<^sub>1 = \ @ \\<^sub>2" using assms by (induct \\<^sub>1 eV V \\<^sub>2 eV' rule: smallstep.induct) auto lemma smallstepsV_consumes_proofstream: assumes "\ \\<^sub>1, eV \ V\i \ \\<^sub>2, eV' \" obtains \ where "\\<^sub>1 = \ @ \\<^sub>2" using assms by (induct \\<^sub>1 eV V i \\<^sub>2 eV' rule: smallsteps.induct) (auto elim: smallstepV_consumes_proofstream) lemma smallstepP_generates_proofstream: assumes "\ \\<^sub>1, eP \ P\ \ \\<^sub>2, eP' \" obtains \ where "\\<^sub>2 = \\<^sub>1 @ \" using assms by (induct \\<^sub>1 eP P \\<^sub>2 eP' rule: smallstep.induct) auto lemma smallstepsP_generates_proofstream: assumes "\ \\<^sub>1, eP \ P\i \ \\<^sub>2, eP' \" obtains \ where "\\<^sub>2 = \\<^sub>1 @ \" using assms by (induct \\<^sub>1 eP P i \\<^sub>2 eP' rule: smallsteps.induct) (auto elim: smallstepP_generates_proofstream) lemma smallstepV_ps_append: "\ \, eV \ V\ \ \', eV' \ \ \ \ @ X, eV \ V\ \ \' @ X, eV' \" (is "?L \ ?R") proof (rule iffI) assume ?L then show ?R by (nominal_induct \ eV V \' eV' avoiding: X rule: smallstep.strong_induct) (auto simp: fresh_append fresh_Pair) next assume ?R then show ?L by (nominal_induct "\ @ X" eV V "\' @ X" eV' avoiding: X rule: smallstep.strong_induct) (auto simp: fresh_append fresh_Pair) qed lemma smallstepV_ps_to_suffix: assumes "\\, e\ V\ \\' @ X, e'\" obtains \'' where "\ = \'' @ X" using assms by (induct \ e V "\' @ X" e' rule: smallstep.induct) auto lemma smallstepsV_ps_append: "\ \, eV \ V\i \ \', eV' \ \ \ \ @ X, eV \ V\i \ \' @ X, eV' \" (is "?L \ ?R") proof (rule iffI) assume ?L then show ?R proof (induct \ eV V i \' eV' rule: smallsteps.induct) case (s_Tr \\<^sub>1 e\<^sub>1 i \\<^sub>2 e\<^sub>2 \\<^sub>3 e\<^sub>3) then show ?case by (auto simp: iffD1[OF smallstepV_ps_append]) qed simp next assume ?R then show ?L proof (induct "\ @ X" eV V i "\' @ X" eV' arbitrary: \' rule: smallsteps.induct) case (s_Tr e\<^sub>1 i \\<^sub>2 e\<^sub>2 e\<^sub>3) from s_Tr(3) obtain \''' where "\\<^sub>2 = \''' @ X" by (auto elim: smallstepV_ps_to_suffix) with s_Tr show ?case by (auto dest: iffD2[OF smallstepV_ps_append]) qed simp qed lemma smallstepP_ps_prepend: "\ \, eP \ P\ \ \', eP' \ \ \ X @ \, eP \ P\ \ X @ \', eP' \" (is "?L \ ?R") proof (rule iffI) assume ?L then show ?R proof (nominal_induct \ eP P \' eP' avoiding: X rule: smallstep.strong_induct) case (s_UnauthP v \ h) then show ?case by (subst append_assoc[symmetric, of X \ "[\v\]"]) (erule smallstep.s_UnauthP) qed (auto simp: fresh_append fresh_Pair) next assume ?R then show ?L by (nominal_induct "X @ \" eP P "X @ \'" eP' avoiding: X rule: smallstep.strong_induct) (auto simp: fresh_append fresh_Pair) qed lemma smallstepsP_ps_prepend: "\ \, eP \ P\i \ \', eP' \ \ \ X @ \, eP \ P\i \ X @ \', eP' \" (is "?L \ ?R") proof (rule iffI) assume ?L then show ?R proof (induct \ eP P i \' eP' rule: smallsteps.induct) case (s_Tr \\<^sub>1 e\<^sub>1 i \\<^sub>2 e\<^sub>2 \\<^sub>3 e\<^sub>3) then show ?case by (auto simp: iffD1[OF smallstepP_ps_prepend]) qed simp next assume ?R then show ?L proof (induct "X @ \" eP P i "X @ \'" eP' arbitrary: \' rule: smallsteps.induct) case (s_Tr e\<^sub>1 i \\<^sub>2 e\<^sub>2 e\<^sub>3) then obtain \'' where \'': "\\<^sub>2 = X @ \ @ \''" by (auto elim: smallstepsP_generates_proofstream) then have "\\, e\<^sub>1\ P\i \\ @ \'', e\<^sub>2\" by (auto dest: s_Tr(2)) with \'' s_Tr(1,3) show ?case by (auto dest: iffD2[OF smallstepP_ps_prepend]) qed simp qed subsection \Type Progress\ lemma type_progress: assumes "{$$} \\<^sub>W e : \" shows "value e \ (\e'. \ [], e \ I\ \ [], e' \)" using assms proof (nominal_induct "{$$} :: tyenv" e \ rule: judge_weak.strong_induct) case (jw_Let x e\<^sub>1 \\<^sub>1 e\<^sub>2 \\<^sub>2) then show ?case by (auto 0 3 simp: fresh_smallstep_I elim!: s_Let2[of e\<^sub>2] intro: exI[where P="\e. \_, _\ _\ \_, e\", OF s_Let1, rotated]) next case (jw_Prj1 v \\<^sub>1 \\<^sub>2) then show ?case by (auto elim!: jw_Prod_inv[of v \\<^sub>1 \\<^sub>2]) next case (jw_Prj2 v \\<^sub>1 \\<^sub>2) then show ?case by (auto elim!: jw_Prod_inv[of v \\<^sub>1 \\<^sub>2]) next case (jw_App e \\<^sub>1 \\<^sub>2 e') then show ?case by (auto 0 4 elim: jw_Fun_inv[of _ _ _ e']) next case (jw_Case v v\<^sub>1 v\<^sub>2 \\<^sub>1 \\<^sub>2 \) then show ?case by (auto 0 4 elim: jw_Sum_inv[of _ v\<^sub>1 v\<^sub>2]) qed fast+ subsection \Weak Type Preservation\ lemma fresh_tyenv_None: fixes \ :: tyenv shows "atom x \ \ \ \ $$ x = None" (is "?L \ ?R") proof assume assm: ?L show ?R proof (rule ccontr) assume "\ $$ x \ None" then obtain \ where "\ $$ x = Some \" by blast with assm have "\a :: var. atom a \ \ \ \ $$ a = Some \" using fmap_freshness_lemma_unique[OF exI, of x \] by (simp add: fresh_Pair fresh_Some) metis then have "{a :: var. atom a \ \} \ fmdom' \" by (auto simp: image_iff Ball_def fmlookup_dom'_iff) moreover { assume "infinite {a :: var. \ atom a \ \}" then have "infinite {a :: var. atom a \ supp \}" unfolding fresh_def by auto then have "infinite (supp \)" by (rule contrapos_nn) (auto simp: image_iff inv_f_f[of atom] inj_on_def elim!: finite_surj[of _ _ "inv atom"] bexI[rotated]) then have False using finite_supp[of \] by blast } then have "infinite {a :: var. atom a \ \}" by auto ultimately show False using finite_subset[of "{a. atom a \ \}" "fmdom' \"] unfolding fmdom'_alt_def by auto qed next assume ?R then show ?L proof (induct \ arbitrary: x) case (fmupd y z \) then show ?case by (cases "y = x") (auto intro: fresh_fmap_update) qed simp qed lemma judge_weak_fresh_env_fresh_term[dest]: fixes a :: var assumes "\ \\<^sub>W e : \" "atom a \ \" shows "atom a \ e" using assms proof (nominal_induct \ e \ avoiding: a rule: judge_weak.strong_induct) case (jw_Var \ x \) then show ?case by (cases "a = x") (auto simp: fresh_tyenv_None) qed (simp_all add: fresh_Cons fresh_fmap_update) lemma judge_weak_weakening_1: assumes "\ \\<^sub>W e : \" "atom y \ e" shows "\(y $$:= \') \\<^sub>W e : \" using assms proof (nominal_induct \ e \ avoiding: y \' rule: judge_weak.strong_induct) case (jw_Lam x \ \\<^sub>1 e \\<^sub>2) from jw_Lam(5)[of y \'] jw_Lam(1-4,6) show ?case - by (auto simp add: fresh_at_base fmap_reorder_neq_updates fresh_fmap_update) + by (auto simp add: fresh_at_base fmupd_reorder_neq fresh_fmap_update) next case (jw_App v v' \ \\<^sub>1 \\<^sub>2) then show ?case - by (force simp add: fresh_at_base fmap_reorder_neq_updates fresh_fmap_update) + by (force simp add: fresh_at_base fmupd_reorder_neq fresh_fmap_update) next case (jw_Let x \ e\<^sub>1 \\<^sub>1 e\<^sub>2 \\<^sub>2) from jw_Let(6)[of y \'] jw_Let(8)[of y \'] jw_Let(1-5,7,9) show ?case - by (auto simp add: fresh_at_base fmap_reorder_neq_updates fresh_fmap_update) + by (auto simp add: fresh_at_base fmupd_reorder_neq fresh_fmap_update) next case (jw_Rec x \ z \\<^sub>1 \\<^sub>2 e') from jw_Rec(9)[of y \'] jw_Rec(1-8,10) show ?case - by (auto simp add: fresh_at_base fmap_reorder_neq_updates fresh_fmap_update fresh_Pair) + by (auto simp add: fresh_at_base fmupd_reorder_neq fresh_fmap_update fresh_Pair) next case (jw_Case v v\<^sub>1 v\<^sub>2 \ \\<^sub>1 \\<^sub>2 \) then show ?case - by (fastforce simp add: fresh_at_base fmap_reorder_neq_updates fresh_fmap_update) + by (fastforce simp add: fresh_at_base fmupd_reorder_neq fresh_fmap_update) next case (jw_Roll \ \ v \) then show ?case by (simp add: fresh_fmap_update) next case (jw_Unroll \ \ v \) then show ?case by (simp add: fresh_fmap_update) qed auto lemma judge_weak_weakening_2: assumes "\ \\<^sub>W e : \" "atom y \ \" shows "\(y $$:= \') \\<^sub>W e : \" proof - from assms have "atom y \ e" by (rule judge_weak_fresh_env_fresh_term) with assms show "\(y $$:= \') \\<^sub>W e : \" by (simp add: judge_weak_weakening_1) qed lemma judge_weak_weakening_env: assumes "{$$} \\<^sub>W e : \" shows "\ \\<^sub>W e : \" using assms proof (induct \) case fmempty then show ?case by assumption next case (fmupd x y \) then show ?case by (simp add: fresh_tyenv_None judge_weak_weakening_2) qed lemma value_subst_value: assumes "value e" "value e'" shows "value (e[e' / x])" using assms by (induct e e' x rule: subst_term.induct) auto lemma judge_weak_subst[intro]: assumes "\(a $$:= \') \\<^sub>W e : \" "{$$} \\<^sub>W e' : \'" shows "\ \\<^sub>W e[e' / a] : \" using assms proof (nominal_induct "\(a $$:= \')" e \ avoiding: a e' \ rule: judge_weak.strong_induct) case (jw_Var x \) then show ?case by (auto simp: judge_weak_weakening_env) next case (jw_Lam x \\<^sub>1 e \\<^sub>2) then show ?case - by (fastforce simp: fmap_reorder_neq_updates) + by (fastforce simp: fmupd_reorder_neq) next case (jw_Rec x y \\<^sub>1 \\<^sub>2 e) then show ?case - by (fastforce simp: fmap_reorder_neq_updates) + by (fastforce simp: fmupd_reorder_neq) next case (jw_Let x e\<^sub>1 \\<^sub>1 e\<^sub>2 \\<^sub>2) then show ?case - by (fastforce simp: fmap_reorder_neq_updates) + by (fastforce simp: fmupd_reorder_neq) qed fastforce+ lemma type_preservation: assumes "\ [], e \ I\ \ [], e' \" "{$$} \\<^sub>W e : \" shows "{$$} \\<^sub>W e' : \" using assms [[simproc del: alpha_lst]] proof (nominal_induct "[]::proofstream" e I "[]::proofstream" e' arbitrary: \ rule: smallstep.strong_induct) case (s_AppLam v x e) then show ?case by force next case (s_AppRec v x e) then show ?case by (elim jw_App_inv jw_Rec_inv) (auto 0 3 simp del: subst_term.simps) next case (s_Let1 x e\<^sub>1 e\<^sub>1' e\<^sub>2) from s_Let1(1,2,7) show ?case by (auto intro: s_Let1(6) del: jw_Let_inv elim!: jw_Let_inv) next case (s_Unroll e e') then obtain \::tvar where "atom \ \ \" using obtain_fresh by blast with s_Unroll show ?case by (auto elim: jw_Unroll_inv[where \ = \]) next case (s_Roll e e') then obtain \::tvar where "atom \ \ \" using obtain_fresh by blast with s_Roll show ?case by (auto elim: jw_Roll_inv[where \ = \]) next case (s_UnrollRoll v) then obtain \::tvar where "atom \ \ \" using obtain_fresh by blast with s_UnrollRoll show ?case by (fastforce simp: Abs1_eq(3) elim: jw_Roll_inv[where \ = \] jw_Unroll_inv[where \ = \]) qed fastforce+ subsection \Corrected Lemma 1 from Miller et al.~\cite{adsg}: Weak Type Soundness\ lemma type_soundness: assumes "{$$} \\<^sub>W e : \" shows "value e \ (\e'. \ [], e \ I\ \ [], e' \ \ {$$} \\<^sub>W e' : \)" proof (cases "value e") case True then show ?thesis by simp next case False with assms obtain e' where "\[], e\ I\ \[], e'\" by (auto dest: type_progress) with assms show ?thesis by (auto simp: type_preservation) qed (*<*) end (*>*)