{-# OPTIONS --safe #-}
open import Ledger.Types.GovStructure
open import Ledger.Transaction using (TransactionStructure)
module Ledger.Gov (txs : _) (open TransactionStructure txs hiding (epoch)) where
open import Ledger.Prelude hiding (any?; Any; all?; All; Rel; lookup; ∈-filter)
open import Axiom.Set.Properties th using (∃-sublist-⇔)
open import Ledger.GovernanceActions govStructure using (Vote)
open import Ledger.Enact govStructure
open import Ledger.Ratify txs hiding (vote)
open import Ledger.Certs govStructure
open import Data.List.Ext using (subpermutations; sublists)
open import Data.List.Ext.Properties2
open import Data.List.Membership.Propositional.Properties using (Any↔; ∈-filter⁻; ∈-filter⁺)
open import Data.List.Relation.Binary.Subset.Propositional using () renaming (_⊆_ to _⊆ˡ_)
open import Data.List.Relation.Unary.All using (all?; All)
open import Data.List.Relation.Unary.Any using (any?; Any)
open import Data.List.Relation.Unary.Unique.DecPropositional using (unique?)
open import Data.List.Relation.Unary.Unique.Propositional using (Unique)
open import Data.Relation.Nullary.Decidable.Ext using (map′⇔)
open import Function.Related.Propositional using (↔⇒)
open GovActionState
GovState : Type
GovState = List (GovActionID × GovActionState)
record GovEnv : Type where
field
txid : TxId
epoch : Epoch
pparams : PParams
ppolicy : Maybe ScriptHash
enactState : EnactState
certState : CertState
rewardCreds : ℙ Credential
instance
unquoteDecl To-GovEnv = derive-To
[ (quote GovEnv , To-GovEnv) ]
private variable
Γ : GovEnv
s s' : GovState
aid : GovActionID
voter : Voter
vote : GovVote
v : Vote
d : Coin
addr : RwdAddr
a : GovAction
prev : NeedsHash (gaType a)
k : ℕ
p : Maybe ScriptHash
open GState
open PState
govActionPriority : GovActionType → ℕ
govActionPriority NoConfidence = 0
govActionPriority UpdateCommittee = 1
govActionPriority NewConstitution = 2
govActionPriority TriggerHF = 3
govActionPriority ChangePParams = 4
govActionPriority TreasuryWdrl = 5
govActionPriority Info = 6
Overlap : GovActionType → GovActionType → Type
Overlap NoConfidence UpdateCommittee = ⊤
Overlap UpdateCommittee NoConfidence = ⊤
Overlap a a' = a ≡ a'
Overlap? : (a a' : GovActionType) → Dec (Overlap a a')
Overlap? NoConfidence UpdateCommittee = Dec-⊤ .dec
Overlap? UpdateCommittee NoConfidence = Dec-⊤ .dec
Overlap? NoConfidence NoConfidence = yes refl
Overlap? NoConfidence NewConstitution = no (λ ())
Overlap? NoConfidence TriggerHF = no (λ ())
Overlap? NoConfidence ChangePParams = no (λ ())
Overlap? NoConfidence TreasuryWdrl = no (λ ())
Overlap? NoConfidence Info = no (λ ())
Overlap? UpdateCommittee UpdateCommittee = yes refl
Overlap? UpdateCommittee NewConstitution = no (λ ())
Overlap? UpdateCommittee TriggerHF = no (λ ())
Overlap? UpdateCommittee ChangePParams = no (λ ())
Overlap? UpdateCommittee TreasuryWdrl = no (λ ())
Overlap? UpdateCommittee Info = no (λ ())
Overlap? NewConstitution NoConfidence = no (λ ())
Overlap? NewConstitution UpdateCommittee = no (λ ())
Overlap? NewConstitution NewConstitution = yes refl
Overlap? NewConstitution TriggerHF = no (λ ())
Overlap? NewConstitution ChangePParams = no (λ ())
Overlap? NewConstitution TreasuryWdrl = no (λ ())
Overlap? NewConstitution Info = no (λ ())
Overlap? TriggerHF NoConfidence = no (λ ())
Overlap? TriggerHF UpdateCommittee = no (λ ())
Overlap? TriggerHF NewConstitution = no (λ ())
Overlap? TriggerHF TriggerHF = yes refl
Overlap? TriggerHF ChangePParams = no (λ ())
Overlap? TriggerHF TreasuryWdrl = no (λ ())
Overlap? TriggerHF Info = no (λ ())
Overlap? ChangePParams NoConfidence = no (λ ())
Overlap? ChangePParams UpdateCommittee = no (λ ())
Overlap? ChangePParams NewConstitution = no (λ ())
Overlap? ChangePParams TriggerHF = no (λ ())
Overlap? ChangePParams ChangePParams = yes refl
Overlap? ChangePParams TreasuryWdrl = no (λ ())
Overlap? ChangePParams Info = no (λ ())
Overlap? TreasuryWdrl NoConfidence = no (λ ())
Overlap? TreasuryWdrl UpdateCommittee = no (λ ())
Overlap? TreasuryWdrl NewConstitution = no (λ ())
Overlap? TreasuryWdrl TriggerHF = no (λ ())
Overlap? TreasuryWdrl ChangePParams = no (λ ())
Overlap? TreasuryWdrl TreasuryWdrl = yes refl
Overlap? TreasuryWdrl Info = no (λ ())
Overlap? Info NoConfidence = no (λ ())
Overlap? Info UpdateCommittee = no (λ ())
Overlap? Info NewConstitution = no (λ ())
Overlap? Info TriggerHF = no (λ ())
Overlap? Info ChangePParams = no (λ ())
Overlap? Info TreasuryWdrl = no (λ ())
Overlap? Info Info = yes refl
insertGovAction : GovState → GovActionID × GovActionState → GovState
insertGovAction [] gaPr = [ gaPr ]
insertGovAction ((gaID₀ , gaSt₀) ∷ gaPrs) (gaID₁ , gaSt₁)
= if (govActionPriority (action gaSt₀ .gaType)) ≤? (govActionPriority (action gaSt₁ .gaType))
then (gaID₀ , gaSt₀) ∷ insertGovAction gaPrs (gaID₁ , gaSt₁)
else (gaID₁ , gaSt₁) ∷ (gaID₀ , gaSt₀) ∷ gaPrs
mkGovStatePair : Epoch → GovActionID → RwdAddr → (a : GovAction) → NeedsHash (a .gaType)
→ GovActionID × GovActionState
mkGovStatePair e aid addr a prev = (aid , record
{ votes = ∅ ; returnAddr = addr ; expiresIn = e ; action = a ; prevAction = prev })
addAction : GovState
→ Epoch → GovActionID → RwdAddr → (a : GovAction) → NeedsHash (a .gaType)
→ GovState
addAction s e aid addr a prev = insertGovAction s (mkGovStatePair e aid addr a prev)
opaque
addVote : GovState → GovActionID → Voter → Vote → GovState
addVote s aid voter v = map modifyVotes s
where modifyVotes : GovActionID × GovActionState → GovActionID × GovActionState
modifyVotes = λ (gid , s') → gid , record s'
{ votes = if gid ≡ aid then insert (votes s') voter v else votes s'}
isRegistered : GovEnv → Voter → Type
isRegistered Γ (r , c) = case r of λ where
CC → just c ∈ range (gState .ccHotKeys)
DRep → c ∈ dom (gState .dreps)
SPO → c ∈ mapˢ KeyHashObj (dom (pState .pools))
where
open CertState (GovEnv.certState Γ) using (gState; pState)
validHFAction : GovProposal → GovState → EnactState → Type
validHFAction (record { action = ⟦ TriggerHF , v ⟧ᵍᵃ ; prevAction = prev }) s e =
(let (v' , aid) = EnactState.pv e in aid ≡ prev × pvCanFollow v' v)
⊎ ∃₂[ x , v' ] (prev , x) ∈ fromList s × x .action ≡ ⟦ TriggerHF , v' ⟧ᵍᵃ × pvCanFollow v' v
validHFAction _ _ _ = ⊤
data
_⊢_⇀⦇_,GOV⦈_ : GovEnv × ℕ → GovState → GovVote ⊎ GovProposal → GovState → Type
_⊢_⇀⦇_,GOVS⦈_ : GovEnv → GovState → List (GovVote ⊎ GovProposal) → GovState → Type
getAidPairsList : GovState → List (GovActionID × GovActionID)
getAidPairsList aid×states =
mapMaybe (λ (aid , aState) → (aid ,_) <$> getHash (prevAction aState)) $ aid×states
_connects_to_ : List (GovActionID × GovActionID) → GovActionID → GovActionID → Type
[] connects aidNew to aidOld = aidNew ≡ aidOld
((aid , aidPrev) ∷ s) connects aidNew to aidOld =
aid ≡ aidNew × s connects aidPrev to aidOld ⊎ s connects aidNew to aidOld
enactable : EnactState → List (GovActionID × GovActionID)
→ GovActionID × GovActionState → Type
enactable e aidPairs = λ (aidNew , as) → case getHashES e (action as .gaType) of
λ where
nothing → ⊤
(just aidOld) → ∃[ t ] fromList t ⊆ fromList aidPairs
× Unique t × t connects aidNew to aidOld
allEnactable : EnactState → GovState → Type
allEnactable e aid×states = All (enactable e (getAidPairsList aid×states)) aid×states
hasParentE : EnactState → GovActionID → GovActionType → Type
hasParentE e aid gaTy = case getHashES e gaTy of
λ where
nothing → ⊤
(just id) → id ≡ aid
hasParent : EnactState → GovState → (gaTy : GovActionType) → NeedsHash gaTy → Type
hasParent e s gaTy aid = case getHash aid of
λ where
nothing → ⊤
(just aid') → hasParentE e aid' gaTy
⊎ Any (λ (gid , gas) → gid ≡ aid' × Overlap (gas .action .gaType) gaTy) s
open Equivalence
hasParentE? : ∀ e aid a → Dec (hasParentE e aid a)
hasParentE? e aid gaTy with getHashES e gaTy
... | nothing = yes _
... | (just id) = id ≟ aid
hasParent? : ∀ e s a aid → Dec (hasParent e s a aid)
hasParent? e s gaTy aid with getHash aid
... | just aid' = hasParentE? e aid' gaTy
⊎-dec any? (λ (gid , gas) → gid ≟ aid' ×-dec Overlap? (gas .action .gaType) gaTy) s
... | nothing = yes _
data hasParent' : EnactState → GovState → (gaTy : GovActionType) → NeedsHash gaTy → Type where
HasParent' : ∀ {x y z w} → hasParent x y z w → hasParent' x y z w
instance
hasParent?' : ∀ {x y z w} → hasParent' x y z w ⁇
hasParent?' = ⁇ map′ HasParent' (λ where (HasParent' x) → x) (hasParent? _ _ _ _)
[_connects_to_?] : ∀ l aidNew aidOld → Dec (l connects aidNew to aidOld)
[ [] connects aidNew to aidOld ?] = aidNew ≟ aidOld
[ (aid , aidPrev) ∷ s connects aidNew to aidOld ?] =
((aid ≟ aidNew) ×-dec [ s connects aidPrev to aidOld ?]) ⊎-dec [ s connects aidNew to aidOld ?]
any?-connecting-subperm : ∀ {u} {v} → ∀ L → Dec (Any(λ l → Unique l × l connects u to v) (subpermutations L))
any?-connecting-subperm {u} {v} L = any? (λ l → unique? _≟_ l ×-dec [ l connects u to v ?]) (subpermutations L)
∃?-connecting-subperm : ∀ {u} {v} → ∀ L → Dec (∃[ l ] l ∈ˡ subpermutations L × Unique l × l connects u to v)
∃?-connecting-subperm L = from (map′⇔ (↔⇒ Any↔)) (any?-connecting-subperm L)
∃?-connecting-subset : ∀ {u} {v} → ∀ L → Dec (∃[ l ] l ⊆ˡ L × Unique l × l connects u to v)
∃?-connecting-subset L = from (map′⇔ ∃uniqueSubset⇔∃uniqueSubperm) (∃?-connecting-subperm L)
enactable? : ∀ eState aidPairs aidNew×st → Dec (enactable eState aidPairs aidNew×st)
enactable? eState aidPairs (aidNew , as) with getHashES eState (GovActionState.action as .gaType)
... | nothing = yes tt
... | just aidOld = from (map′⇔ ∃-sublist-⇔) (∃?-connecting-subset aidPairs)
allEnactable? : ∀ eState aid×states → Dec (allEnactable eState aid×states)
allEnactable? eState aid×states =
all? (λ aid×st → enactable? eState (getAidPairsList aid×states) aid×st) aid×states
data allEnactable' : EnactState → GovState → Type where
AllEnactable' : ∀ {x y} → allEnactable x y → allEnactable' x y
instance
allEnactable?' : ∀ {x y} → allEnactable' x y ⁇
allEnactable?' = ⁇ map′ AllEnactable' (λ where (AllEnactable' x) → x) (allEnactable? _ _)
maxAllEnactable : EnactState → List (GovActionID × GovActionState) → List (List (GovActionID × GovActionState))
maxAllEnactable e = maxsublists⊧P (allEnactable? e)
∈-maxAllEnactable→allEnactable : ∀ {e} {aid×states} l
→ l ∈ˡ maxAllEnactable e aid×states → allEnactable e l
∈-maxAllEnactable→allEnactable {e} {aid×states} l l∈ =
proj₂ (∈-filter⁻ (allEnactable? e) {l} {sublists aid×states}
(proj₁ (∈-filter⁻ (λ l → length l ≟ maxlen (sublists⊧P (allEnactable? e) aid×states)) l∈)))
∈-maxAllEnactable→maxLength : ∀ {e aid×states l l'}
→ l ∈ˡ sublists aid×states → allEnactable e l
→ l' ∈ˡ maxAllEnactable e aid×states
→ length l ≤ length l'
∈-maxAllEnactable→maxLength {e} {aid×states} {l} {l'} l∈ el l'∈ =
let ls = sublists⊧P (allEnactable? e) aid×states in
subst (length l ≤_)
(sym (proj₂ (∈-filter⁻ (λ l → length l ≟ maxlen ls) {xs = ls} l'∈)))
(∈-maxlen-≤ l (∈-filter⁺ (allEnactable? e) l∈ el))
actionValid : ℙ Credential → Maybe ScriptHash → Maybe ScriptHash → Epoch → GovAction → Type
actionValid rewardCreds p ppolicy epoch ⟦ ChangePParams , _ ⟧ᵍᵃ =
p ≡ ppolicy
actionValid rewardCreds p ppolicy epoch ⟦ TreasuryWdrl , x ⟧ᵍᵃ =
p ≡ ppolicy × mapˢ RwdAddr.stake (dom x) ⊆ rewardCreds
actionValid rewardCreds p ppolicy epoch ⟦ UpdateCommittee , (new , rem , q) ⟧ᵍᵃ =
p ≡ nothing × (∀[ e ∈ range new ] epoch < e) × (dom new ∩ rem ≡ᵉ ∅)
actionValid rewardCreds p ppolicy epoch _ =
p ≡ nothing
actionWellFormed : GovAction → Type
actionWellFormed ⟦ ChangePParams , x ⟧ᵍᵃ = ppdWellFormed x
actionWellFormed ⟦ TreasuryWdrl , x ⟧ᵍᵃ =
(∀[ a ∈ dom x ] RwdAddr.net a ≡ NetworkId) × (∃[ v ∈ range x ] ¬ (v ≡ 0))
actionWellFormed _ = ⊤
actionValid? : ∀ {rewardCreds p ppolicy epoch a} → actionValid rewardCreds p ppolicy epoch a ⁇
actionValid? {a = ⟦ NoConfidence , _ ⟧ᵍᵃ} = it
actionValid? {a = ⟦ UpdateCommittee , _ ⟧ᵍᵃ} = it
actionValid? {a = ⟦ NewConstitution , _ ⟧ᵍᵃ} = it
actionValid? {a = ⟦ TriggerHF , _ ⟧ᵍᵃ} = it
actionValid? {a = ⟦ ChangePParams , _ ⟧ᵍᵃ} = it
actionValid? {a = ⟦ TreasuryWdrl , _ ⟧ᵍᵃ} = it
actionValid? {a = ⟦ Info , _ ⟧ᵍᵃ} = it
actionWellFormed? : ∀ {a} → actionWellFormed a ⁇
actionWellFormed? {⟦ NoConfidence , _ ⟧ᵍᵃ} = it
actionWellFormed? {⟦ UpdateCommittee , _ ⟧ᵍᵃ} = it
actionWellFormed? {⟦ NewConstitution , _ ⟧ᵍᵃ} = it
actionWellFormed? {⟦ TriggerHF , _ ⟧ᵍᵃ} = it
actionWellFormed? {⟦ ChangePParams , _ ⟧ᵍᵃ} = it
actionWellFormed? {⟦ TreasuryWdrl , _ ⟧ᵍᵃ} = it
actionWellFormed? {⟦ Info , _ ⟧ᵍᵃ} = it
open GovEnv
open PParams hiding (a)
variable
machr : Maybe Anchor
achr : Anchor
ast : GovActionState
data _⊢_⇀⦇_,GOV⦈_ where
GOV-Vote :
∙ (aid , ast) ∈ fromList s
∙ canVote (Γ .pparams) (action ast) (proj₁ voter)
∙ isRegistered Γ voter
∙ ¬ expired (Γ .epoch) ast
───────────────────────────────────────
(Γ , k) ⊢ s ⇀⦇ inj₁ ⟦ aid , voter , v , machr ⟧ ,GOV⦈ addVote s aid voter v
GOV-Propose :
let pp = Γ .pparams
e = Γ .epoch
enactState = Γ .enactState
rewardCreds = Γ .rewardCreds
prop = record { returnAddr = addr ; action = a ; anchor = achr
; policy = p ; deposit = d ; prevAction = prev }
in
∙ actionWellFormed a
∙ actionValid rewardCreds p (Γ .ppolicy) e a
∙ d ≡ pp .govActionDeposit
∙ validHFAction prop s enactState
∙ hasParent enactState s (a .gaType) prev
∙ addr .RwdAddr.net ≡ NetworkId
∙ addr .RwdAddr.stake ∈ rewardCreds
───────────────────────────────────────
(Γ , k) ⊢ s ⇀⦇ inj₂ prop ,GOV⦈ addAction s (pp .govActionLifetime +ᵉ e)
(Γ .txid , k) addr a prev
_⊢_⇀⦇_,GOVS⦈_ = ReflexiveTransitiveClosureᵢ {sts = _⊢_⇀⦇_,GOV⦈_}