Theory Post_Visibility_Traceback
theory Post_Visibility_Traceback
imports Traceback_Intro
begin
consts PID :: postID
consts VIS :: vis
subsection ‹Tracing Back Post Visibility Status›
text ‹We prove the following traceback property:
If, at some point ‹t› on a system trace, the visibility of a post ‹PID›
has a value ‹VIS›, then one of the following holds:
\begin{itemize}
\item Either ‹VIS› is ‹FriendV› (i.e., friends-only) which is the default at post creation
\item Or the post's owner had issued a successful ``update visibility'' action setting the visibility to ‹VIS›,
and no other successful update actions to ‹PID›'s visibility occur
between the time of that action and ‹t›.
\end{itemize}
This will be captured in the predicate ‹proper›, and the main theorem states that ‹proper tr›
holds for any trace ‹tr› that leads to post ‹PID› acquiring visibility ‹VIS›.
›
text ‹‹SNC uidd trn› means
``The transaction ‹trn› is a successful post creation by user ‹uidd›'' ›
fun SNC :: "userID ⇒ (state,act,out) trans ⇒ bool" where
"SNC uidd (Trans s (Cact (cPost uid p pid tit)) ou s') = (ou = outOK ∧ (uid,pid) = (uidd,PID))"
|
"SNC uidd _ = False"
text ‹‹SNVU uidd vvs trn› means
"The transaction ‹trn› is a successful post visibility update for ‹PID›, by user ‹uidd›, to value ‹vvs›'' ›
fun SNVU :: "userID ⇒ vis ⇒ (state,act,out) trans ⇒ bool" where
"SNVU uidd vvs (Trans s (Uact (uVisPost uid p pid vs)) ou s') =
(ou = outOK ∧ (uid,pid) = (uidd,PID) ∧ vs = vvs)"
|
"SNVU uidd vvis _ = False"
definition proper :: "(state,act,out) trans trace ⇒ bool" where
"proper tr ≡
VIS = FriendV
∨
(∃ uid tr1 trn tr2 trnn tr3.
tr = tr1 @ trn # tr2 @ trnn # tr3 ∧
SNC uid trn ∧ SNVU uid VIS trnn ∧ (∀ vis. never (SNVU uid vis) tr3))"
definition proper1 :: "(state,act,out) trans trace ⇒ bool" where
"proper1 tr ≡
∃ tr2 trnn tr3.
tr = tr2 @ trnn # tr3 ∧
SNVU (owner (srcOf trnn) PID) VIS trnn"
lemma not_never_ex:
assumes "¬ never P xs"
shows "∃ xs1 x xs2. xs = xs1 @ x # xs2 ∧ P x ∧ never P xs2"
using assms proof(induct xs rule: rev_induct)
case (Nil)
thus ?case unfolding list_all_iff empty_iff by auto
next
case (snoc y ys)
show ?case
proof(cases "P y")
case True thus ?thesis using snoc
apply(intro exI[of _ ys]) apply(intro exI[of _ y] exI[of _ "[]"]) by auto
next
case False then obtain xs1 x xs2 where "ys = xs1 @ x # xs2 ∧ P x ∧ never P xs2"
using snoc by auto
thus ?thesis using snoc False
apply(intro exI[of _ xs1]) apply(intro exI[of _ x] exI[of _ "xs2 ## y"]) by auto
qed
qed
lemma SNVU_postIDs:
assumes "validTrans trn" and "SNVU uid vs trn"
shows "PID ∈∈ postIDs (srcOf trn)"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
by (cases "a") (auto simp: all_defs elim: step_elims)
qed
lemma SNVU_visib:
assumes "validTrans trn" and "SNVU uid vs trn"
shows "vis (tgtOf trn) PID = vs"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
by (cases "a") (auto simp: all_defs elim: step_elims)
qed
lemma owner_validTrans:
assumes "validTrans trn" and "PID ∈∈ postIDs (srcOf trn)"
shows "owner (srcOf trn) PID = owner (tgtOf trn) PID"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
by (cases "a") (auto simp: all_defs elim: step_elims)
qed
lemma owner_valid:
assumes "valid tr" and "PID ∈∈ postIDs (srcOf (hd tr))"
shows "owner (srcOf (hd tr)) PID = owner (tgtOf (last tr)) PID"
using assms using owner_validTrans IDs_mono validTrans by induct auto
lemma SNVU_vis_validTrans:
assumes "validTrans trn" and "PID ∈∈ postIDs (srcOf trn)"
and "∀ vs. ¬ SNVU (owner (srcOf trn) PID) vs trn"
shows "vis (srcOf trn) PID = vis (tgtOf trn) PID"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
by (cases "a") (auto simp: all_defs elim: step_elims)
qed
lemma SNVU_vis_valid:
assumes "valid tr" and "PID ∈∈ postIDs (srcOf (hd tr))"
and "∀ vis. never (SNVU (owner (srcOf (hd tr)) PID) vis) tr"
shows "vis (srcOf (hd tr)) PID = vis (tgtOf (last tr)) PID"
using assms proof induct
case (Singl)
thus ?case using SNVU_vis_validTrans by auto
next
case (Cons trn tr)
have n: "PID ∈∈ postIDs (srcOf (hd tr))"
using Cons by (simp add: IDs_mono(2) validTrans)
have v: "∀ vis. never (SNVU (owner (srcOf (hd tr)) PID) vis) tr"
using Cons by (simp add: owner_validTrans)
have "vis (srcOf trn) PID = vis (srcOf (hd tr)) PID"
using Cons SNVU_vis_validTrans by auto
also have "... = vis (tgtOf (last tr)) PID"
using n v Cons(4) by auto
finally show ?case using Cons by auto
qed
lemma proper1_never:
assumes vtr: "valid tr" and PID: "PID ∈∈ postIDs (srcOf (hd tr))"
and tr: "proper1 tr" and v: "vis (tgtOf (last tr)) PID = VIS"
shows "∃ tr2 trnn tr3.
tr = tr2 @ trnn # tr3 ∧
SNVU (owner (srcOf trnn) PID) VIS trnn ∧ (∀ vis. never (SNVU (owner (srcOf trnn) PID) vis) tr3)"
proof-
obtain tr2 trnn tr3 where
tr: "tr = tr2 @ trnn # tr3" and SNVU: "SNVU (owner (srcOf trnn) PID) VIS trnn"
using tr unfolding proper1_def by auto
define uid where "uid ≡ owner (srcOf trnn) PID"
show ?thesis
proof(cases "never (λ trn. ∃ vis. SNVU uid vis trn) tr3")
case True thus ?thesis using tr SNVU unfolding uid_def list_all_iff by blast
next
case False
from not_never_ex[OF this] obtain tr3a tr3n tr3b vs where tr3: "tr3 = tr3a @ tr3n # tr3b"
and SNVUtr3n: "SNVU uid vs tr3n" and n: "∀ vs. never (SNVU uid vs) tr3b"
unfolding list_all_iff by blast
have trnn: "validTrans trnn" and
tr3n: "validTrans tr3n" and vtr3: "valid tr3" using tr unfolding tr tr3
by (metis Nil_is_append_conv append_self_conv2 list.distinct(1) tr tr3 valid_ConsE valid_append vtr)+
hence PID_trnn: "PID ∈∈ postIDs (srcOf trnn)" and
PID_tr3n: "PID ∈∈ postIDs (srcOf tr3n)" using SNVU_postIDs SNVU SNVUtr3n by auto
have vvv: "valid (trnn # tr3a @ [tr3n])"
using vtr unfolding tr tr3
by (smt Nil_is_append_conv append_self_conv2 hd_append2 list.distinct(1) list.sel(1)
valid_Cons_iff valid_append)
hence PID_tr3n': "PID ∈∈ postIDs (tgtOf tr3n)" using tr3n SNVUtr3n
by (simp add: IDs_mono(2) PID_tr3n validTrans)
from owner_valid[OF vvv] PID_trnn
have 000: "owner (tgtOf tr3n) PID = uid" unfolding uid_def by simp
hence 0: "owner (srcOf tr3n) PID = uid" using PID_tr3n owner_validTrans tr3n by blast
have 00: "vs = vis (tgtOf tr3n) PID" using SNVUtr3n tr3n SNVU_visib by auto
have vis: "vs = VIS"
proof(cases "tr3b = []")
case True
thus ?thesis using v 00 unfolding tr tr3 by simp
next
case False
hence tgt: "tgtOf tr3n = srcOf (hd tr3b)" and tr3b: "valid tr3b" using vtr3 unfolding tr3
apply (metis valid_append list.distinct(2) self_append_conv2 valid_ConsE)
by (metis False append_self_conv2 list.distinct(1) tr3 valid_Cons_iff valid_append vtr3)
show ?thesis unfolding 00 tgt
using v False PID_tr3n'
using SNVU_vis_valid[OF tr3b _ n[unfolded 000[symmetric] tgt]]
unfolding tr tr3 tgt by simp
qed
show ?thesis apply(intro exI[of _ "tr2 @ trnn # tr3a"])
apply(intro exI[of _ tr3n] exI[of _ tr3b])
using SNVUtr3n n unfolding tr tr3 0 vis by simp
qed
qed
lemma SNVU_validTrans:
assumes "validTrans trn"
and "PID ∈∈ postIDs (srcOf trn)"
and "vis (srcOf trn) PID ≠ VIS"
and "vis (tgtOf trn) PID = VIS"
shows "SNVU (owner (srcOf trn) PID) VIS trn"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
by (cases "a") (auto simp: all_defs elim: step_elims)
qed
lemma valid_mono_postID:
assumes "valid tr"
and "PID ∈∈ postIDs (srcOf (hd tr))"
shows "PID ∈∈ postIDs (tgtOf (last tr))"
using assms proof induct
case (Singl trn)
then show ?case using IDs_mono(2) by (cases trn) auto
next
case (Cons trn tr)
then show ?case using IDs_mono(2) by (cases trn) auto
qed
lemma proper1_valid:
assumes V: "VIS ≠ FriendV"
and a: "valid tr"
"PID ∈∈ postIDs (srcOf (hd tr))"
"vis (srcOf (hd tr)) PID ≠ VIS"
"vis (tgtOf (last tr)) PID = VIS"
shows "proper1 tr"
using a unfolding valid_valid2 proof induct
case (Singl trn)
then show ?case unfolding proper1_def using SNVU_validTrans
by (intro exI[of _ "owner (srcOf trn) PID"] exI[of _ "[]"] exI[of _ trn]) auto
next
case (Rcons tr trn)
hence "PID ∈∈ postIDs (srcOf (hd tr))" using Rcons by simp
from valid_mono_postID[OF ‹valid2 tr›[unfolded valid2_valid] this]
have "PID ∈∈ postIDs (tgtOf (last tr))" by simp
hence 0: "PID ∈∈ postIDs (srcOf trn)" using Rcons by simp
show ?case
proof(cases "vis (srcOf trn) PID = VIS")
case False
hence "SNVU (owner (srcOf trn) PID) VIS trn"
apply (intro SNVU_validTrans) using 0 Rcons by auto
thus ?thesis unfolding proper1_def
by (intro exI[of _ tr] exI[of _ trn] exI[of _ "[]"]) auto
next
case True
hence "proper1 tr" using Rcons by auto
then obtain trr trnn tr3 where
tr: "tr = trr @ trnn # tr3" and SNVU: "SNVU (owner (srcOf trnn) PID) VIS trnn"
unfolding proper1_def using V by auto
have "vis (tgtOf trn) PID = VIS" using Rcons.prems by auto
thus ?thesis
using SNVU V unfolding proper1_def tr
by(intro exI[of _ trr] exI[of _ trnn] exI[of _ "tr3 ## trn"]) auto
qed
qed
lemma istate_postIDs:
"¬ PID ∈∈ postIDs istate"
unfolding istate_def by simp
definition proper2 :: "(state,act,out) trans trace ⇒ bool" where
"proper2 tr ≡
∃ uid tr1 trn tr2.
tr = tr1 @ trn # tr2 ∧ SNC uid trn"
lemma SNC_validTrans:
assumes "VIS ≠ FriendV" and "validTrans trn"
and "¬ PID ∈∈ postIDs (srcOf trn)"
and "PID ∈∈ postIDs (tgtOf trn)"
shows "∃ uid. SNC uid trn"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
by (cases "a") (auto simp: all_defs elim: step_elims)
qed
lemma proper2_valid:
assumes V: "VIS ≠ FriendV"
and a: "valid tr"
"¬ PID ∈∈ postIDs (srcOf (hd tr))"
"PID ∈∈ postIDs (tgtOf (last tr))"
shows "proper2 tr"
using a unfolding valid_valid2 proof induct
case (Singl trn)
then obtain uid where "SNC uid trn" using SNC_validTrans V by auto
thus ?case unfolding proper2_def using SNC_validTrans
by (intro exI[of _ uid] exI[of _ "[]"] exI[of _ trn]) auto
next
case (Rcons tr trn)
show ?case
proof(cases "PID ∈∈ postIDs (srcOf trn)")
case False
then obtain uid where "SNC uid trn"
using Rcons SNC_validTrans V by auto
thus ?thesis unfolding proper2_def
apply - apply (intro exI[of _ uid] exI[of _ tr]) by (intro exI[of _ trn] exI[of _ "[]"]) auto
next
case True
hence "proper2 tr" using Rcons by auto
then obtain uid tr1 trnn tr2 where
tr: "tr = tr1 @ trnn # tr2" and SFRC: "SNC uid trnn"
unfolding proper2_def by auto
have "PID ∈∈ postIDs (tgtOf trn)" using V Rcons.prems by auto
show ?thesis using SFRC unfolding proper2_def tr
apply - apply (intro exI[of _ uid] exI[of _ tr1])
by (intro exI[of _ trnn] exI[of _ "tr2 ## trn"]) simp
qed
qed
lemma proper2_valid_istate:
assumes V: "VIS ≠ FriendV"
and a: "valid tr"
"srcOf (hd tr) = istate"
"PID ∈∈ postIDs (tgtOf (last tr))"
shows "proper2 tr"
using proper2_valid assms istate_postIDs by auto
lemma SNC_visPost:
assumes "VIS ≠ FriendV"
and "validTrans trn" "SNC uid trn" and "reach (srcOf trn)"
shows "vis (tgtOf trn) PID ≠ VIS"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
apply (cases "a") apply (auto simp: all_defs elim: step_elims)
subgoal for x2 apply(cases x2)
using reach_not_postIDs_vis_FriendV
by (auto simp: all_defs elim: step_elims) .
qed
lemma SNC_postIDs:
assumes "validTrans trn" and "SNC uid trn"
shows "PID ∈∈ postIDs (tgtOf trn)"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
by (cases "a") (auto simp: all_defs elim: step_elims)
qed
lemma SNC_owner:
assumes "validTrans trn" and "SNC uid trn"
shows "uid = owner (tgtOf trn) PID"
proof(cases trn)
case (Trans s a ou s')
then show ?thesis
using assms
by (cases "a") (auto simp: all_defs elim: step_elims)
qed
theorem post_accountability:
assumes v: "valid tr" and i: "srcOf (hd tr) = istate"
and PIDin: "PID ∈∈ postIDs (tgtOf (last tr))"
and PID: "vis (tgtOf (last tr)) PID = VIS"
shows "proper tr"
proof(cases "VIS = FriendV")
case True thus ?thesis unfolding proper_def by auto
next
case False
have "proper2 tr" using proper2_valid_istate[OF False v i PIDin] .
then obtain uid tr1 trn trr where
tr: "tr = tr1 @ trn # trr" and SNC: "SNC uid trn" unfolding proper2_def by auto
hence trn: "validTrans trn" and r: "reach (srcOf trn)" using v unfolding tr
apply (metis list.distinct(2) self_append_conv2 valid_ConsE valid_append)
by (metis (mono_tags, lifting) append_Cons hd_append i list.sel(1) reach.simps tr v valid_append valid_init_reach)
hence N: "PID ∈∈ postIDs (tgtOf trn)" "vis (tgtOf trn) PID ≠ VIS"
using SNC_postIDs SNC_visPost False SNC by auto
hence trrNE: "trr ≠ []" and 1: "last tr = last trr" using PID unfolding tr by auto
hence trr_v: "valid trr" using v unfolding tr
by (metis valid_Cons_iff append_self_conv2 list.distinct(1) valid_append)
have 0: "tgtOf trn = srcOf (hd trr)" using v trrNE unfolding tr
by (metis valid_append list.distinct(2) self_append_conv2 valid_ConsE)
have "proper1 trr" using proper1_valid[OF False trr_v N[unfolded 0] PID[unfolded 1]] .
from proper1_never[OF trr_v N(1)[unfolded 0] this PID[unfolded 1]] obtain tr2 trnn tr3 where
trr: "trr = tr2 @ trnn # tr3" and SNVU: "SNVU (owner (srcOf trnn) PID) VIS trnn"
and vis: "∀ vis. never (SNVU (owner (srcOf trnn) PID) vis) tr3" by auto
have 00: "srcOf (hd (tr2 @ [trnn])) = tgtOf trn" using v unfolding tr trr
by (metis "0" append_self_conv2 hd_append2 list.sel(1) trr)
have trnn: "validTrans trnn" using trr_v unfolding trr
by (metis valid_Cons_iff append_self_conv2 list.distinct(1) valid_append)
have vv: "valid (tr2 @ [trnn])"
using v unfolding tr trr
by (smt Nil_is_append_conv append_self_conv2 hd_append2 list.distinct(1) list.sel(1)
valid_Cons_iff valid_append)
have "uid = owner (tgtOf trn) PID" using SNC trn SNC_owner by auto
also have "... = owner (tgtOf trnn) PID"
using owner_valid[OF vv] N(1) unfolding 00 by simp
also have "... = owner (srcOf trnn) PID"
using SNVU trnn SNVU_postIDs owner_validTrans by auto
finally have uid: "uid = owner (srcOf trnn) PID" .
show ?thesis unfolding proper_def
apply(rule disjI2)
apply(intro exI[of _ uid] exI[of _ tr1])
apply(rule exI[of _ trn], rule exI[of _ tr2])
apply(intro exI[of _ trnn] exI[of _ tr3])
using SNC SNVU vis unfolding tr trr uid by auto
qed
end