468 lines
16 KiB
Lean4
468 lines
16 KiB
Lean4
import Mathlib.Data.Set.Basic
|
||
import Mathlib.Data.Set.Insert
|
||
import InductiveVerification.Message
|
||
|
||
-- Define the `Event` type
|
||
inductive Event
|
||
| Says : Agent → Agent → Msg → Event
|
||
| Gets : Agent → Msg → Event
|
||
| Notes : Agent → Msg → Event
|
||
|
||
-- Define the `initState` function
|
||
class HasInitState (α : Type) where
|
||
initState : α → Set Msg
|
||
|
||
variable [ hasInitStateAgent : HasInitState Agent ]
|
||
|
||
open HasInitState
|
||
|
||
-- Define the `bad` set
|
||
abbrev DecidableMem ( A : Set Agent ) := (a : Agent) → Decidable (a ∈ A)
|
||
class Bad where
|
||
bad : Set Agent
|
||
decidableBad : DecidableMem bad
|
||
Spy_in_bad : Agent.Spy ∈ bad
|
||
Server_not_bad : Agent.Server ∉ bad
|
||
|
||
instance [Bad] : DecidableMem Bad.bad := Bad.decidableBad
|
||
open Bad
|
||
|
||
-- attribute [simp] Spy_in_bad
|
||
-- attribute [simp] Server_not_bad
|
||
|
||
instance decidableAgentEq : DecidableEq Agent :=
|
||
λ a b =>
|
||
match a, b with
|
||
| Agent.Spy, Agent.Spy => isTrue rfl
|
||
| Agent.Spy, Agent.Server => isFalse (λ h => by contradiction)
|
||
| Agent.Spy, Agent.Friend m => isFalse (λ h => by contradiction)
|
||
| Agent.Server, Agent.Spy => isFalse (λ h => by contradiction)
|
||
| Agent.Server, Agent.Server => isTrue rfl
|
||
| Agent.Server, Agent.Friend m => isFalse (λ h => by contradiction)
|
||
| Agent.Friend n, Agent.Spy => isFalse (λ h => by contradiction)
|
||
| Agent.Friend n, Agent.Server => isFalse (λ h => by contradiction)
|
||
| Agent.Friend n, Agent.Friend m =>
|
||
if h : n = m then isTrue (congrArg Agent.Friend h) else isFalse (λ h' => h (Agent.Friend.inj h'))
|
||
|
||
-- instance decidableBad (a: Agent) : Decidable (a ∈ bad) :=
|
||
-- by rw[bad]; apply Set.decidableSingleton
|
||
|
||
-- Define the `knows` function
|
||
def knows [Bad] : Agent → List Event → Set Msg
|
||
| A, [] => initState A
|
||
| Agent.Spy, Event.Says _ _ X :: evs => insert X (knows Agent.Spy evs)
|
||
| Agent.Spy, Event.Gets _ _ :: evs => knows Agent.Spy evs
|
||
| Agent.Spy, Event.Notes A X :: evs =>
|
||
if A ∈ bad then insert X (knows Agent.Spy evs) else knows Agent.Spy evs
|
||
| A, Event.Says A' _ X :: evs =>
|
||
if A = A' then insert X (knows A evs) else knows A evs
|
||
| A, Event.Gets A' X :: evs =>
|
||
if A = A' then insert X (knows A evs) else knows A evs
|
||
| A, Event.Notes A' X :: evs =>
|
||
if A = A' then insert X (knows A evs) else knows A evs
|
||
|
||
-- Define the `spies` abbreviation
|
||
abbrev spies (evs : List Event) [Bad] : Set Msg := knows Agent.Spy evs
|
||
|
||
-- Define the `used` function
|
||
def used : List Event → Set Msg
|
||
| [] => ⋃ (B : Agent), parts (initState B)
|
||
| Event.Says _ _ X :: evs => parts {X} ∪ used evs
|
||
| Event.Gets _ _ :: evs => used evs
|
||
| Event.Notes _ X :: evs => parts {X} ∪ used evs
|
||
|
||
-- Lemmas for `used`
|
||
|
||
lemma used_mono : used (evs) ⊆ used (ev :: evs) := by
|
||
cases ev <;> simp[used]
|
||
|
||
lemma Notes_imp_used {A : Agent} {X : Msg} {evs : List Event} :
|
||
Event.Notes A X ∈ evs → X ∈ used evs := by
|
||
induction evs with
|
||
| nil => intro h; cases h
|
||
| cons ev evs ih =>
|
||
intro h
|
||
cases h with
|
||
| tail => cases ev
|
||
· simp [used]; right; aapply ih
|
||
· simp [used]; aapply ih
|
||
· simp [used]; right; aapply ih
|
||
| head => simp [used]; left; apply parts.inj; simp
|
||
|
||
lemma Says_imp_used {A B : Agent} {X : Msg} {evs : List Event} :
|
||
Event.Says A B X ∈ evs → X ∈ used evs := by
|
||
induction evs with
|
||
| nil => intro h; cases h
|
||
| cons ev evs ih =>
|
||
intro h
|
||
cases h with
|
||
| tail => cases ev
|
||
· simp [used]; right; aapply ih
|
||
· simp [used]; aapply ih
|
||
· simp [used]; right; aapply ih
|
||
| head => simp [used]; left; apply parts.inj; simp
|
||
|
||
-- Knowledge subset rules
|
||
lemma knows_subset_knows_Cons [Bad] {A : Agent} {ev : Event} {evs : List Event} :
|
||
knows A (evs) ⊆ knows A (ev :: evs) := by
|
||
by_cases h :A = Agent.Spy
|
||
· rw[h]
|
||
intro _ _
|
||
cases ev
|
||
· simp [knows]; right; assumption
|
||
· simp [knows]; assumption
|
||
· simp [knows]; split_ifs
|
||
· right; assumption
|
||
· assumption
|
||
· intro _ _
|
||
cases ev <;> (simp [knows]; split_ifs; right; assumption; assumption)
|
||
|
||
lemma initState_subset_knows [Bad] :
|
||
∀ {A : Agent} {evs : List Event},
|
||
initState A ⊆ knows A evs := by
|
||
intro A evs
|
||
induction evs with
|
||
| nil => simp [knows]
|
||
| cons e evs ih =>
|
||
apply subset_trans
|
||
· exact ih
|
||
· apply knows_subset_knows_Cons
|
||
|
||
-- Lemmas for `knows`
|
||
@[simp]
|
||
lemma knows_Spy_Says [Bad] {A B : Agent} {X : Msg} {evs : List Event} :
|
||
knows Agent.Spy (Event.Says A B X :: evs) = insert X (knows Agent.Spy evs) := by
|
||
simp [knows]
|
||
|
||
@[simp]
|
||
lemma knows_Spy_Notes [Bad] {A : Agent} {X : Msg} {evs : List Event} :
|
||
knows Agent.Spy (Event.Notes A X :: evs) =
|
||
if A ∈ bad then insert X (knows Agent.Spy evs) else knows Agent.Spy evs := by
|
||
simp [knows]
|
||
|
||
@[simp]
|
||
lemma knows_Spy_Gets [Bad] {A : Agent} {X : Msg} {evs : List Event} :
|
||
knows Agent.Spy (Event.Gets A X :: evs) = knows Agent.Spy evs := by
|
||
simp [knows]
|
||
|
||
lemma Says_imp_knows_Spy [Bad] {A B : Agent} {X : Msg} {evs : List Event} :
|
||
Event.Says A B X ∈ evs → X ∈ knows Agent.Spy evs := by
|
||
induction evs with
|
||
| nil => intro h; cases h
|
||
| cons ev evs ih =>
|
||
intro h
|
||
cases h with
|
||
| tail h => cases ev
|
||
· simp [knows]; right; aapply ih
|
||
· simp [knows]; aapply ih
|
||
· simp [knows]; split_ifs
|
||
· right; aapply ih
|
||
· aapply ih
|
||
| head h => simp [knows];
|
||
|
||
lemma Notes_imp_knows_Spy [Bad] {A : Agent} {X : Msg} {evs : List Event} :
|
||
Event.Notes A X ∈ evs → A ∈ bad → X ∈ knows Agent.Spy evs := by
|
||
induction evs with
|
||
| nil => intro h; cases h
|
||
| cons ev evs ih =>
|
||
intro h h_bad
|
||
cases h with
|
||
| head => simp [knows]; split_ifs; left; trivial
|
||
| tail _ h => apply knows_subset_knows_Cons; apply ih; apply h; apply h_bad
|
||
|
||
-- Elimination rules: derive contradictions from old Says events containing
|
||
-- items known to be fresh
|
||
lemma Says_imp_parts_knows_Spy [Bad] :
|
||
∀ {A B : Agent} {X : Msg} {evs : List Event},
|
||
Event.Says A B X ∈ evs → X ∈ parts (knows Agent.Spy evs) := by
|
||
intro A B X evs h
|
||
apply parts.inj
|
||
apply Says_imp_knows_Spy
|
||
exact h
|
||
|
||
lemma knows_Spy_partsEs [Bad] :
|
||
∀ {A B : Agent} {X : Msg} {evs : List Event},
|
||
Event.Says A B X ∈ evs → X ∈ parts (knows Agent.Spy evs) := by
|
||
exact Says_imp_parts_knows_Spy
|
||
|
||
lemma Says_imp_analz_Spy [InvKey] [Bad]
|
||
{A B : Agent} {X : Msg} {evs : List Event} :
|
||
Event.Says A B X ∈ evs → X ∈ analz (knows Agent.Spy evs) := by
|
||
intro h
|
||
apply analz.inj
|
||
apply Says_imp_knows_Spy
|
||
exact h
|
||
|
||
-- Compatibility for the old "spies" function
|
||
lemma spies_partsEs [Bad] :
|
||
∀ {A B : Agent} {X : Msg} {evs : List Event},
|
||
Event.Says A B X ∈ evs → X ∈ parts (knows Agent.Spy evs) := by
|
||
exact knows_Spy_partsEs
|
||
|
||
lemma Says_imp_spies [Bad] :
|
||
∀ {A B : Agent} {X : Msg} {evs : List Event},
|
||
Event.Says A B X ∈ evs → X ∈ knows Agent.Spy evs := by
|
||
exact Says_imp_knows_Spy
|
||
|
||
lemma parts_insert_spies [Bad] :
|
||
parts (insert X (knows Agent.Spy evs)) = parts {X} ∪ parts (knows Agent.Spy evs) :=
|
||
by
|
||
apply parts_insert
|
||
|
||
lemma analz_spies_mono [InvKey] [Bad]
|
||
{ h : M ∈ analz (knows Agent.Spy evs) } :
|
||
M ∈ analz (knows Agent.Spy (ev :: evs))
|
||
:= by
|
||
aapply analz_mono; exact knows_subset_knows_Cons
|
||
|
||
lemma analz_spies_mono_neg [InvKey] [Bad]
|
||
{ h : M ∉ analz (knows Agent.Spy (ev :: evs)) } :
|
||
M ∉ analz (knows Agent.Spy evs)
|
||
:= by
|
||
intro h₁; apply h; aapply analz_spies_mono
|
||
|
||
-- Knowledge of Agents
|
||
lemma knows_subset_knows_Says [Bad] :
|
||
∀ {A A' B : Agent} {X : Msg} {evs : List Event},
|
||
knows A evs ⊆ knows A (Event.Says A' B X :: evs) := by
|
||
intro A A' B X evs
|
||
apply knows_subset_knows_Cons
|
||
|
||
lemma knows_subset_knows_Notes [Bad] :
|
||
∀ {A A' : Agent} {X : Msg} {evs : List Event},
|
||
knows A evs ⊆ knows A (Event.Notes A' X :: evs) := by
|
||
intro A A' X evs
|
||
apply knows_subset_knows_Cons
|
||
|
||
lemma knows_subset_knows_Gets [Bad] :
|
||
∀ {A A' : Agent} {X : Msg} {evs : List Event},
|
||
knows A evs ⊆ knows A (Event.Gets A' X :: evs) := by
|
||
intro A A' X evs
|
||
apply knows_subset_knows_Cons
|
||
|
||
-- Agents know what they say
|
||
lemma Says_imp_knows [Bad] :
|
||
∀ {A B : Agent} {X : Msg} {evs : List Event},
|
||
Event.Says A B X ∈ evs → X ∈ knows A evs := by
|
||
intro A B X evs h
|
||
induction evs with
|
||
| nil => cases h
|
||
| cons ev evs ih =>
|
||
cases h with
|
||
| head => by_cases h: A = Agent.Spy
|
||
· rw [h]; simp [knows]
|
||
· simp [knows]
|
||
| tail => by_cases h: A = Agent.Spy
|
||
· rw[h]; cases ev
|
||
· simp [knows]; right; rw[←h]; aapply ih
|
||
· simp [knows]; rw[←h]; aapply ih
|
||
· simp [knows]; split_ifs
|
||
· right; rw[←h]; aapply ih
|
||
· rw[←h]; aapply ih
|
||
· cases ev <;> (
|
||
simp [knows]; split_ifs; right; aapply ih; aapply ih)
|
||
|
||
-- Agents know what they note
|
||
lemma Notes_imp_knows [Bad] :
|
||
∀ {A : Agent} {X : Msg} {evs : List Event},
|
||
Event.Notes A X ∈ evs → X ∈ knows A evs := by
|
||
intro A X evs h
|
||
induction evs with
|
||
| nil => cases h
|
||
| cons ev evs ih =>
|
||
cases h with
|
||
| head => by_cases h: A = Agent.Spy
|
||
· rw [h]; simp [knows, Spy_in_bad]
|
||
· simp [knows]
|
||
| tail => by_cases h: A = Agent.Spy
|
||
· rw[h]; cases ev
|
||
· simp [knows]; right; rw[←h]; aapply ih
|
||
· simp [knows]; rw[←h]; aapply ih
|
||
· simp [knows]; split_ifs
|
||
· right; rw[←h]; aapply ih
|
||
· rw[←h]; aapply ih
|
||
· cases ev <;> (
|
||
simp [knows]; split_ifs; right; aapply ih; aapply ih)
|
||
|
||
-- Agents know what they receive
|
||
lemma Gets_imp_knows_agents [Bad] :
|
||
∀ {A : Agent} {X : Msg} {evs : List Event},
|
||
A ≠ Agent.Spy → Event.Gets A X ∈ evs → X ∈ knows A evs := by
|
||
intro A X evs h_ne h
|
||
induction evs with
|
||
| nil => cases h
|
||
| cons ev evs ih =>
|
||
cases h with
|
||
| head => simp [knows]
|
||
| tail => cases ev <;> (simp [knows]; split_ifs; right; aapply ih; aapply ih)
|
||
|
||
-- What agents DIFFERENT FROM Spy know
|
||
lemma knows_imp_Says_Gets_Notes_initState [Bad] :
|
||
∀ {A : Agent} {X : Msg} {evs : List Event},
|
||
X ∈ knows A evs → A ≠ Agent.Spy →
|
||
∃ B, Event.Says A B X ∈ evs ∨ Event.Gets A X ∈ evs ∨ Event.Notes A X ∈ evs ∨ X ∈ initState A := by
|
||
intro _ _ evs h _
|
||
induction evs with
|
||
| nil => simp [knows] at h; exists Agent.Server; simp_all
|
||
| cons ev evs ih =>
|
||
cases ev
|
||
· simp [knows] at h; split_ifs at h with eq
|
||
· cases h with
|
||
| inl h₁ => grind
|
||
| inr h' => apply ih at h'; cases h' with | intro A'; exists A'; grind
|
||
· apply ih at h; cases h with | intro A'; exists A'; grind
|
||
· simp [knows] at h; split_ifs at h with eq
|
||
· cases h with
|
||
| inl h₁ => simp[h₁, eq]; exact ⟨Agent.Server⟩
|
||
| inr h' => apply ih at h'; cases h' with | intro A'; exists A'; grind
|
||
· apply ih at h; cases h with | intro A'; exists A'; grind
|
||
· simp [knows] at h; split_ifs at h with eq
|
||
· cases h with
|
||
| inl h₁ => simp[h₁, eq]; exact ⟨Agent.Server⟩
|
||
| inr h' => apply ih at h'; cases h' with | intro A'; exists A'; grind
|
||
· apply ih at h; cases h with | intro A'; exists A'; grind
|
||
|
||
-- auxiliary lemma
|
||
|
||
lemma knows_Spy_imp_Says_Notes_initState_aux
|
||
[Bad] {X : Msg} {ev : Event} {evs : List Event} :
|
||
(∃ A B, Event.Says A B X ∈ evs ∨ Event.Notes A X ∈ evs ∨ X ∈ initState Agent.Spy)
|
||
→ (∃ A B,
|
||
Event.Says A B X ∈ ev :: evs ∨ Event.Notes A X ∈ ev :: evs ∨ X ∈ initState Agent.Spy
|
||
) := by
|
||
intro h
|
||
cases h with | intro A h =>
|
||
cases h with | intro B h =>
|
||
exists A; exists B
|
||
cases h with
|
||
| inl => left; right; assumption
|
||
| inr h => right; cases h
|
||
· left; right; assumption
|
||
· right; assumption
|
||
|
||
-- What the Spy knows
|
||
lemma knows_Spy_imp_Says_Notes_initState [Bad] {X : Msg} {evs : List Event} :
|
||
X ∈ knows Agent.Spy evs →
|
||
∃ A B, Event.Says A B X ∈ evs ∨ Event.Notes A X ∈ evs ∨ X ∈ initState Agent.Spy := by
|
||
intro h
|
||
induction evs with
|
||
| nil => simp [knows] at h; exists Agent.Server; exists Agent.Server; simp_all
|
||
| cons ev evs ih =>
|
||
cases ev with
|
||
| Says A' B' =>
|
||
simp [knows] at h; cases h with
|
||
| inl => exists A'; exists B'; simp_all;
|
||
| inr h =>
|
||
apply ih at h; aapply knows_Spy_imp_Says_Notes_initState_aux
|
||
| Gets =>
|
||
simp [knows] at h; apply ih at h; aapply knows_Spy_imp_Says_Notes_initState_aux
|
||
| Notes A' X' =>
|
||
simp [knows] at h; split_ifs at h with A'_bad
|
||
· cases h with
|
||
| inl h => rw[h]; exists A'; exists A'; simp
|
||
| inr h => apply ih at h; aapply knows_Spy_imp_Says_Notes_initState_aux
|
||
· apply ih at h; aapply knows_Spy_imp_Says_Notes_initState_aux
|
||
|
||
-- Parts of what the Spy knows are a subset of what is used
|
||
lemma parts_knows_Spy_subset_used [Bad] :
|
||
parts (knows Agent.Spy evs) ⊆ used evs := by
|
||
induction evs with
|
||
| nil => simp [used, knows]; intro _ _; simp; exists Agent.Spy;
|
||
| cons ev evs ih =>
|
||
cases ev
|
||
· simp[used, knows]; apply subset_trans; apply ih; simp
|
||
· simp[used, knows]; assumption
|
||
· simp[used, knows]; split_ifs with ABad
|
||
· simp; apply subset_trans; apply ih; simp
|
||
· apply subset_trans; apply ih; simp
|
||
|
||
lemma parts_knows_Spy_subset_used_neg [Bad] :
|
||
M ∉ used evs → M ∉ parts (knows Agent.Spy evs) := by
|
||
intro h₁ h₂; apply h₁; aapply parts_knows_Spy_subset_used
|
||
|
||
lemma analz_knows_Spy_subset_used [Bad] [InvKey] :
|
||
analz (knows Agent.Spy evs) ⊆ used evs
|
||
:= by
|
||
apply subset_trans ( b := parts (knows Agent.Spy evs) )
|
||
· exact analz_subset_parts
|
||
· exact parts_knows_Spy_subset_used
|
||
|
||
lemma analz_knows_Spy_subset_used_neg [Bad] [InvKey] :
|
||
M ∉ used evs → M ∉ analz (knows Agent.Spy evs) := by
|
||
intro h₁ h₂; apply h₁; aapply analz_knows_Spy_subset_used
|
||
|
||
-- Parts of what the Spy knows are a subset of what is used
|
||
lemma usedI [Bad] :
|
||
X ∈ parts (knows Agent.Spy evs) → X ∈ used evs := by
|
||
intro h
|
||
apply parts_knows_Spy_subset_used
|
||
exact h
|
||
|
||
-- Initial state messages are part of the used set
|
||
|
||
lemma initState_into_used {B : Agent} {evs : List Event} :
|
||
parts (initState B) ⊆ used evs := by
|
||
induction evs with
|
||
| nil => simp [used]; apply Set.subset_iUnion (parts ∘ initState) B
|
||
| cons ev =>
|
||
cases ev <;> (simp[used]; try apply Set.subset_union_of_subset_right)
|
||
all_goals assumption
|
||
|
||
-- Simplification rules for `used`
|
||
|
||
@[simp]
|
||
lemma used_Says {A B : Agent} {X : Msg} {evs : List Event} :
|
||
used (Event.Says A B X :: evs) = parts {X} ∪ used evs := by
|
||
simp [used]
|
||
|
||
|
||
@[simp]
|
||
lemma used_Notes {A : Agent} {X : Msg} {evs : List Event} :
|
||
used (Event.Notes A X :: evs) = parts {X} ∪ used evs := by
|
||
simp [used]
|
||
|
||
|
||
@[simp]
|
||
lemma used_Gets {A : Agent} {X : Msg} {evs : List Event} :
|
||
used (Event.Gets A X :: evs) = used evs := by
|
||
simp [used]
|
||
|
||
|
||
lemma used_nil_subset {evs : List Event} :
|
||
used [] ⊆ used evs := by
|
||
have B := Agent.Server
|
||
induction evs with
|
||
| nil => simp
|
||
| cons head tail ih =>
|
||
apply subset_trans (b := used tail)
|
||
· assumption
|
||
· exact used_mono
|
||
|
||
-- Keys for parts insert
|
||
open InvKey
|
||
|
||
omit hasInitStateAgent in
|
||
|
||
lemma keysFor_parts_insert {K : Key} {X : Msg} {G H : Set Msg} [InvKey]:
|
||
K ∈ keysFor (parts (insert X G)) →
|
||
X ∈ synth (analz H) →
|
||
K ∈ keysFor (parts (G ∪ H)) ∪ invKey '' {K | Msg.Key K ∈ parts H} := by
|
||
intro h h₂
|
||
rw[parts_union, keysFor_union]
|
||
rcases h with ⟨K', ⟨⟨X', h⟩, r⟩⟩
|
||
by_cases KkfpG: K∈ keysFor (parts G)
|
||
· left; left; assumption
|
||
· rw[Set.union_assoc]; right; rw[←keysFor_synth]; rw[parts_insert] at h
|
||
cases h with
|
||
| inl h =>
|
||
apply Crypt_imp_invKey_keysFor at h; rw[r] at h
|
||
apply keysFor_mono (a := parts {X})
|
||
· apply synth_subset_iff.mpr; rw[←synth_subset_iff]
|
||
apply subset_trans (b := parts (synth (analz H)))
|
||
· apply parts_mono; simp; assumption
|
||
· rw[parts_synth, parts_analz]; apply sup_le
|
||
· exact synth_increasing
|
||
· apply synth_mono; exact analz_subset_parts
|
||
· assumption
|
||
| inr h => apply Crypt_imp_invKey_keysFor at h; rw[r] at h; contradiction
|