Theory Uv_Proofs
theory Uv_Proofs
imports Heard_Of.Reduction
Two_Step_Observing "../HO_Transition_System" Uv_Defs
begin
subsection ‹Proofs›
type_synonym uv_TS_state = "(nat × (process ⇒ (val pstate)))"
axiomatization where val_linorder:
"OFCLASS(val, linorder_class)"
instance val :: linorder by (rule val_linorder)
lemma two_step_step:
"step = two_step"
"phase = two_phase"
by(auto simp add: step_def two_step_def phase_def two_phase_def)
context mono_quorum
begin
definition UV_Alg :: "(process, val pstate, val msg)CHOAlgorithm" where
"UV_Alg = CHOAlgorithm.truncate UV_M"
definition UV_TS ::
"(round ⇒ process HO) ⇒ (round ⇒ process HO) ⇒ (round ⇒ process) ⇒ uv_TS_state TS"
where
"UV_TS HOs SHOs crds = CHO_to_TS UV_Alg HOs SHOs (K o crds)"
lemmas UV_TS_defs = UV_TS_def CHO_to_TS_def UV_Alg_def CHOinitConfig_def
UV_initState_def
type_synonym rHO = "nat ⇒ process HO"
definition UV_trans_step
where
"UV_trans_step HOs SHOs nxt_f snd_f stp ≡ ⋃r μ.
{((r, cfg), (Suc r, cfg'))|cfg cfg'. step r = stp ∧ (∀p.
μ p ∈ get_msgs (snd_f r) cfg (HOs r) (SHOs r) p
∧ nxt_f r p (cfg p) (μ p) (cfg' p)
)}"
lemma step_less_D:
"0 < step r ⟹ step r = Suc 0"
by(auto simp add: step_def)
lemma UV_trans:
"CSHO_trans_alt UV_sendMsg (λr p st msgs crd st'. UV_nextState r p st msgs st') HOs SHOs crds =
UV_trans_step HOs SHOs next0 send0 0
∪ UV_trans_step HOs SHOs next1 send1 1
"
proof
show "CSHO_trans_alt UV_sendMsg (λr p st msgs crd. UV_nextState r p st msgs) HOs SHOs crds
⊆ UV_trans_step HOs SHOs next0 send0 0 ∪ UV_trans_step HOs SHOs next1 send1 1"
by(force simp add: CSHO_trans_alt_def UV_sendMsg_def UV_nextState_def UV_trans_step_def
K_def dest!: step_less_D)
next
show " UV_trans_step HOs SHOs next0 send0 0 ∪
UV_trans_step HOs SHOs next1 send1 1
⊆ CSHO_trans_alt UV_sendMsg
(λr p st msgs crd. UV_nextState r p st msgs) HOs SHOs crds"
by(force simp add: CSHO_trans_alt_def UV_sendMsg_def UV_nextState_def UV_trans_step_def)
qed
subsubsection ‹Invariants›
definition UV_inv1
:: "uv_TS_state set"
where
"UV_inv1 = {(r, s).
two_step r = 0 ⟶ (∀p. agreed_vote (s p) = None)
}"
lemmas UV_inv1I = UV_inv1_def [THEN setc_def_to_intro, rule_format]
lemmas UV_inv1E [elim] = UV_inv1_def [THEN setc_def_to_elim, rule_format]
lemmas UV_inv1D = UV_inv1_def [THEN setc_def_to_dest, rule_format]
lemma UV_inv1_inductive:
"init (UV_TS HOs SHOs crds) ⊆ UV_inv1"
"{UV_inv1} TS.trans (UV_TS HOs SHOs crds) {> UV_inv1}"
by(auto simp add: UV_inv1_def UV_TS_defs CHO_trans_alt UV_trans PO_hoare_def
UV_HOMachine_def CHOAlgorithm.truncate_def UV_trans_step_def
all_conj_distrib two_step_phase_Suc two_step_step next1_def)
lemma UV_inv1_invariant:
"reach (UV_TS HOs SHOs crds) ⊆ UV_inv1"
by(intro inv_rule_basic UV_inv1_inductive)
subsubsection ‹Refinement›
definition ref_rel :: "(tso_state × uv_TS_state)set" where
"ref_rel ≡ {(sa, (r, sc)).
r = next_round sa
∧ (step r = 1 ⟶ r_votes sa = agreed_vote o sc)
∧ (∀p v. last_obs (sc p) = v ⟶ (∃q. opt_obsv_state.last_obs sa q ∈ {None, Some v}))
∧ decisions sa = decide o sc
}"
text ‹Agreement for UV only holds if the communication predicates hold›
context
fixes
HOs :: "nat ⇒ process ⇒ process set"
and rho :: "nat ⇒ process ⇒ 'val pstate"
assumes global: "UV_commGlobal HOs"
and per_rd: "∀r. UV_commPerRd (HOs r)"
and run: "HORun fA rho HOs"
begin
lemma HOs_intersect:
"HOs r p ∩ HOs r' q ≠ {}" using per_rd
apply(simp add: UV_commPerRd_def)
apply(blast dest: qintersect)
done
lemma HOs_nonempty:
"HOs r p ≠ {}"
using HOs_intersect
by blast
lemma vote_origin:
assumes
send: "∀p. μ p ∈ get_msgs (send0 r) cfg (HOs r) (HOs r) p"
and step: "∀p. next0 r p (cfg p) (μ p) (cfg' p)"
and inv: "(r, cfg) ∈ UV_inv1"
and step_r: "two_step r = 0"
shows
"agreed_vote (cfg' p) = Some v ⟷ (∀q ∈ HOs r p. last_obs (cfg q) = v)"
using send[THEN spec, where x=p] step[THEN spec, where x=p] inv step_r HOs_nonempty
by(auto simp add: next0_def get_msgs_benign send0_def msgRcvd_def o_def restrict_map_def)
lemma same_new_vote:
assumes
send: "∀p. μ p ∈ get_msgs (send0 r) cfg (HOs r) (HOs r) p"
and step: "∀p. next0 r p (cfg p) (μ p) (cfg' p)"
and inv: "(r, cfg) ∈ UV_inv1"
and step_r: "two_step r = 0"
obtains v where "∀p w. agreed_vote (cfg' p) = Some w ⟶ w = v"
proof(cases "∃p v. agreed_vote (cfg' p) = Some v")
case True
assume asm: "⋀v. ∀p w. agreed_vote (cfg' p) = Some w ⟶ w = v ⟹ thesis"
from True obtain p v where "agreed_vote (cfg' p) = Some v" by auto
hence "∀p w. agreed_vote (cfg' p) = Some w ⟶ w = v" (is "?LV(v)")
using vote_origin[OF send step inv step_r] HOs_intersect
by(force)
from asm[OF this] show ?thesis .
qed(auto)
lemma x_origin1:
assumes
send: "∀p. μ p ∈ get_msgs (send0 r) cfg (HOs r) (HOs r) p"
and step: "∀p. next0 r p (cfg p) (μ p) (cfg' p)"
and step_r: "two_step r = 0"
and last_obs: "last_obs (cfg' p) = v"
shows
"∃q. last_obs (cfg q) = v"
proof-
have "smallestValRcvd (μ p) ∈ {v. ∃q. μ p q = Some (Val v)}" (is "smallestValRcvd ?msgs ∈ ?vals")
unfolding smallestValRcvd_def
proof(rule Min_in)
have "?vals ⊆ getval ` ((the ∘ ?msgs) ` (HOs r p))"
using send[THEN spec, where x=p]
by (auto simp: image_def get_msgs_benign restrict_map_def send0_def)
thus "finite ?vals" by (auto simp: finite_subset)
next
from send[THEN spec, where x=p]
show "?vals ≠ {}" using HOs_nonempty[of r p]
by (auto simp: image_def get_msgs_benign restrict_map_def send0_def)
qed
hence "v ∈ ?vals" using last_obs step[THEN spec, of p]
by(auto simp add: next0_def all_conj_distrib)
thus ?thesis using send[THEN spec, of p]
by(auto simp add: get_msgs_benign send0_def restrict_map_def)
qed
lemma step0_ref:
"{ref_rel ∩ UNIV × UV_inv1} ⋃r S v. tso_round0 r S v,
UV_trans_step HOs HOs next0 send0 0 {> ref_rel}"
proof(clarsimp simp add: PO_rhoare_defs UV_trans_step_def two_step_step all_conj_distrib)
fix sa r cfg μ cfg'
assume
R: "(sa, (r, cfg)) ∈ ref_rel"
and step_r: "two_step r = 0"
and send: "∀p. μ p ∈ get_msgs (send0 r) cfg (HOs r) (HOs r) p"
and step: "∀p. next0 r p (cfg p) (μ p) (cfg' p)"
and inv: "(r, cfg) ∈ UV_inv1"
from R have next_r: "next_round sa = r"
by(simp add: ref_rel_def)
from HOs_nonempty send have "∀p. ∃q. q ∈ msgRcvd (μ p)"
by(fastforce simp add: get_msgs_benign send0_def msgRcvd_def restrict_map_def)
with step have same_dec: "decide o cfg' = decide o cfg"
apply(simp add: next0_def o_def)
by (metis pstate.select_convs(3) pstate.surjective pstate.update_convs(1) pstate.update_convs(2))
define S where "S = {p. ∃v. agreed_vote (cfg' p) = Some v}"
from same_new_vote[OF send step inv step_r]
obtain v where v: "∀p ∈ S. agreed_vote (cfg' p) = Some v"
by(simp add: S_def) (metis)
hence vote_const_map: "agreed_vote o cfg' = const_map v S"
by(auto simp add: S_def const_map_def restrict_map_def intro!: ext)
note x_origin = x_origin1[OF send step step_r]
define sa' where "sa' = sa⦇ next_round := Suc r, r_votes := const_map v S ⦈"
have "∀p. p ∈ S ⟶ opt_obs_safe (opt_obsv_state.last_obs sa) v"
using vote_origin[OF send step inv step_r] R per_rd[THEN spec, of r] v
apply(clarsimp simp add: UV_commPerRd_def opt_obs_safe_def ref_rel_def)
by metis
hence "(sa, sa') ∈ tso_round0 r S v" using next_r step_r v R
vote_origin[OF send step inv step_r]
by(auto simp add: tso_round0_def sa'_def all_conj_distrib)
moreover have "(sa', Suc r, cfg') ∈ ref_rel" using step send v R same_dec step_r next_r
apply(clarsimp simp add: ref_rel_def sa'_def two_step_step two_step_phase_Suc vote_const_map)
by (metis x_origin)
ultimately show
"∃sa'. (∃r S v. (sa, sa') ∈ tso_round0 r S v) ∧ (sa', Suc r, cfg') ∈ ref_rel"
by blast
qed
lemma x_origin2:
assumes
send: "∀p. μ p ∈ get_msgs (send1 r) cfg (HOs r) (HOs r) p"
and step: "∀p. next1 r p (cfg p) (μ p) (cfg' p)"
and step_r: "two_step r = Suc 0"
and last_obs: "last_obs (cfg' p) = v"
shows
"(∃q. last_obs (cfg q) = v) ∨ (∃q. agreed_vote (cfg q) = Some v)"
proof(cases "∀q ∈ HOs r p. ∃w. μ p q = Some (ValVote w None)")
case True
hence empty: "someVoteRcvd (μ p) = {}" using send[THEN spec, of p] HOs_nonempty[of r p]
by(auto simp add: someVoteRcvd_def msgRcvd_def isValVote_def
get_msgs_benign send1_def restrict_map_def)
have "smallestValNoVoteRcvd (μ p) ∈ {v. ∃q. μ p q = Some (ValVote v None)}"
(is "smallestValNoVoteRcvd ?msgs ∈ ?vals")
unfolding smallestValNoVoteRcvd_def
proof(rule Min_in)
have "?vals ⊆ getval ` ((the ∘ ?msgs) ` (HOs r p))"
using send[THEN spec, where x=p]
by (auto simp: image_def get_msgs_benign restrict_map_def send0_def)
thus "finite ?vals" by (auto simp: finite_subset)
next
from send[THEN spec, where x=p] True HOs_nonempty[of r p]
show "?vals ≠ {}"
by (auto simp: image_def get_msgs_benign restrict_map_def send1_def)
qed
hence "v ∈ ?vals" using empty step[THEN spec, of p] last_obs
by(auto simp add: next1_def x_update_def)
thus ?thesis using send[THEN spec, of p]
by(auto simp add: get_msgs_benign restrict_map_def send1_def)
next
case False
hence "someVoteRcvd (μ p) ≠ {}" using send[THEN spec, of p] HOs_nonempty[of r p]
by(auto simp add: someVoteRcvd_def msgRcvd_def isValVote_def
get_msgs_benign send1_def restrict_map_def)
hence "∃q ∈ someVoteRcvd (μ p). v = the (getvote (the (μ p q)))" using step[THEN spec, of p] last_obs
by(auto simp add: next1_def x_update_def)
thus ?thesis using send[THEN spec, of p]
by(auto simp add: next1_def x_update_def someVoteRcvd_def isValVote_def
send1_def get_msgs_benign msgRcvd_def restrict_map_def)
qed
definition D where
"D cfg cfg' ≡ {p. decide (cfg' p) ≠ decide (cfg p) }"
lemma decide_origin:
assumes
send: "∀p. μ p ∈ get_msgs (send1 r) cfg (HOs r) (HOs r) p"
and step: "∀p. next1 r p (cfg p) (μ p) (cfg' p)"
and step_r: "two_step r = Suc 0"
shows
"D cfg cfg' ⊆ {p. ∃v. decide (cfg' p) = Some v ∧ (∀q ∈ HOs r p. agreed_vote (cfg q) = Some v)}"
using assms
by(fastforce simp add: D_def next1_def get_msgs_benign send1_def msgRcvd_def o_def restrict_map_def
x_update_def dec_update_def identicalVoteRcvd_def all_conj_distrib someVoteRcvd_def isValVote_def
smallestValNoVoteRcvd_def)
lemma step1_ref:
"{ref_rel ∩ (TSO_inv1 ∩ TSO_inv2) × UNIV} ⋃r d_f o_f. tso_round1 r d_f o_f,
UV_trans_step HOs HOs next1 send1 (Suc 0) {> ref_rel}"
proof(clarsimp simp add: PO_rhoare_defs UV_trans_step_def two_step_step all_conj_distrib)
fix sa r cfg μ and cfg' :: "process ⇒ val pstate"
assume
R: "(sa, (r, cfg)) ∈ ref_rel"
and step_r: "two_step r = Suc 0"
and send: "∀p. μ p ∈ get_msgs (send1 r) cfg (HOs r) (HOs r) p"
and step: "∀p. next1 r p (cfg p) (μ p) (cfg' p)"
and ainv: "sa ∈ TSO_inv1"
and ainv2: "sa ∈ TSO_inv2"
from R have next_r: "next_round sa = r"
by(simp add: ref_rel_def)
define S where "S = {p. ∃v. agreed_vote (cfg p) = Some v}"
from R obtain v where v: "∀p ∈ S. agreed_vote (cfg p) = Some v" using ainv step_r
by(auto simp add: ref_rel_def TSO_inv1_def S_def two_step_step)
define Ob where "Ob = {p. last_obs (cfg' p) = v}"
define o_f where "o_f p = (if S ∈ Quorum then Some v else None)" for p :: process
define dec_f where "dec_f p = (if p ∈ D cfg cfg' then decide (cfg' p) else None)" for p
{
fix p w
assume "agreed_vote (cfg p) = Some w"
hence "w = v" using v
by(unfold S_def, auto)
} note v'=this
have d_guard: "d_guard dec_f (agreed_vote ∘ cfg)" using per_rd[THEN spec, of r]
by(fastforce simp add: d_guard_def locked_in_vf_def quorum_for_def dec_f_def
UV_commPerRd_def dest!: decide_origin[OF send step step_r, THEN subsetD])
have "dom (agreed_vote ∘ cfg) ∈ Quorum ⟶ Ob = UNIV"
proof(auto simp add: Ob_def)
fix p
assume Q: "dom (agreed_vote ∘ cfg) ∈ Quorum" (is "?Q ∈ Quorum")
hence "?Q ∩ HOs r p ≠ {}" using per_rd[THEN spec, of r]
by(auto simp add: UV_commPerRd_def dest: qintersect)
hence "someVoteRcvd (μ p) ≠ {}" using send[THEN spec, of p]
by(force simp add: someVoteRcvd_def get_msgs_benign msgRcvd_def restrict_map_def
isValVote_def send1_def)
moreover have "∀q ∈ someVoteRcvd (μ p). ∃x'. μ p q = Some (ValVote x' (Some v))"
using send[THEN spec, of p]
by(auto simp add: someVoteRcvd_def get_msgs_benign msgRcvd_def restrict_map_def
isValVote_def send1_def dest: v')
ultimately show "last_obs (cfg' p) = v" using step[THEN spec, of p]
by(auto simp add: next1_def x_update_def)
qed
note Ob_UNIV=this[rule_format]
have obs_guard: "obs_guard o_f (agreed_vote ∘ cfg)"
apply(auto simp add: obs_guard_def o_f_def S_def dom_def
dest: v' Ob_UNIV quorum_non_empty)
apply (metis S_def all_not_in_conv empty_not_quorum v)
done
define sa' where "sa' = sa⦇
next_round := Suc (next_round sa)
, decisions := decisions sa ++ dec_f
, opt_obsv_state.last_obs := opt_obsv_state.last_obs sa ++ o_f
⦈"
have abs_step: "(sa, sa') ∈ tso_round1 r dec_f o_f" using next_r step_r R d_guard obs_guard
by(auto simp add: tso_round1_def sa'_def ref_rel_def two_step_step)
have "∀p. ((decide ∘ cfg) ++ dec_f) p = decide (cfg' p)"
proof
fix p
show "((decide ∘ cfg) ++ dec_f) p = decide (cfg' p)" using step[THEN spec, of p]
by(auto simp add: dec_f_def D_def next1_def dec_update_def map_add_def)
qed
note dec_rel=this[rule_format]
have "∀p. (∃q. o_f q = None ∧ opt_obsv_state.last_obs sa q = None
∨ (opt_obsv_state.last_obs sa ++ o_f) q = Some (last_obs (cfg' p)))"
proof(intro allI impI, cases "S ∈ Quorum")
fix p
case True
hence "last_obs (cfg' p) = v" using Ob_UNIV
by(auto simp add: S_def Ob_def dom_def)
thus "(∃q. o_f q = None ∧ opt_obsv_state.last_obs sa q = None
∨ (opt_obsv_state.last_obs sa ++ o_f) q = Some (last_obs (cfg' p)))"
using True
by(auto simp add: o_f_def)
next
fix p
case False
hence empty: "o_f = Map.empty"
by(auto simp add: o_f_def)
note last_obs = x_origin2[OF send step step_r refl, of p]
thus "(∃q. o_f q = None ∧ opt_obsv_state.last_obs sa q = None
∨ (opt_obsv_state.last_obs sa ++ o_f) q = Some (last_obs (cfg' p)))"
proof(elim disjE exE)
fix q
assume "last_obs (cfg q) = last_obs (cfg' p)"
from this[symmetric] show ?thesis using R step_r empty
by(simp add: ref_rel_def two_step_step)
next
fix q
assume "agreed_vote (cfg q) = Some (last_obs (cfg' p))"
from this[symmetric] show ?thesis using R ainv2 step_r empty
apply(auto simp add: ref_rel_def two_step_step TSO_inv2_def)
by metis
qed
qed
note obs_rel=this[rule_format]
have post_rel:
"(sa', Suc r, cfg') ∈ ref_rel" using step send next_r R step_r
by(auto simp add: sa'_def ref_rel_def two_step_step
two_step_phase_Suc dec_rel obs_rel)
from abs_step post_rel show
"∃sa'. (∃r d_f o_f. (sa, sa') ∈ tso_round1 r d_f o_f) ∧ (sa', Suc r, cfg') ∈ ref_rel"
by blast
qed
lemma UV_Refines_votes:
"PO_refines (ref_rel ∩ (TSO_inv1 ∩ TSO_inv2) × UV_inv1)
tso_TS (UV_TS HOs HOs crds)"
proof(rule refine_using_invariants)
show "init (UV_TS HOs HOs crds) ⊆ ref_rel `` init tso_TS"
by(auto simp add: UV_TS_defs UV_HOMachine_def CHOAlgorithm.truncate_def
tso_TS_defs ref_rel_def tso_init_def Let_def o_def)
next
show
"{ref_rel ∩ (TSO_inv1 ∩ TSO_inv2) × UV_inv1} TS.trans tso_TS,
TS.trans (UV_TS HOs HOs crds) {> ref_rel}"
apply(simp add: tso_TS_defs UV_TS_defs UV_HOMachine_def CHOAlgorithm.truncate_def)
apply(auto simp add: CHO_trans_alt UV_trans intro!: step0_ref step1_ref)
done
qed(auto intro!: TSO_inv1_inductive TSO_inv2_inductive UV_inv1_inductive)
end
end
subsubsection ‹Termination›
text ‹As the model of the algorithm is taken verbatim from the HO Model AFP, we
do not repeat the termination proof here and refer to that AFP entry.›
end