Skip to content

Commit 0f70d5c

Browse files
williamdemeoclaude
andcommitted
revised statement of property; and complete proof!
Gov/Properties/LastVoteApplied: - last-vote-applied-to-GA: across a block (the GOVS closure of GOV), the last vote a voter casts on an action is the one recorded in the resulting GovState, provided the action was not created by the current transaction (Γ.txid ≢ proj₁ aid). - vote-applied-to-GA: the single-GOV-step companion. The proof is an induction on the GOVS derivation, chaining the per-step facts (recordedVote-addVote / -≢gid / -≢voter / -addAction-≢) into the foldl that lastVoteOn computes. Inducting on the derivation rather than a pure fold over the signals is essential: the GOV-Vote rule supplies the proof that the voted action is present. Without the freshness precondition the statement is false (a same-block re-proposal can shadow the voted entry); discharging it for all ledger-reachable states is left as a TODO noted in the source. Axiom.Set.Map.Extras: adds four general, non-Gov-specific finite-map lemmas the proof relies on — lookupᵐ?-insert, ∈-insert-≢, ∈-insert-≢⁻, and lookupᵐ?-insert-≢ (lookup commutes with insert at a distinct key). Candidates for upstreaming to agda-sets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rz41G9j463RqCCpUpFTGc4
1 parent 137269d commit 0f70d5c

2 files changed

Lines changed: 291 additions & 138 deletions

File tree

src-lib-exts/abstract-set-theory/Axiom/Set/Map/Extra.agda

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,3 +701,53 @@ module _ {A B : Type}
701701

702702
lem-del-excluded : m ¬ P k filterᵐ P′ (m ∣ ❴ k ❵ ᶜ) ≡ᵐ filterᵐ P′ m
703703
lem-del-excluded m ¬p = filterᵐ-restrict m ⟨≈⟩ restrict-singleton-filterᵐ-false m ¬p
704+
705+
706+
-- Map lemmas: lookup after insert
707+
708+
-- Looking up a freshly inserted key returns the inserted value.
709+
-- Since `insert m k v = ❴ k , v ❵ᵐ ∪ˡ m` (singleton on the left),
710+
-- `(k , v)` is in the inserted map, and `∈⇒lookup≡just` reads it back.
711+
lookupᵐ?-insert : {A B : Type} ⦃ _ : DecEq A ⦄ (m : A ⇀ B) (k : A) (v : B)
712+
lookupᵐ? (insert m k v) k ≡ just v
713+
lookupᵐ?-insert m k v =
714+
∈⇒lookup≡just (insert m k v) k (Properties.∈-∪⁺ (inj₁ (Equivalence.to ∈-singleton refl)))
715+
716+
-- Inserting at a *different* key preserves membership in both directions (`insert` is a
717+
-- left-biased union with the singleton `❴ k₀ , v₀ ❵ᵐ`, which only touches the key `k₀`).
718+
∈-insert-≢ : {A B : Type} ⦃ _ : DecEq A ⦄ {m : A ⇀ B} {k₀ k : A} {v₀ y : B}
719+
k₀ ≢ k (k , y) ∈ m ˢ (k , y) ∈ (insert m k₀ v₀) ˢ
720+
∈-insert-≢ {k₀ = k₀} {k} ne ky∈m =
721+
Properties.∈-∪⁺ (inj₂ (Equivalence.to ∈-filter
722+
((λ k∈ ne (sym (cong proj₁ (Equivalence.from ∈-singleton (proj₂ (Equivalence.from dom∈ k∈)))))) , ky∈m)))
723+
724+
∈-insert-≢⁻ : {A B : Type} ⦃ _ : DecEq A ⦄ {m : A ⇀ B} {k₀ k : A} {v₀ y : B}
725+
k₀ ≢ k (k , y) ∈ (insert m k₀ v₀) ˢ (k , y) ∈ m ˢ
726+
∈-insert-≢⁻ ne ky∈ins with Properties.∈-∪⁻ ky∈ins
727+
... | inj₁ ky∈sing = ⊥-elim (ne (sym (cong proj₁ (Equivalence.from ∈-singleton ky∈sing))))
728+
... | inj₂ ky∈filt = proj₂ (Equivalence.from ∈-filter ky∈filt)
729+
730+
-- Hence looking up a *different* key is unaffected by `insert`. We match both `⁇` instances
731+
-- (so each `lookupᵐ?` reduces, as in `∈⇒lookup≡just`; the "present in one but not the other"
732+
-- cases are impossible by membership preservation:
733+
lookupᵐ?-insert-≢ : {A B : Type} ⦃ _ : DecEq A ⦄ (m : A ⇀ B) {k₀ k : A} {v₀ : B}
734+
k₀ ≢ k
735+
→ ⦃ i1 : (k ∈ dom ((insert m k₀ v₀) ˢ)) ⁇ ⦄ ⦃ i2 : (k ∈ dom (m ˢ)) ⁇ ⦄
736+
lookupᵐ? (insert m k₀ v₀) k ⦃ i1 ⦄ ≡ lookupᵐ? m k ⦃ i2 ⦄
737+
lookupᵐ?-insert-≢ m {k₀} {k} {v₀} ne ⦃ ⁇ yes k∈ins ⦄ ⦃ ⁇ yes k∈m ⦄ =
738+
let (y , ky∈m) = Equivalence.from dom∈ k∈m
739+
ky∈ins : (k , y) ∈ (insert m k₀ v₀) ˢ
740+
ky∈ins = ∈-insert-≢ {m = m} {v₀ = v₀} ne ky∈m
741+
in trans (∈⇒lookup≡just (insert m k₀ v₀) k ky∈ins ⦃ ⁇ yes k∈ins ⦄)
742+
(sym (∈⇒lookup≡just m k ky∈m ⦃ ⁇ yes k∈m ⦄))
743+
lookupᵐ?-insert-≢ m {k₀} {k} {v₀} ne ⦃ ⁇ yes k∈ins ⦄ ⦃ ⁇ no k∉m ⦄ =
744+
let (y , ky∈ins) = Equivalence.from dom∈ k∈ins
745+
ky∈m : (k , y) ∈ m ˢ
746+
ky∈m = ∈-insert-≢⁻ {m = m} {v₀ = v₀} ne ky∈ins
747+
in ⊥-elim (k∉m (Equivalence.to dom∈ (y , ky∈m)))
748+
lookupᵐ?-insert-≢ m {k₀} {k} {v₀} ne ⦃ ⁇ no k∉ins ⦄ ⦃ ⁇ yes k∈m ⦄ =
749+
let (y , ky∈m) = Equivalence.from dom∈ k∈m
750+
ky∈ins : (k , y) ∈ (insert m k₀ v₀) ˢ
751+
ky∈ins = ∈-insert-≢ {m = m} {v₀ = v₀} ne ky∈m
752+
in ⊥-elim (k∉ins (Equivalence.to dom∈ (y , ky∈ins)))
753+
lookupᵐ?-insert-≢ m {k₀} {k} {v₀} ne ⦃ ⁇ no k∉ins ⦄ ⦃ ⁇ no k∉m ⦄ = refl

0 commit comments

Comments
 (0)