Theory Friend_State_Indistinguishability
theory Friend_State_Indistinguishability
imports "Friend_Observation_Setup"
begin
subsection ‹Unwinding helper definitions and lemmas›
locale Friend = FriendObservationSetup +
fixes
UID1 :: userID
and
UID2 :: userID
assumes
UID1_UID2_UIDs: "{UID1,UID2} ∩ UIDs = {}"
and
UID1_UID2: "UID1 ≠ UID2"
begin
fun eqButUIDl :: "userID ⇒ userID list ⇒ userID list ⇒ bool" where
"eqButUIDl uid uidl uidl1 = (remove1 uid uidl = remove1 uid uidl1)"
lemma eqButUIDl_eq[simp,intro!]: "eqButUIDl uid uidl uidl"
by auto
lemma eqButUIDl_sym:
assumes "eqButUIDl uid uidl uidl1"
shows "eqButUIDl uid uidl1 uidl"
using assms by auto
lemma eqButUIDl_trans:
assumes "eqButUIDl uid uidl uidl1" and "eqButUIDl uid uidl1 uidl2"
shows "eqButUIDl uid uidl uidl2"
using assms by auto
lemma eqButUIDl_remove1_cong:
assumes "eqButUIDl uid uidl uidl1"
shows "eqButUIDl uid (remove1 uid' uidl) (remove1 uid' uidl1)"
proof -
have "remove1 uid (remove1 uid' uidl) = remove1 uid' (remove1 uid uidl)" by (simp add: remove1_commute)
also have "… = remove1 uid' (remove1 uid uidl1)" using assms by simp
also have "… = remove1 uid (remove1 uid' uidl1)" by (simp add: remove1_commute)
finally show ?thesis by simp
qed
lemma eqButUIDl_snoc_cong:
assumes "eqButUIDl uid uidl uidl1"
and "uid' ∈∈ uidl ⟷ uid' ∈∈ uidl1"
shows "eqButUIDl uid (uidl ## uid') (uidl1 ## uid')"
using assms by (auto simp add: remove1_append remove1_idem)
definition eqButUIDf where
"eqButUIDf frds frds1 ≡
eqButUIDl UID2 (frds UID1) (frds1 UID1)
∧ eqButUIDl UID1 (frds UID2) (frds1 UID2)
∧ (∀uid. uid ≠ UID1 ∧ uid ≠ UID2 ⟶ frds uid = frds1 uid)"
lemmas eqButUIDf_intro = eqButUIDf_def[THEN meta_eq_to_obj_eq, THEN iffD2]
lemma eqButUIDf_eeq[simp,intro!]: "eqButUIDf frds frds"
unfolding eqButUIDf_def by auto
lemma eqButUIDf_sym:
assumes "eqButUIDf frds frds1" shows "eqButUIDf frds1 frds"
using assms eqButUIDl_sym unfolding eqButUIDf_def
by presburger
lemma eqButUIDf_trans:
assumes "eqButUIDf frds frds1" and "eqButUIDf frds1 frds2"
shows "eqButUIDf frds frds2"
using assms eqButUIDl_trans unfolding eqButUIDf_def by (auto split: if_splits)
lemma eqButUIDf_cong:
assumes "eqButUIDf frds frds1"
and "uid = UID1 ⟹ eqButUIDl UID2 uu uu1"
and "uid = UID2 ⟹ eqButUIDl UID1 uu uu1"
and "uid ≠ UID1 ⟹ uid ≠ UID2 ⟹ uu = uu1"
shows "eqButUIDf (frds (uid := uu)) (frds1(uid := uu1))"
using assms unfolding eqButUIDf_def by (auto split: if_splits)
lemma eqButUIDf_eqButUIDl:
assumes "eqButUIDf frds frds1"
shows "eqButUIDl UID2 (frds UID1) (frds1 UID1)"
and "eqButUIDl UID1 (frds UID2) (frds1 UID2)"
using assms unfolding eqButUIDf_def by (auto split: if_splits)
lemma eqButUIDf_not_UID:
"⟦eqButUIDf frds frds1; uid ≠ UID1; uid ≠ UID2⟧ ⟹ frds uid = frds1 uid"
unfolding eqButUIDf_def by (auto split: if_splits)
lemma eqButUIDf_not_UID':
assumes eq1: "eqButUIDf frds frds1"
and uid: "(uid,uid') ∉ {(UID1,UID2), (UID2,UID1)}"
shows "uid ∈∈ frds uid' ⟷ uid ∈∈ frds1 uid'"
proof -
from uid have "(uid' = UID1 ∧ uid ≠ UID2)
∨ (uid' = UID2 ∧ uid ≠ UID1)
∨ (uid' ∉ {UID1,UID2})" (is "?u1 ∨ ?u2 ∨ ?n12")
by auto
then show ?thesis proof (elim disjE)
assume "?u1"
moreover then have "uid ∈∈ remove1 UID2 (frds uid') ⟷ uid ∈∈ remove1 UID2 (frds1 uid')"
using eq1 unfolding eqButUIDf_def by auto
ultimately show ?thesis by auto
next
assume "?u2"
moreover then have "uid ∈∈ remove1 UID1 (frds uid') ⟷ uid ∈∈ remove1 UID1 (frds1 uid')"
using eq1 unfolding eqButUIDf_def by auto
ultimately show ?thesis by auto
next
assume "?n12"
then show ?thesis using eq1 unfolding eqButUIDf_def by auto
qed
qed
definition eqButUID12 where
"eqButUID12 freq freq1 ≡
∀ uid uid'. if (uid,uid') ∈ {(UID1,UID2), (UID2,UID1)} then True else freq uid uid' = freq1 uid uid'"
lemmas eqButUID12_intro = eqButUID12_def[THEN meta_eq_to_obj_eq, THEN iffD2]
lemma eqButUID12_eeq[simp,intro!]: "eqButUID12 freq freq"
unfolding eqButUID12_def by auto
lemma eqButUID12_sym:
assumes "eqButUID12 freq freq1" shows "eqButUID12 freq1 freq"
using assms unfolding eqButUID12_def
by presburger
lemma eqButUID12_trans:
assumes "eqButUID12 freq freq1" and "eqButUID12 freq1 freq2"
shows "eqButUID12 freq freq2"
using assms unfolding eqButUID12_def by (auto split: if_splits)
lemma eqButUID12_cong:
assumes "eqButUID12 freq freq1"
and "¬ (uid,uid') ∈ {(UID1,UID2), (UID2,UID1)} ⟹ uu = uu1"
shows "eqButUID12 (fun_upd2 freq uid uid' uu) (fun_upd2 freq1 uid uid' uu1)"
using assms unfolding eqButUID12_def fun_upd2_def by (auto split: if_splits)
lemma eqButUID12_not_UID:
"⟦eqButUID12 freq freq1; ¬ (uid,uid') ∈ {(UID1,UID2), (UID2,UID1)}⟧ ⟹ freq uid uid' = freq1 uid uid'"
unfolding eqButUID12_def by (auto split: if_splits)
definition eqButUID :: "state ⇒ state ⇒ bool" where
"eqButUID s s1 ≡
admin s = admin s1 ∧
pendingUReqs s = pendingUReqs s1 ∧ userReq s = userReq s1 ∧
userIDs s = userIDs s1 ∧ user s = user s1 ∧ pass s = pass s1 ∧
eqButUIDf (pendingFReqs s) (pendingFReqs s1) ∧
eqButUID12 (friendReq s) (friendReq s1) ∧
eqButUIDf (friendIDs s) (friendIDs s1) ∧
postIDs s = postIDs s1 ∧ admin s = admin s1 ∧
post s = post s1 ∧ vis s = vis s1 ∧
owner s = owner s1 ∧
pendingSApiReqs s = pendingSApiReqs s1 ∧ sApiReq s = sApiReq s1 ∧
serverApiIDs s = serverApiIDs s1 ∧ serverPass s = serverPass s1 ∧
outerPostIDs s = outerPostIDs s1 ∧ outerPost s = outerPost s1 ∧ outerVis s = outerVis s1 ∧
outerOwner s = outerOwner s1 ∧
sentOuterFriendIDs s = sentOuterFriendIDs s1 ∧
recvOuterFriendIDs s = recvOuterFriendIDs s1 ∧
pendingCApiReqs s = pendingCApiReqs s1 ∧ cApiReq s = cApiReq s1 ∧
clientApiIDs s = clientApiIDs s1 ∧ clientPass s = clientPass s1 ∧
sharedWith s = sharedWith s1"
lemmas eqButUID_intro = eqButUID_def[THEN meta_eq_to_obj_eq, THEN iffD2]
lemma eqButUID_refl[simp,intro!]: "eqButUID s s"
unfolding eqButUID_def by auto
lemma eqButUID_sym[sym]:
assumes "eqButUID s s1" shows "eqButUID s1 s"
using assms eqButUIDf_sym eqButUID12_sym unfolding eqButUID_def by auto
lemma eqButUID_trans[trans]:
assumes "eqButUID s s1" and "eqButUID s1 s2" shows "eqButUID s s2"
using assms eqButUIDf_trans eqButUID12_trans unfolding eqButUID_def by metis
lemma eqButUID_stateSelectors:
assumes "eqButUID s s1"
shows "admin s = admin s1"
"pendingUReqs s = pendingUReqs s1" "userReq s = userReq s1"
"userIDs s = userIDs s1" "user s = user s1" "pass s = pass s1"
"eqButUIDf (pendingFReqs s) (pendingFReqs s1)"
"eqButUID12 (friendReq s) (friendReq s1)"
"eqButUIDf (friendIDs s) (friendIDs s1)"
"postIDs s = postIDs s1"
"post s = post s1" "vis s = vis s1"
"owner s = owner s1"
"pendingSApiReqs s = pendingSApiReqs s1" "sApiReq s = sApiReq s1"
"serverApiIDs s = serverApiIDs s1" "serverPass s = serverPass s1"
"outerPostIDs s = outerPostIDs s1" "outerPost s = outerPost s1" "outerVis s = outerVis s1"
"outerOwner s = outerOwner s1"
"sentOuterFriendIDs s = sentOuterFriendIDs s1"
"recvOuterFriendIDs s = recvOuterFriendIDs s1"
"pendingCApiReqs s = pendingCApiReqs s1" "cApiReq s = cApiReq s1"
"clientApiIDs s = clientApiIDs s1" "clientPass s = clientPass s1"
"sharedWith s = sharedWith s1"
"IDsOK s = IDsOK s1"
using assms unfolding eqButUID_def IDsOK_def[abs_def] by auto
lemma eqButUID_eqButUID2:
"eqButUID s s1 ⟹ eqButUIDl UID2 (friendIDs s UID1) (friendIDs s1 UID1)"
unfolding eqButUID_def using eqButUIDf_eqButUIDl
by (smt eqButUIDf_eqButUIDl eqButUIDl.simps)
lemma eqButUID_not_UID:
"eqButUID s s1 ⟹ uid ≠ UID ⟹ post s uid = post s1 uid"
unfolding eqButUID_def by auto
lemma eqButUID_cong[simp, intro]:
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇admin := uu1⦈) (s1 ⦇admin := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇pendingUReqs := uu1⦈) (s1 ⦇pendingUReqs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇userReq := uu1⦈) (s1 ⦇userReq := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇userIDs := uu1⦈) (s1 ⦇userIDs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇user := uu1⦈) (s1 ⦇user := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇pass := uu1⦈) (s1 ⦇pass := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇postIDs := uu1⦈) (s1 ⦇postIDs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇owner := uu1⦈) (s1 ⦇owner := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇post := uu1⦈) (s1 ⦇post := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇vis := uu1⦈) (s1 ⦇vis := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ eqButUIDf uu1 uu2 ⟹ eqButUID (s ⦇pendingFReqs := uu1⦈) (s1 ⦇pendingFReqs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ eqButUID12 uu1 uu2 ⟹ eqButUID (s ⦇friendReq := uu1⦈) (s1 ⦇friendReq := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ eqButUIDf uu1 uu2 ⟹ eqButUID (s ⦇friendIDs := uu1⦈) (s1 ⦇friendIDs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇pendingSApiReqs := uu1⦈) (s1 ⦇pendingSApiReqs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇sApiReq := uu1⦈) (s1 ⦇sApiReq := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇serverApiIDs := uu1⦈) (s1 ⦇serverApiIDs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇serverPass := uu1⦈) (s1 ⦇serverPass := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇outerPostIDs := uu1⦈) (s1 ⦇outerPostIDs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇outerPost := uu1⦈) (s1 ⦇outerPost := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇outerVis := uu1⦈) (s1 ⦇outerVis := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇outerOwner := uu1⦈) (s1 ⦇outerOwner := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇sentOuterFriendIDs := uu1⦈) (s1 ⦇sentOuterFriendIDs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇recvOuterFriendIDs := uu1⦈) (s1 ⦇recvOuterFriendIDs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇pendingCApiReqs := uu1⦈) (s1 ⦇pendingCApiReqs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇cApiReq := uu1⦈) (s1 ⦇cApiReq := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇clientApiIDs := uu1⦈) (s1 ⦇clientApiIDs := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇clientPass := uu1⦈) (s1 ⦇clientPass := uu2⦈)"
"⋀ uu1 uu2. eqButUID s s1 ⟹ uu1 = uu2 ⟹ eqButUID (s ⦇sharedWith := uu1⦈) (s1 ⦇sharedWith:= uu2⦈)"
unfolding eqButUID_def by auto
definition "friends12" :: "state ⇒ bool"
where "friends12 s ≡ UID1 ∈∈ friendIDs s UID2 ∧ UID2 ∈∈ friendIDs s UID1"
lemma step_friendIDs:
assumes "step s a = (ou, s')"
and "a ≠ Cact (cFriend uid (pass s uid) uid') ∧ a ≠ Cact (cFriend uid' (pass s uid') uid) ∧
a ≠ Dact (dFriend uid (pass s uid) uid') ∧ a ≠ Dact (dFriend uid' (pass s uid') uid)"
shows "uid ∈∈ friendIDs s' uid' ⟷ uid ∈∈ friendIDs s uid'" (is ?uid)
and "uid' ∈∈ friendIDs s' uid ⟷ uid' ∈∈ friendIDs s uid" (is ?uid')
proof -
from assms have "?uid ∧ ?uid'"
proof (cases a)
case (Sact sa) then show ?thesis using assms by (cases sa) (auto simp: s_defs) next
case (Uact ua) then show ?thesis using assms by (cases ua) (auto simp: u_defs) next
case (COMact ca) then show ?thesis using assms by (cases ca) (auto simp: com_defs) next
case (Cact ca) then show ?thesis using assms by (cases ca) (auto simp: c_defs) next
case (Dact da) then show ?thesis using assms by (cases da) (auto simp: d_defs)
qed auto
then show ?uid and ?uid' by auto
qed
lemma step_friends12:
assumes "step s a = (ou, s')"
and "a ≠ Cact (cFriend UID1 (pass s UID1) UID2) ∧ a ≠ Cact (cFriend UID2 (pass s UID2) UID1) ∧
a ≠ Dact (dFriend UID1 (pass s UID1) UID2) ∧ a ≠ Dact (dFriend UID2 (pass s UID2) UID1)"
shows "friends12 s' ⟷ friends12 s"
using step_friendIDs[OF assms] unfolding friends12_def by auto
lemma step_pendingFReqs:
assumes step: "step s a = (ou, s')"
and "∀req. a ≠ Cact (cFriend uid (pass s uid) uid') ∧ a ≠ Cact (cFriend uid' (pass s uid') uid) ∧
a ≠ Dact (dFriend uid (pass s uid) uid') ∧ a ≠ Dact (dFriend uid' (pass s uid') uid) ∧
a ≠ Cact (cFriendReq uid (pass s uid) uid' req) ∧
a ≠ Cact (cFriendReq uid' (pass s uid') uid req)"
shows "uid ∈∈ pendingFReqs s' uid' ⟷ uid ∈∈ pendingFReqs s uid'" (is ?uid)
and "uid' ∈∈ pendingFReqs s' uid ⟷ uid' ∈∈ pendingFReqs s uid" (is ?uid')
proof -
from assms have "?uid ∧ ?uid'"
proof (cases a)
case (Sact sa) then show ?thesis using assms by (cases sa) (auto simp: s_defs) next
case (Uact ua) then show ?thesis using assms by (cases ua) (auto simp: u_defs) next
case (COMact ca) then show ?thesis using assms by (cases ca) (auto simp: com_defs) next
case (Cact ca) then show ?thesis using assms proof (cases ca)
case (cFriend uid1 p uid1')
then have "((uid1 = uid ⟶ uid1' ≠ uid') ∧ (uid1 = uid' ⟶ uid1' ≠ uid)) ∨ ou = outErr"
using Cact assms by (auto simp: c_defs)
then show ?thesis using step Cact cFriend by (auto simp: c_defs)
qed (auto simp: c_defs) next
case (Dact da) then show ?thesis using assms by (cases da) (auto simp: d_defs)
qed auto
then show ?uid and ?uid' by auto
qed
lemma eqButUID_friends12_set_friendIDs_eq:
assumes ss1: "eqButUID s s1"
and f12: "friends12 s = friends12 s1"
and rs: "reach s" and rs1: "reach s1"
shows "set (friendIDs s uid) = set (friendIDs s1 uid)"
proof -
have dfIDs: "distinct (friendIDs s uid)" "distinct (friendIDs s1 uid)"
using reach_distinct_friends_reqs[OF rs] reach_distinct_friends_reqs[OF rs1] by auto
from f12 have uid12: "UID1 ∈∈ friendIDs s UID2 ⟷ UID1 ∈∈ friendIDs s1 UID2"
"UID2 ∈∈ friendIDs s UID1 ⟷ UID2 ∈∈ friendIDs s1 UID1"
using reach_friendIDs_symmetric[OF rs] reach_friendIDs_symmetric[OF rs1]
unfolding friends12_def by auto
from ss1 have fIDs: "eqButUIDf (friendIDs s) (friendIDs s1)" unfolding eqButUID_def by simp
show "set (friendIDs s uid) = set (friendIDs s1 uid)"
proof (intro equalityI subsetI)
fix uid'
assume "uid' ∈∈ friendIDs s uid"
then show "uid' ∈∈ friendIDs s1 uid"
using fIDs dfIDs uid12 eqButUIDf_not_UID' unfolding eqButUIDf_def
by (metis (no_types, lifting) insert_iff prod.inject singletonD)
next
fix uid'
assume "uid' ∈∈ friendIDs s1 uid"
then show "uid' ∈∈ friendIDs s uid"
using fIDs dfIDs uid12 eqButUIDf_not_UID' unfolding eqButUIDf_def
by (metis (no_types, lifting) insert_iff prod.inject singletonD)
qed
qed
lemma distinct_remove1_idem: "distinct xs ⟹ remove1 y (remove1 y xs) = remove1 y xs"
by (induction xs) (auto simp add: remove1_idem)
lemma Cact_cFriend_step_eqButUID:
assumes step: "step s (Cact (cFriend uid p uid')) = (ou,s')"
and s: "reach s"
and uids: "(uid = UID1 ∧ uid' = UID2) ∨ (uid = UID2 ∧ uid' = UID1)" (is "?u12 ∨ ?u21")
shows "eqButUID s s'"
using assms proof (cases)
assume ou: "ou = outOK"
then have "uid' ∈∈ pendingFReqs s uid" using step by (auto simp add: c_defs)
then have fIDs: "uid' ∉ set (friendIDs s uid)" "uid ∉ set (friendIDs s uid')"
and fRs: "distinct (pendingFReqs s uid)" "distinct (pendingFReqs s uid')"
using reach_distinct_friends_reqs[OF s] by auto
have "eqButUIDf (friendIDs s) (friendIDs (createFriend s uid p uid'))"
using fIDs uids UID1_UID2 unfolding eqButUIDf_def
by (cases "?u12") (auto simp add: c_defs remove1_idem remove1_append)
moreover have "eqButUIDf (pendingFReqs s) (pendingFReqs (createFriend s uid p uid'))"
using fRs uids UID1_UID2 unfolding eqButUIDf_def
by (cases "?u12") (auto simp add: c_defs distinct_remove1_idem)
moreover have "eqButUID12 (friendReq s) (friendReq (createFriend s uid p uid'))"
using uids unfolding eqButUID12_def
by (auto simp add: c_defs fun_upd2_eq_but_a_b)
ultimately show "eqButUID s s'" using step ou unfolding eqButUID_def by (auto simp add: c_defs)
qed (auto)
lemma Cact_cFriendReq_step_eqButUID:
assumes step: "step s (Cact (cFriendReq uid p uid' req)) = (ou,s')"
and uids: "(uid = UID1 ∧ uid' = UID2) ∨ (uid = UID2 ∧ uid' = UID1)" (is "?u12 ∨ ?u21")
shows "eqButUID s s'"
using assms proof (cases)
assume ou: "ou = outOK"
then have "uid ∉ set (pendingFReqs s uid')" "uid ∉ set (friendIDs s uid')"
using step by (auto simp add: c_defs)
then have "eqButUIDf (pendingFReqs s) (pendingFReqs (createFriendReq s uid p uid' req))"
using uids UID1_UID2 unfolding eqButUIDf_def
by (cases "?u12") (auto simp add: c_defs remove1_idem remove1_append)
moreover have "eqButUID12 (friendReq s) (friendReq (createFriendReq s uid p uid' req))"
using uids unfolding eqButUID12_def
by (auto simp add: c_defs fun_upd2_eq_but_a_b)
ultimately show "eqButUID s s'" using step ou unfolding eqButUID_def by (auto simp add: c_defs)
qed (auto)
lemma Dact_dFriend_step_eqButUID:
assumes step: "step s (Dact (dFriend uid p uid')) = (ou,s')"
and s: "reach s"
and uids: "(uid = UID1 ∧ uid' = UID2) ∨ (uid = UID2 ∧ uid' = UID1)" (is "?u12 ∨ ?u21")
shows "eqButUID s s'"
using assms proof (cases)
assume ou: "ou = outOK"
then have "uid' ∈∈ friendIDs s uid" using step by (auto simp add: d_defs)
then have fRs: "distinct (friendIDs s uid)" "distinct (friendIDs s uid')"
using reach_distinct_friends_reqs[OF s] by auto
have "eqButUIDf (friendIDs s) (friendIDs (deleteFriend s uid p uid'))"
using fRs uids UID1_UID2 unfolding eqButUIDf_def
by (cases "?u12") (auto simp add: d_defs remove1_idem distinct_remove1_removeAll)
then show "eqButUID s s'" using step ou unfolding eqButUID_def by (auto simp add: d_defs)
qed (auto)
lemma eqButUID_step:
assumes ss1: "eqButUID s s1"
and step: "step s a = (ou,s')"
and step1: "step s1 a = (ou1,s1')"
and rs: "reach s"
and rs1: "reach s1"
shows "eqButUID s' s1'"
proof -
note simps = eqButUID_stateSelectors s_defs c_defs u_defs r_defs l_defs com_defs
from assms show ?thesis proof (cases a)
case (Sact sa) with assms show ?thesis by (cases sa) (auto simp add: simps)
next
case (Cact ca) note a = this
with assms show ?thesis proof (cases ca)
case (cFriendReq uid p uid' req) note ca = this
then show ?thesis
proof (cases "(uid = UID1 ∧ uid' = UID2) ∨ (uid = UID2 ∧ uid' = UID1)")
case True
then have "eqButUID s s'" and "eqButUID s1 s1'"
using step step1 unfolding a ca
by (auto intro: Cact_cFriendReq_step_eqButUID)
with ss1 show "eqButUID s' s1'" by (auto intro: eqButUID_sym eqButUID_trans)
next
case False
have fRs: "eqButUIDf (pendingFReqs s) (pendingFReqs s1)"
and fIDs: "eqButUIDf (friendIDs s) (friendIDs s1)" using ss1 by (auto simp: simps)
then have uid_uid': "uid ∈∈ pendingFReqs s uid' ⟷ uid ∈∈ pendingFReqs s1 uid'"
"uid ∈∈ friendIDs s uid' ⟷ uid ∈∈ friendIDs s1 uid'"
using False by (auto intro!: eqButUIDf_not_UID')
have "eqButUIDf ((pendingFReqs s)(uid' := pendingFReqs s uid' ## uid))
((pendingFReqs s1)(uid' := pendingFReqs s1 uid' ## uid))"
using fRs False
by (intro eqButUIDf_cong) (auto simp add: remove1_append remove1_idem eqButUIDf_def)
moreover have "eqButUID12 (fun_upd2 (friendReq s) uid uid' req)
(fun_upd2 (friendReq s1) uid uid' req)"
using ss1 by (intro eqButUID12_cong) (auto simp: simps)
moreover have "e_createFriendReq s uid p uid' req
⟷ e_createFriendReq s1 uid p uid' req"
using uid_uid' ss1 by (auto simp: simps)
ultimately show ?thesis using assms unfolding a ca by (auto simp: simps)
qed
next
case (cFriend uid p uid') note ca = this
then show ?thesis
proof (cases "(uid = UID1 ∧ uid' = UID2) ∨ (uid = UID2 ∧ uid' = UID1)")
case True
then have "eqButUID s s'" and "eqButUID s1 s1'"
using step step1 rs rs1 unfolding a ca
by (auto intro!: Cact_cFriend_step_eqButUID)+
with ss1 show "eqButUID s' s1'" by (auto intro: eqButUID_sym eqButUID_trans)
next
case False
have fRs: "eqButUIDf (pendingFReqs s) (pendingFReqs s1)"
(is "eqButUIDf (?pfr s) (?pfr s1)")
and fIDs: "eqButUIDf (friendIDs s) (friendIDs s1)" using ss1 by (auto simp: simps)
then have uid_uid': "uid ∈∈ pendingFReqs s uid' ⟷ uid ∈∈ pendingFReqs s1 uid'"
"uid' ∈∈ pendingFReqs s uid ⟷ uid' ∈∈ pendingFReqs s1 uid"
"uid ∈∈ friendIDs s uid' ⟷ uid ∈∈ friendIDs s1 uid'"
"uid' ∈∈ friendIDs s uid ⟷ uid' ∈∈ friendIDs s1 uid"
using False by (auto intro!: eqButUIDf_not_UID')
have "eqButUIDl UID1 (remove1 uid' (?pfr s UID2)) (remove1 uid' (?pfr s1 UID2))"
and "eqButUIDl UID2 (remove1 uid' (?pfr s UID1)) (remove1 uid' (?pfr s1 UID1))"
and "eqButUIDl UID1 (remove1 uid (?pfr s UID2)) (remove1 uid (?pfr s1 UID2))"
and "eqButUIDl UID2 (remove1 uid (?pfr s UID1)) (remove1 uid (?pfr s1 UID1))"
using fRs unfolding eqButUIDf_def
by (auto intro!: eqButUIDl_remove1_cong simp del: eqButUIDl.simps)
then have 1: "eqButUIDf ((?pfr s)(uid := remove1 uid' (?pfr s uid),
uid' := remove1 uid (?pfr s uid')))
((?pfr s1)(uid := remove1 uid' (?pfr s1 uid),
uid' := remove1 uid (?pfr s1 uid')))"
using fRs False
by (intro eqButUIDf_cong) (auto simp add: eqButUIDf_def)
have "uid = UID1 ⟹ eqButUIDl UID2 (friendIDs s UID1 ## uid') (friendIDs s1 UID1 ## uid')"
and "uid = UID2 ⟹ eqButUIDl UID1 (friendIDs s UID2 ## uid') (friendIDs s1 UID2 ## uid')"
and "uid' = UID1 ⟹ eqButUIDl UID2 (friendIDs s UID1 ## uid) (friendIDs s1 UID1 ## uid)"
and "uid' = UID2 ⟹ eqButUIDl UID1 (friendIDs s UID2 ## uid) (friendIDs s1 UID2 ## uid)"
using fIDs uid_uid' by - (intro eqButUIDl_snoc_cong; simp add: eqButUIDf_def)+
then have 2: "eqButUIDf ((friendIDs s)(uid := friendIDs s uid ## uid',
uid' := friendIDs s uid' ## uid))
((friendIDs s1)(uid := friendIDs s1 uid ## uid',
uid' := friendIDs s1 uid' ## uid))"
using fIDs by (intro eqButUIDf_cong) (auto simp add: eqButUIDf_def)
have 3: "eqButUID12 (fun_upd2 (fun_upd2 (friendReq s) uid' uid emptyRequestInfo)
uid uid' emptyRequestInfo)
(fun_upd2 (fun_upd2 (friendReq s1) uid' uid emptyRequestInfo)
uid uid' emptyRequestInfo)"
using ss1 by (intro eqButUID12_cong) (auto simp: simps)
have "e_createFriend s uid p uid'
⟷ e_createFriend s1 uid p uid'"
using uid_uid' ss1 by (auto simp: simps)
with 1 2 3 show ?thesis using assms unfolding a ca by (auto simp: simps)
qed
qed (auto simp: simps)
next
case (Uact ua) with assms show ?thesis by (cases ua) (auto simp add: simps)
next
case (Ract ra) with assms show ?thesis by (cases ra) (auto simp add: simps)
next
case (Lact la) with assms show ?thesis by (cases la) (auto simp add: simps)
next
case (COMact ca) with assms show ?thesis by (cases ca) (auto simp add: simps)
next
case (Dact da) note a = this
with assms show ?thesis proof (cases da)
case (dFriend uid p uid') note ca = this
then show ?thesis
proof (cases "(uid = UID1 ∧ uid' = UID2) ∨ (uid = UID2 ∧ uid' = UID1)")
case True
then have "eqButUID s s'" and "eqButUID s1 s1'"
using step step1 rs rs1 unfolding a ca
by (auto intro!: Dact_dFriend_step_eqButUID)+
with ss1 show "eqButUID s' s1'" by (auto intro: eqButUID_sym eqButUID_trans)
next
case False
have fIDs: "eqButUIDf (friendIDs s) (friendIDs s1)" using ss1 by (auto simp: simps)
then have uid_uid': "uid ∈∈ friendIDs s uid' ⟷ uid ∈∈ friendIDs s1 uid'"
"uid' ∈∈ friendIDs s uid ⟷ uid' ∈∈ friendIDs s1 uid"
using False by (auto intro!: eqButUIDf_not_UID')
have dfIDs: "distinct (friendIDs s uid)" "distinct (friendIDs s uid')"
"distinct (friendIDs s1 uid)" "distinct (friendIDs s1 uid')"
using reach_distinct_friends_reqs[OF rs] reach_distinct_friends_reqs[OF rs1] by auto
have "uid = UID1 ⟹ eqButUIDl UID2 (remove1 uid' (friendIDs s UID1)) (remove1 uid' (friendIDs s1 UID1))"
and "uid = UID2 ⟹ eqButUIDl UID1 (remove1 uid' (friendIDs s UID2)) (remove1 uid' (friendIDs s1 UID2))"
and "uid' = UID1 ⟹ eqButUIDl UID2 (remove1 uid (friendIDs s UID1)) (remove1 uid (friendIDs s1 UID1))"
and "uid' = UID2 ⟹ eqButUIDl UID1 (remove1 uid (friendIDs s UID2)) (remove1 uid (friendIDs s1 UID2))"
using fIDs uid_uid' by - (intro eqButUIDl_remove1_cong; simp add: eqButUIDf_def)+
then have 1: "eqButUIDf ((friendIDs s)(uid := remove1 uid' (friendIDs s uid),
uid' := remove1 uid (friendIDs s uid')))
((friendIDs s1)(uid := remove1 uid' (friendIDs s1 uid),
uid' := remove1 uid (friendIDs s1 uid')))"
using fIDs by (intro eqButUIDf_cong) (auto simp add: eqButUIDf_def)
have "e_deleteFriend s uid p uid'
⟷ e_deleteFriend s1 uid p uid'"
using uid_uid' ss1 by (auto simp: simps d_defs)
with 1 show ?thesis using assms dfIDs unfolding a ca
by (auto simp: simps d_defs distinct_remove1_removeAll)
qed
qed
qed
qed
lemma eqButUID_step_friendIDs_eq:
assumes ss1: "eqButUID s s1"
and rs: "reach s" and rs1: "reach s1"
and step: "step s a = (ou,s')" and step1: "step s1 a = (ou1,s1')"
and a: "a ≠ Cact (cFriend UID1 (pass s UID1) UID2) ∧ a ≠ Cact (cFriend UID2 (pass s UID2) UID1) ∧
a ≠ Dact (dFriend UID1 (pass s UID1) UID2) ∧ a ≠ Dact (dFriend UID2 (pass s UID2) UID1)"
and "friendIDs s = friendIDs s1"
shows "friendIDs s' = friendIDs s1'"
using assms proof (cases a)
case (Sact sa) then show ?thesis using assms by (cases sa) (auto simp: s_defs) next
case (Uact ua) then show ?thesis using assms by (cases ua) (auto simp: u_defs) next
case (COMact ca) then show ?thesis using assms by (cases ca) (auto simp: com_defs) next
case (Dact da) then show ?thesis using assms proof (cases da)
case (dFriend uid p uid')
with Dact assms show ?thesis
by (cases "(uid,uid') ∈ {(UID1,UID2), (UID2,UID1)}")
(auto simp: d_defs eqButUID_stateSelectors eqButUIDf_not_UID')
qed
next
case (Cact ca) then show ?thesis using assms proof (cases ca)
case (cFriend uid p uid')
{ assume "p = pass s uid"
then have "uid' ∈∈ pendingFReqs s uid ⟷ uid' ∈∈ pendingFReqs s1 uid"
using Cact cFriend ss1 a by (intro eqButUIDf_not_UID') (auto simp: eqButUID_stateSelectors)
}
with Cact cFriend assms show ?thesis
by (auto simp: c_defs eqButUID_stateSelectors)
qed (auto simp: c_defs)
qed auto
lemma createFriend_sym: "createFriend s uid p uid' = createFriend s uid' p' uid"
unfolding c_defs by (cases "uid = uid'") (auto simp: fun_upd2_comm fun_upd_twist)
lemma deleteFriend_sym: "deleteFriend s uid p uid' = deleteFriend s uid' p' uid"
unfolding d_defs by (cases "uid = uid'") (auto simp: fun_upd_twist)
lemma createFriendReq_createFriend_absorb:
assumes "e_createFriendReq s uid' p uid req"
shows "createFriend (createFriendReq s uid' p1 uid req) uid p2 uid' = createFriend s uid p3 uid'"
using assms unfolding c_defs by (auto simp: remove1_idem remove1_append fun_upd2_absorb)
lemma eqButUID_deleteFriend12_friendIDs_eq:
assumes ss1: "eqButUID s s1"
and rs: "reach s" and rs1: "reach s1"
shows "friendIDs (deleteFriend s UID1 p UID2) = friendIDs (deleteFriend s1 UID1 p' UID2)"
proof -
have "distinct (friendIDs s UID1)" "distinct (friendIDs s UID2)"
"distinct (friendIDs s1 UID1)" "distinct (friendIDs s1 UID2)"
using rs rs1 by (auto intro: reach_distinct_friends_reqs)
then show ?thesis
using ss1 unfolding eqButUID_def eqButUIDf_def unfolding d_defs
by (auto simp: distinct_remove1_removeAll)
qed
lemma eqButUID_createFriend12_friendIDs_eq:
assumes ss1: "eqButUID s s1"
and rs: "reach s" and rs1: "reach s1"
and f12: "¬friends12 s" "¬friends12 s1"
shows "friendIDs (createFriend s UID1 p UID2) = friendIDs (createFriend s1 UID1 p' UID2)"
proof -
have f12': "UID1 ∉ set (friendIDs s UID2)" "UID2 ∉ set (friendIDs s UID1)"
"UID1 ∉ set (friendIDs s1 UID2)" "UID2 ∉ set (friendIDs s1 UID1)"
using f12 rs rs1 reach_friendIDs_symmetric unfolding friends12_def by auto
have "friendIDs s = friendIDs s1"
proof (intro ext)
fix uid
show "friendIDs s uid = friendIDs s1 uid"
using ss1 f12' unfolding eqButUID_def eqButUIDf_def
by (cases "uid = UID1 ∨ uid = UID2") (auto simp: remove1_idem)
qed
then show ?thesis by (auto simp: c_defs)
qed
end
end