@@ -12,91 +12,204 @@ source_path: src/Ledger/Conway/Specification/Certs/Properties/VoteDelegsVDeleg.l
1212
1313open import Ledger.Conway.Specification.Gov.Base
1414
15- module Ledger.Conway.Specification.Certs.Properties.VoteDelegsVDeleg (gs : _) (open GovStructure gs) where
15+ module Ledger.Conway.Specification.Certs.Properties.VoteDelegsVDeleg
16+ (gs : GovStructure) (open GovStructure gs)
17+ where
1618
1719open import Ledger.Conway.Specification.Certs gs
1820open import Ledger.Prelude
1921open import Ledger.Conway.Specification.Gov.Actions gs
2022
23+ open import Data.List.Relation.Unary.Any using (here; there)
24+
2125private variable
22- Γ : CertEnv
23- s s' : CertState
24- certs : List DCert
26+ Γ : CertEnv
27+ s s' : CertState
28+ stᵈ stᵈ' : DState
29+ certs : List DCert
30+ dCert : DCert
31+ D D' : ℙ Credential
32+ m : VoteDelegs
33+ v : VDeleg
2534```
2635-->
2736
2837* Informally* .
2938
30- A ` CertState ` {.AgdaRecord} has a ` DState ` {.AgdaRecord}, a ` PState ` {.AgdaRecord}, and a
31- ` GState ` {.AgdaRecord}. The ` DState ` {.AgdaRecord} contains a field
32- ` voteDelegs ` {.AgdaField}, a map sending the ` Credential ` {.AgdaDatatype} of a delegator to
33- the ` VDeleg ` {.AgdaDatatype} that receives its voting stake. The ` GState ` {.AgdaRecord}
34- contains a field ` dreps ` {.AgdaField} whose domain is the set of registered
35- ` DReps ` {.AgdaFunction}.
39+ A ` CertState ` {.AgdaRecord} has a ` DState ` {.AgdaRecord}, a ` PState ` {.AgdaRecord},
40+ and a ` GState ` {.AgdaRecord}. The ` DState ` {.AgdaRecord} contains a field
41+ ` voteDelegs ` {.AgdaField}, a map sending the ` Credential ` {.AgdaDatatype} of a
42+ delegator to the ` VDeleg ` {.AgdaDatatype} that receives its voting stake. The
43+ ` GState ` {.AgdaRecord} contains a field ` dreps ` {.AgdaField} whose domain is the set
44+ of registered ` DReps ` {.AgdaFunction}.
3645
3746` VDeleg ` {.AgdaDatatype} has three constructors:
3847` vDelegCredential ` {.AgdaInductiveConstructor}, which takes the
3948` Credential ` {.AgdaDatatype} of a ` DRep ` , and the two constants
4049` vDelegAbstain ` {.AgdaInductiveConstructor} and
41- ` vDelegNoConfidence ` {.AgdaInductiveConstructor}.
50+ ` vDelegNoConfidence ` {.AgdaInductiveConstructor}. Call a ` VDeleg ` {.AgdaDatatype}
51+ * active* for a set of credentials if it is one of those two constants or if it
52+ wraps a credential from that set.
53+
54+ The property proved here asserts that no ` CERTS ` {.AgdaDatatype} step introduces a
55+ vote delegation that is inactive for the registered ` DReps ` {.AgdaFunction}: if
56+ every value of ` voteDelegs ` {.AgdaField} is active before the batch of
57+ certificates, then so is every value after it.
4258
43- Call a ` VDeleg ` {.AgdaDatatype} * active* in a state if it is one of those two constants or
44- if it wraps the ` Credential ` {.AgdaDatatype} of a ` DRep ` registered in that state. The
45- present property asserts that a ` CERTS ` {.AgdaDatatype} step leaves no other kind of
46- ` VDeleg ` {.AgdaDatatype} behind: every value of the ` voteDelegs ` {.AgdaField} map of the
47- resulting state is active in that state. Nothing is assumed about the initial state,
48- because the ` POST-CERT ` {.AgdaDatatype} rule concluding every ` CERTS ` {.AgdaDatatype} step
49- corestricts ` voteDelegs ` {.AgdaField} to exactly the set of active
50- ` VDelegs ` {.AgdaDatatype}.
59+ The two rules that could break this maintain it themselves, in opposite ways.
60+ ` DELEG-delegate ` {.AgdaInductiveConstructor} may only install a ` VDeleg ` {.AgdaDatatype}
61+ that is already active, and ` GOVCERT-deregdrep ` {.AgdaInductiveConstructor}, which
62+ * shrinks* the set of registered ` DReps ` {.AgdaFunction}, simultaneously deletes every
63+ delegation to the credential it deregisters.
5164
5265* Formally* .
5366
5467``` agda
55- activeVDelegs : CertState → ℙ VDeleg
56- activeVDelegs s = mapˢ vDelegCredential (dom (DRepsOf s))
68+ activeVDelegs : ℙ Credential → ℙ VDeleg
69+ activeVDelegs D = mapˢ vDelegCredential D
5770 ∪ fromList (vDelegNoConfidence ∷ vDelegAbstain ∷ [])
5871
5972voteDelegsVDeleg : CertState → Type
60- voteDelegsVDeleg s = range (VoteDelegsOf s) ⊆ activeVDelegs s
73+ voteDelegsVDeleg s = range (VoteDelegsOf s) ⊆ activeVDelegs (dom (DRepsOf s))
6174
62- CERTS-voteDelegsVDeleg : Γ ⊢ s ⇀⦇ certs ,CERTS⦈ s' → voteDelegsVDeleg s'
75+ CERTS-voteDelegsVDeleg : LedgerInvariant _⊢_⇀⦇_ ,CERTS⦈_ voteDelegsVDeleg
6376```
6477
6578* Proof* .
6679
67- A ` CERTS ` {.AgdaDatatype} step consists of a ` PRE-CERT ` {.AgdaDatatype} step followed by a
68- trace of ` CERT ` {.AgdaDatatype} steps that ends with a ` POST-CERT ` {.AgdaDatatype} step, so
69- it suffices to establish the property at the end of such a trace. We do so in two
70- lemmas.
80+ It is convenient to read the property off one entry at a time, so we name the pointwise
81+ form and record that the two forms agree.
82+
83+ ``` agda
84+ vDelegsIn : ℙ Credential → VoteDelegs → Type
85+ vDelegsIn D m = ∀ {c v} → (c , v) ∈ m → v ∈ activeVDelegs D
86+
87+ ⊆⇒vDelegsIn : (m : VoteDelegs) → range m ⊆ activeVDelegs D → vDelegsIn D m
88+ ⊆⇒vDelegsIn _ h cv∈ = h (∈-map′ cv∈)
89+
90+ vDelegsIn⇒⊆ : (m : VoteDelegs) → vDelegsIn D m → range m ⊆ activeVDelegs D
91+ vDelegsIn⇒⊆ _ h v∈range with Equivalence.from ∈-map v∈range
92+ ... | _ , refl , cv∈ = h cv∈
93+ ```
94+
95+ The set of active ` VDelegs ` {.AgdaDatatype} grows with the set of credentials, and
96+ the two constants are active for every set.
97+
98+ ``` agda
99+ activeVDelegs-mono : D ⊆ D' → activeVDelegs D ⊆ activeVDelegs D'
100+ activeVDelegs-mono D⊆D' v∈ with Equivalence.from ∈-∪ v∈
101+ ... | inj₂ v∈consts = Equivalence.to ∈-∪ (inj₂ v∈consts)
102+ ... | inj₁ v∈creds with Equivalence.from ∈-map v∈creds
103+ ... | c , refl , c∈D =
104+ Equivalence.to ∈-∪ (inj₁ (Equivalence.to ∈-map (c , refl , D⊆D' c∈D)))
105+
106+ abstain∈active : vDelegAbstain ∈ activeVDelegs D
107+ abstain∈active = Equivalence.to ∈-∪ (inj₂ (Equivalence.to ∈-fromList (there (here refl))))
108+
109+ noConfidence∈active : vDelegNoConfidence ∈ activeVDelegs D
110+ noConfidence∈active = Equivalence.to ∈-∪ (inj₂ (Equivalence.to ∈-fromList (here refl)))
111+ ```
112+
113+ ** Lemma (` DELEG ` {.AgdaDatatype} preserves the property)** .
114+ The delegatee set is fixed throughout, so this is a statement about
115+ ` voteDelegs ` {.AgdaField} alone. The premise of
116+ ` DELEG-delegate ` {.AgdaInductiveConstructor} says precisely that the installed
117+ ` VDeleg ` {.AgdaDatatype} is active; ` DELEG-dereg ` {.AgdaInductiveConstructor} only
118+ removes entries, and ` DELEG-reg ` {.AgdaInductiveConstructor} leaves
119+ ` voteDelegs ` {.AgdaField} alone.
120+
121+ ``` agda
122+ delegatee∈active :
123+ just v ∈ mapˢ (just ∘ vDelegCredential) D
124+ ∪ fromList (nothing ∷ just vDelegAbstain ∷ just vDelegNoConfidence ∷ [])
125+ → v ∈ activeVDelegs D
126+ delegatee∈active mvd∈ with Equivalence.from ∈-∪ mvd∈
127+ ... | inj₁ ∈creds with Equivalence.from ∈-map ∈creds
128+ ... | c , refl , c∈D = Equivalence.to ∈-∪ (inj₁ (Equivalence.to ∈-map (c , refl , c∈D)))
129+ delegatee∈active mvd∈ | inj₂ ∈consts with Equivalence.from ∈-fromList ∈consts
130+ ... | there (here refl) = abstain∈active
131+ ... | there (there (here refl)) = noConfidence∈active
132+ ```
133+
134+ ``` agda
135+ DELEG-vDelegsIn : ∀ {pp : PParams} {pools : Pools}
136+ → ⟦ pp , pools , D ⟧ ⊢ stᵈ ⇀⦇ dCert ,DELEG⦈ stᵈ'
137+ → vDelegsIn D (VoteDelegsOf stᵈ) → vDelegsIn D (VoteDelegsOf stᵈ')
138+ DELEG-vDelegsIn (DELEG-delegate {mvd = nothing} _) h = h
139+ DELEG-vDelegsIn (DELEG-delegate {mvd = just _} (_ , _ , mvd∈ , _)) h cv∈
140+ with Properties.∈-∪⁻ cv∈
141+ ... | inj₂ cv∈rest = h (proj₂ (Equivalence.from ∈-filter cv∈rest))
142+ ... | inj₁ cv∈new =
143+ subst (_∈ activeVDelegs _)
144+ (sym (cong proj₂ (Equivalence.from ∈-singleton cv∈new)))
145+ (delegatee∈active mvd∈)
146+ DELEG-vDelegsIn (DELEG-dereg _) h cv∈ = h (ex-⊆ cv∈)
147+ DELEG-vDelegsIn (DELEG-reg _) h = h
148+ ```
71149
72- ** Lemma (` POST-CERT ` {.AgdaDatatype} establishes the property).** The single constructor
73- ` CERT-post ` {.AgdaInductiveConstructor} reveals the ` voteDelegs ` {.AgdaField} of its
74- resulting state to be a corestriction ` vd ` {.AgdaBound} ` ∣^ ` {.AgdaOperator}
75- ` X ` {.AgdaBound} of the incoming map ` vd ` {.AgdaBound}, and the range of a corestricted map
76- is contained in the corestricting set (` cores-range-⊆ ` {.AgdaFunction}). The set
77- ` X ` {.AgdaBound} is read off the ` GState ` {.AgdaRecord}, which the rule leaves untouched, so
78- ` X ` {.AgdaBound} is ` activeVDelegs ` {.AgdaFunction} of the resulting state.
150+ ** Lemma (` GOVCERT ` {.AgdaDatatype} preserves the property)** .
151+ ` GOVCERT-regdrep ` {.AgdaInductiveConstructor} only grows the domain of
152+ ` dreps ` {.AgdaField}, so ` activeVDelegs ` {.AgdaFunction} only grows;
153+ ` GOVCERT-ccreghot ` {.AgdaInductiveConstructor} touches neither field. In the
154+ ` GOVCERT-deregdrep ` {.AgdaInductiveConstructor} case a value ` v ` {.AgdaBound} of the
155+ resulting map comes from the incoming map and, by the corestriction, differs from
156+ ` vDelegCredential ` {.AgdaInductiveConstructor} ` c ` {.AgdaBound}. If ` v ` {.AgdaBound}
157+ is one of the two constants it stays active; otherwise ` v ` {.AgdaBound} is
158+ ` vDelegCredential ` {.AgdaInductiveConstructor} ` c' ` {.AgdaBound} for some registered
159+ ` c' ` {.AgdaBound}, and ` c' ` {.AgdaBound} ` ≢ ` {.AgdaFunction} ` c ` {.AgdaBound}, so
160+ ` c' ` {.AgdaBound} is still registered after the deregistration.
79161
80162``` agda
81- POST-CERT-voteDelegsVDeleg : Γ ⊢ s ⇀⦇ _ ,POST-CERT⦈ s' → voteDelegsVDeleg s'
82- POST-CERT-voteDelegsVDeleg (CERT-post {voteDelegs = vd}) = cores-range-⊆ vd
163+ GOVCERT-voteDelegsVDeleg : LedgerInvariant _⊢_⇀⦇_,GOVCERT⦈_ voteDelegsVDeleg
164+ GOVCERT-voteDelegsVDeleg (GOVCERT-regdrep {dReps = dReps} _) h =
165+ activeVDelegs-mono (dom-insert-⊇ dReps) ∘ h
166+ GOVCERT-voteDelegsVDeleg (GOVCERT-ccreghot _) h = h
167+ GOVCERT-voteDelegsVDeleg (GOVCERT-deregdrep {c = c} {dReps = dReps} {vDelegs = vDelegs} _) h =
168+ vDelegsIn⇒⊆ (vDelegs ∣^ ❴ vDelegCredential c ❵ ᶜ) λ cv∈ →
169+ let v∉ , cv∈vd = coex-∈⁻ vDelegs cv∈ in
170+ reinstate v∉ (⊆⇒vDelegsIn vDelegs h cv∈vd)
171+ where
172+ -- A delegation to `c'` survives the deregistration of `c` because `c' ≢ c`: were they
173+ -- equal, `v` would be the very `vDelegCredential c` the corestriction ruled out.
174+ keep : ∀ {v c'} → v ∉ ❴ vDelegCredential c ❵ → v ≡ vDelegCredential c'
175+ → c' ∈ dom dReps → v ∈ activeVDelegs (dom (dReps ∣ ❴ c ❵ ᶜ))
176+ keep {c' = c'} v∉ v≡ c'∈dom = Equivalence.to ∈-∪ (inj₁ (Equivalence.to ∈-map
177+ ( c' , v≡
178+ , ∈-resᶜ-dom⁺ ( (λ c'∈ → v∉ (Equivalence.to ∈-singleton (trans v≡
179+ (cong vDelegCredential (Equivalence.from ∈-singleton c'∈)))))
180+ , Equivalence.from dom∈ c'∈dom ) )))
181+
182+ reinstate : ∀ {v} → v ∉ ❴ vDelegCredential c ❵ → v ∈ activeVDelegs (dom dReps)
183+ → v ∈ activeVDelegs (dom (dReps ∣ ❴ c ❵ ᶜ))
184+ reinstate v∉ v∈ with Equivalence.from ∈-∪ v∈
185+ ... | inj₂ v∈consts = Equivalence.to ∈-∪ (inj₂ v∈consts)
186+ ... | inj₁ v∈creds =
187+ let c' , v≡ , c'∈dom = Equivalence.from ∈-map v∈creds in keep v∉ v≡ c'∈dom
83188```
84189
85- ** Lemma (the property holds at the end of a ` CERT ` {.AgdaDatatype} trace). ** Induct on the
86- trace. The intermediate ` CERT ` {.AgdaDatatype} steps are irrelevant: only the final state
87- is constrained, and it is produced by the ` POST- CERT` {.AgdaDatatype} step in the
88- ` run-[] ` {.AgdaInductiveConstructor} case .
190+ ** Lemma (` CERT ` {.AgdaDatatype} and ` PRE- CERT` {.AgdaDatatype} preserve the property) ** .
191+ ` CERT-pool ` {.AgdaInductiveConstructor} touches neither field, and
192+ ` CERT-pre ` {.AgdaInductiveConstructor} leaves ` voteDelegs ` {.AgdaField} alone while
193+ refreshing ` dreps ` {.AgdaField} with a left-biased union that keeps every key .
89194
90195``` agda
91- CERT-trace-voteDelegsVDeleg :
92- RunTraceAndThen _⊢_⇀⦇_,CERT⦈_ _⊢_⇀⦇_,POST-CERT⦈_ Γ s certs s' → voteDelegsVDeleg s'
93- CERT-trace-voteDelegsVDeleg (run-[] post) = POST-CERT-voteDelegsVDeleg post
94- CERT-trace-voteDelegsVDeleg (run-∷ _ trace) = CERT-trace-voteDelegsVDeleg trace
196+ CERT-voteDelegsVDeleg : LedgerInvariant _⊢_⇀⦇_,CERT⦈_ voteDelegsVDeleg
197+ CERT-voteDelegsVDeleg (CERT-deleg {stᵈ = stᵈ} {stᵈ' = stᵈ'} deleg) h =
198+ vDelegsIn⇒⊆ (VoteDelegsOf stᵈ')
199+ (DELEG-vDelegsIn deleg (⊆⇒vDelegsIn (VoteDelegsOf stᵈ) h))
200+ CERT-voteDelegsVDeleg (CERT-pool _) h = h
201+ CERT-voteDelegsVDeleg (CERT-vdel govcert) h = GOVCERT-voteDelegsVDeleg govcert h
202+
203+ PRE-CERT-voteDelegsVDeleg : LedgerInvariant _⊢_⇀⦇_,PRE-CERT⦈_ voteDelegsVDeleg
204+ PRE-CERT-voteDelegsVDeleg (CERT-pre {dReps = dReps} _) h =
205+ activeVDelegs-mono (dom-mapValueRestricted-⊇ dReps) ∘ h
95206```
96207
97- The theorem follows by inverting the ` CERTS ` {.AgdaDatatype} step and discarding its
98- ` PRE-CERT ` {.AgdaDatatype} component.
208+ A ` CERTS ` {.AgdaDatatype} step is a ` PRE-CERT ` {.AgdaDatatype} step followed by a
209+ trace of ` CERT ` {.AgdaDatatype} steps, so the theorem follows by lifting the two
210+ lemmas along the reflexive-transitive closure.
99211
100212``` agda
101- CERTS-voteDelegsVDeleg (run (_ , trace)) = CERT-trace-voteDelegsVDeleg trace
213+ CERTS-voteDelegsVDeleg (run (pre , trace)) =
214+ RTC-preserves-inv CERT-voteDelegsVDeleg trace ∘ PRE-CERT-voteDelegsVDeleg pre
102215```
0 commit comments