\section{Enactment}
\label{sec:enactment}
\begin{code}[hide]
{-# OPTIONS --safe #-}

open import Data.Nat.Properties using (+-0-monoid)
open import Data.Rational using ()

open import Ledger.Prelude
open import Ledger.Types.GovStructure

module Ledger.Enact (gs : _) (open GovStructure gs) where

open import Ledger.GovernanceActions gs
\end{code}

Figure~\ref{fig:enact-defs} contains some definitions required to
define the ENACT transition system. \EnactEnv is the environment and
\EnactState the state of ENACT, which enacts a governance action. All
governance actions except \TreasuryWdrl and \Info modify \EnactState
permanently, which of course can have further
consequences. \TreasuryWdrl accumulates withdrawal temporarily in \EnactState,
but this information is applied and discarded immediately in EPOCH.
Also, enacting these governance actions is the
\emph{only} way of modifying \EnactState. The \withdrawals field of
\EnactState is special in that it is ephemeral---ENACT accumulates
withdrawals there which are paid out at the next epoch boundary where
this field will be reset.

Note that all other fields of \EnactState also contain a \GovActionID
since they are \HashProtected.

\begin{figure*}[h]
\begin{AgdaMultiCode}
\begin{code}
record EnactEnv : Type where
\end{code}
\begin{code}[hide]
  constructor ⟦_,_,_⟧ᵉ
  field
\end{code}
\begin{code}
    gid       : GovActionID
    treasury  : Coin
    epoch     : Epoch

record EnactState : Type where
\end{code}
\begin{code}[hide]
  field
\end{code}
\begin{code}
    cc            : HashProtected (Maybe ((Credential  Epoch) × ))
    constitution  : HashProtected (DocHash × Maybe ScriptHash)
    pv            : HashProtected ProtVer
    pparams       : HashProtected PParams
    withdrawals   : RwdAddr  Coin
\end{code}
\begin{code}[hide]
open EnactState
\end{code}
\begin{code}

ccCreds : HashProtected (Maybe ((Credential  Epoch) × ))   Credential
ccCreds (just x   , _)  = dom (x .proj₁)
ccCreds (nothing  , _)  = 

getHash :  {a}  NeedsHash a  Maybe GovActionID
getHash {NoConfidence}           h = just h
getHash {UpdateCommittee _ _ _}  h = just h
getHash {NewConstitution _ _}    h = just h
getHash {TriggerHF _}            h = just h
getHash {ChangePParams _}        h = just h
getHash {TreasuryWdrl _}         _ = nothing
getHash {Info}                   _ = nothing

getHashES : EnactState  GovAction  Maybe GovActionID
getHashES es NoConfidence             = just (es .cc .proj₂)
getHashES es (UpdateCommittee _ _ _)  = just (es .cc .proj₂)
getHashES es (NewConstitution _ _)    = just (es .constitution .proj₂)
getHashES es (TriggerHF _)            = just (es .pv .proj₂)
getHashES es (ChangePParams _)        = just (es .pparams .proj₂)
getHashES es (TreasuryWdrl _)         = nothing
getHashES es Info                     = nothing
\end{code}
\emph{Type of the ENACT transition system}
\begin{code}[hide]
data
\end{code}
\begin{code}
  _⊢_⇀⦇_,ENACT⦈_ : EnactEnv  EnactState  GovAction  EnactState  Type
\end{code}
\end{AgdaMultiCode}
\caption{Types and function used for the ENACT transition system}
\label{fig:enact-defs}
\end{figure*}
\begin{code}[hide]
open EnactState

private variable
  s : EnactState
  up : PParamsUpdate
  new : Credential  Epoch
  rem :  Credential
  q : 
  dh : DocHash
  sh : Maybe ScriptHash
  v : ProtVer
  wdrl : RwdAddr  Coin
  t : Coin
  gid : GovActionID
  e : Epoch

instance
  _ = +-0-monoid
\end{code}

Figures~\ref{fig:sts:enact} and~\ref{fig:sts:enact-cont} define the rules of the ENACT transition
system. Usually no preconditions are checked and the state is simply
updated (including the \GovActionID for the hash protection scheme, if
required). The exceptions are \UpdateCommittee and \TreasuryWdrl:
\begin{itemize}
\item \UpdateCommittee requires that maximum terms are respected, and
\item \TreasuryWdrl requires that the treasury is able to cover the sum of all withdrawals (old and new).
\end{itemize}

\begin{figure*}[h]
\begin{AgdaMultiCode}
\begin{code}[hide]
open PParams using (ccMaxTermLength)
open EnactState using (cc)
data _⊢_⇀⦇_,ENACT⦈_ where
\end{code}
\begin{code}
  Enact-NoConf :
    ───────────────────────────────────────
     gid , t , e ⟧ᵉ  s ⇀⦇ NoConfidence ,ENACT⦈ record s { cc = nothing , gid }

  Enact-NewComm : let old      = maybe proj₁  (s .cc .proj₁)
                      maxTerm  = s .pparams .proj₁ .ccMaxTermLength +ᵉ e
                  in
    ∀[ term  range new ] term  maxTerm
    ───────────────────────────────────────
     gid , t , e ⟧ᵉ  s ⇀⦇ UpdateCommittee new rem q ,ENACT⦈
      record s { cc = just ((new ∪ˡ old)  rem  , q) , gid }

  Enact-NewConst :
    ───────────────────────────────────────
     gid , t , e ⟧ᵉ  s ⇀⦇ NewConstitution dh sh ,ENACT⦈ record s { constitution = (dh , sh) , gid }
\end{code}
\end{AgdaMultiCode}
\caption{ENACT transition system}
\label{fig:sts:enact}
\end{figure*}
\begin{figure*}[ht]
\begin{AgdaMultiCode}
\begin{code}
  Enact-HF :
    ───────────────────────────────────────
     gid , t , e ⟧ᵉ  s ⇀⦇ TriggerHF v ,ENACT⦈ record s { pv = v , gid }

  Enact-PParams :
    ───────────────────────────────────────
     gid , t , e ⟧ᵉ  s ⇀⦇ ChangePParams up ,ENACT⦈
      record s { pparams = applyUpdate (s .pparams .proj₁) up , gid }

  Enact-Wdrl : let newWdrls = s .withdrawals ∪⁺ wdrl in
    ∑[ x  newWdrls ] x  t
    ───────────────────────────────────────
     gid , t , e ⟧ᵉ  s ⇀⦇ TreasuryWdrl wdrl ,ENACT⦈ record s { withdrawals = newWdrls }

  Enact-Info :
    ───────────────────────────────────────
     gid , t , e ⟧ᵉ  s ⇀⦇ Info ,ENACT⦈ s
\end{code}
\end{AgdaMultiCode}
\caption{ENACT transition system (continued)}
\label{fig:sts:enact-cont}
\end{figure*}