Computational

{-# OPTIONS --safe #-}

open import Ledger.Dijkstra.Specification.Gov.Base
open import Ledger.Dijkstra.Specification.Transaction using (TransactionStructure)

module Ledger.Dijkstra.Specification.Gov.Properties.Computational
  (txs : _) (open TransactionStructure txs using (govStructure))
  (open GovStructure govStructure hiding (epoch)) where

open import Ledger.Prelude hiding (Any; any?)

open import Axiom.Set.Properties

open import Ledger.Core.Specification.ProtocolVersion
open import Ledger.Dijkstra.Specification.Enact govStructure
open import Ledger.Dijkstra.Specification.Gov govStructure
open import Ledger.Dijkstra.Specification.Gov.Actions govStructure hiding (yes; no)
open import Ledger.Dijkstra.Specification.Ratify govStructure

import Data.List.Membership.Propositional as P
open import Data.List.Membership.Propositional.Properties
open import Data.List.Relation.Unary.All using (all?; All)
open import Data.List.Relation.Unary.Any hiding (map)
open import Data.List.Relation.Unary.Unique.Propositional
open import Data.Maybe.Properties
open import Relation.Binary using (IsEquivalence)

open import Tactic.Defaults
open import stdlib-meta.Tactic.GenError

open Equivalence
open Inverse

lookupActionId :
  (pparams  : PParams)
  (role     : GovRole)
  (aid      : GovActionID)
  (epoch    : Epoch)
  (s        : GovState)
   Dec (Any ( λ (aid' , ast)   aid  aid'
                                 × canVote pparams (GovActionOf ast) role
                                 × ¬ (expired epoch ast) ) s)

lookupActionId pparams role aid epoch =
  let  instance _ = λ {e ga}   (expired? e ga)
  in   any? λ _  ¿ _ ¿


private
  isUpdateCommittee : (a : GovAction)
     Dec (∃[ new ] ∃[ rem ] ∃[ q ] a  $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1087}{\htmlId{1854}{\htmlClass{InductiveConstructor}{\text{UpdateCommittee}}}}\, \\ \,\htmlId{1872}{\htmlClass{Symbol}{\text{(}}}\,\,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#1826}{\htmlId{1873}{\htmlClass{Bound}{\text{new}}}}\, , \,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#1835}{\htmlId{1879}{\htmlClass{Bound}{\text{rem}}}}\, , \,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#1844}{\htmlId{1885}{\htmlClass{Bound}{\text{q}}}}\,\,\htmlId{1886}{\htmlClass{Symbol}{\text{)}}}\, \end{pmatrix}$)
  -- (new , rem , q) : (Credential ⇀ Epoch) × ℙ Credential × ℚ

  isUpdateCommittee $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1049}{\htmlId{1979}{\htmlClass{InductiveConstructor}{\text{NoConfidence}}}}\,       \\ \,\htmlId{2000}{\htmlClass{Symbol}{\text{\_}}}\,                \end{pmatrix}$ = no λ()
  isUpdateCommittee $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1087}{\htmlId{2052}{\htmlClass{InductiveConstructor}{\text{UpdateCommittee}}}}\,    \\ \,\htmlId{2073}{\htmlClass{Symbol}{\text{(}}}\,\,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#2074}{\htmlId{2074}{\htmlClass{Bound}{\text{new}}}}\, , \,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#2080}{\htmlId{2080}{\htmlClass{Bound}{\text{rem}}}}\, , \,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#2086}{\htmlId{2086}{\htmlClass{Bound}{\text{q}}}}\,\,\htmlId{2087}{\htmlClass{Symbol}{\text{)}}}\,  \end{pmatrix}$ = yes (new , rem , q , refl)
  isUpdateCommittee $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1125}{\htmlId{2145}{\htmlClass{InductiveConstructor}{\text{NewConstitution}}}}\,    \\ \,\htmlId{2166}{\htmlClass{Symbol}{\text{\_}}}\,                \end{pmatrix}$ = no λ()
  isUpdateCommittee $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1163}{\htmlId{2218}{\htmlClass{InductiveConstructor}{\text{TriggerHardFork}}}}\,    \\ \,\htmlId{2239}{\htmlClass{Symbol}{\text{\_}}}\,                \end{pmatrix}$ = no λ()
  isUpdateCommittee $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1201}{\htmlId{2291}{\htmlClass{InductiveConstructor}{\text{ChangePParams}}}}\,      \\ \,\htmlId{2312}{\htmlClass{Symbol}{\text{\_}}}\,                \end{pmatrix}$ = no λ()
  isUpdateCommittee $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1239}{\htmlId{2364}{\htmlClass{InductiveConstructor}{\text{TreasuryWithdrawal}}}}\, \\ \,\htmlId{2385}{\htmlClass{Symbol}{\text{\_}}}\,                \end{pmatrix}$ = no λ()
  isUpdateCommittee $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1277}{\htmlId{2437}{\htmlClass{InductiveConstructor}{\text{Info}}}}\,               \\ \,\htmlId{2458}{\htmlClass{Symbol}{\text{\_}}}\,                \end{pmatrix}$ = no λ()

  hasPrev : (ast : GovActionState) (v : ProtVer)
     Dec (∃[ v' ] (GovActionOf ast)  $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1163}{\htmlId{2579}{\htmlClass{InductiveConstructor}{\text{TriggerHardFork}}}}\, \\ \,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#2552}{\htmlId{2597}{\htmlClass{Bound}{\text{v'}}}}\, \end{pmatrix}$ × pvCanFollow v' v)

  hasPrev record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1049}{\htmlId{2655}{\htmlClass{InductiveConstructor}{\text{NoConfidence}}}}\,        \\ \,\htmlId{2677}{\htmlClass{Symbol}{\text{\_}}}\,   \end{pmatrix}$} v = no λ ()
  hasPrev record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1087}{\htmlId{2728}{\htmlClass{InductiveConstructor}{\text{UpdateCommittee}}}}\,     \\ \,\htmlId{2750}{\htmlClass{Symbol}{\text{\_}}}\,   \end{pmatrix}$} v = no λ ()
  hasPrev record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1125}{\htmlId{2801}{\htmlClass{InductiveConstructor}{\text{NewConstitution}}}}\,     \\ \,\htmlId{2823}{\htmlClass{Symbol}{\text{\_}}}\,   \end{pmatrix}$} v = no λ ()
  hasPrev record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1163}{\htmlId{2874}{\htmlClass{InductiveConstructor}{\text{TriggerHardFork}}}}\,     \\ \,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#2896}{\htmlId{2896}{\htmlClass{Bound}{\text{v'}}}}\,  \end{pmatrix}$} v =
    case pvCanFollow? {v'} {v} of λ where
      (yes p)  yes (-, refl , p)
      (no ¬p)  no   where (_ , refl , h)  ¬p h)
  hasPrev record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1201}{\htmlId{3067}{\htmlClass{InductiveConstructor}{\text{ChangePParams}}}}\,       \\ \,\htmlId{3089}{\htmlClass{Symbol}{\text{\_}}}\,   \end{pmatrix}$} v = no λ ()
  hasPrev record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1239}{\htmlId{3140}{\htmlClass{InductiveConstructor}{\text{TreasuryWithdrawal}}}}\,  \\ \,\htmlId{3162}{\htmlClass{Symbol}{\text{\_}}}\,   \end{pmatrix}$} v = no λ ()
  hasPrev record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1277}{\htmlId{3213}{\htmlClass{InductiveConstructor}{\text{Info}}}}\,                \\ \,\htmlId{3235}{\htmlClass{Symbol}{\text{\_}}}\,   \end{pmatrix}$} v = no λ ()


opaque
  unfolding validHFAction isRegistered

  instance
    validHFAction? :  {p : GovProposal} {s : GovState} {e : EnactState}
       validHFAction p s e 

    validHFAction?  {record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1049}{\htmlId{3461}{\htmlClass{InductiveConstructor}{\text{NoConfidence}}}}\,     \\ \,\htmlId{3480}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$}} = Dec-⊤
    validHFAction?  {record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1087}{\htmlId{3537}{\htmlClass{InductiveConstructor}{\text{UpdateCommittee}}}}\,  \\ \,\htmlId{3556}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$}} = Dec-⊤
    validHFAction?  {record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1125}{\htmlId{3613}{\htmlClass{InductiveConstructor}{\text{NewConstitution}}}}\,  \\ \,\htmlId{3632}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$}} = Dec-⊤
    validHFAction?  {record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1163}{\htmlId{3689}{\htmlClass{InductiveConstructor}{\text{TriggerHardFork}}}}\,  \\ \,\href{Ledger.Dijkstra.Specification.Gov.Properties.Computational.html#3708}{\htmlId{3708}{\htmlClass{Bound}{\text{v}}}}\, \end{pmatrix}$ ; prevAction = prev }}
                    {s} {record { pv = (v' , aid') }}
      with    aid'  prev ×-dec pvCanFollow? {v'} {v}
           |  any?  (aid , x)  aid  prev ×-dec hasPrev x v) s

    ... | yes p  | _       =  yes (inj₁ p)
    ... | no _   | yes p with ((aid , x) , x∈xs , (refl , v , h))P.find p
                           =  yes (inj₂ (x , v , to ∈-fromList x∈xs , h))
    ... | no ¬p₁ | no ¬p₂  =  no λ  { (inj₁ x)  ¬p₁ x
                                     ; (inj₂ (s , v , (h₁ , h₂ , h₃)))  ¬p₂ $
                                       ∃∈-Any  ( (prev , s)
                                               , from ∈-fromList h₁ , refl , (v , h₂ , h₃)
                                               )
                                     }
    validHFAction? {record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1201}{\htmlId{4522}{\htmlClass{InductiveConstructor}{\text{ChangePParams}}}}\,       \\ \,\htmlId{4544}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$}} = Dec-⊤
    validHFAction? {record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1239}{\htmlId{4600}{\htmlClass{InductiveConstructor}{\text{TreasuryWithdrawal}}}}\,  \\ \,\htmlId{4622}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$}} = Dec-⊤
    validHFAction? {record { action = $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#1277}{\htmlId{4678}{\htmlClass{InductiveConstructor}{\text{Info}}}}\,                \\ \,\htmlId{4700}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$}} = Dec-⊤

  isRegistered? :  Γ v  Dec (isRegistered Γ v)
  isRegistered? _ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#851}{\htmlId{4786}{\htmlClass{InductiveConstructor}{\text{CC}}}}\,   \\ \,\htmlId{4793}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$ = ¿ _  _ ¿
  isRegistered? _ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#854}{\htmlId{4831}{\htmlClass{InductiveConstructor}{\text{DRep}}}}\, \\ \,\htmlId{4838}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$ = ¿ _  _ ¿
  isRegistered? _ $\begin{pmatrix} \,\href{Ledger.Dijkstra.Specification.Gov.Actions.html#859}{\htmlId{4876}{\htmlClass{InductiveConstructor}{\text{SPO}}}}\,  \\ \,\htmlId{4883}{\htmlClass{Symbol}{\text{\_}}}\, \end{pmatrix}$ = ¿ _  _ ¿

open GovVoter

instance
  Computational-GOV : Computational _⊢_⇀⦇_,GOV⦈_ String
  Computational-GOV = record {Go} where
    module Go (Γk : GovEnv × ) (s : GovState) where
      Γ : GovEnv
      Γ = proj₁ Γk

      k : 
      k = proj₂ Γk

      module GoVote sig where
        open GovVote sig

        computeProof = case lookupActionId (PParamsOf Γ) (gvRole voter) gid (EpochOf Γ) s ,′ isRegistered? Γ voter of λ where
            (yes p , yes p')  case Any↔ .from p of λ where
              (_ , mem , refl , cV , ¬exp)  success (_ , GOV-Vote (∈-fromList .to mem , cV , p' , ¬exp))
            (yes _ , no ¬p)  failure (genErrors ¬p)
            (no ¬p , _    )  failure (genErrors ¬p)

        completeness :  s'  (Γ , k)  s ⇀⦇ inj₁ sig ,GOV⦈ s'  map proj₁ computeProof  success s'
        completeness s' (GOV-Vote {ast = ast} (mem , cV , reg , ¬expired))
          with lookupActionId (PParamsOf Γ) (gvRole voter) gid (EpochOf Γ) s | isRegistered? Γ voter
        ... | no ¬p | _ = ⊥-elim (¬p (Any↔ .to (_ , ∈-fromList .from mem , refl , cV , ¬expired)))
        ... | yes _ | no ¬p = ⊥-elim $ ¬p reg
        ... | yes p | yes q with Any↔ .from p
        ... | ((_ , ast') , mem , refl , cV) = refl

      module GoProp prop where
        open PParams (PParamsOf Γ)

        instance
          Dec-actionWellFormed = actionWellFormed?
          Dec-actionValid = actionValid?
        {-# INCOHERENT Dec-actionWellFormed #-}
        {-# INCOHERENT Dec-actionValid #-}

        H = ¿ actionWellFormed (GovActionOf prop)
            × actionValid (RewardCredentialsOf Γ) (PolicyOf prop) (GovEnv.ppolicy Γ) (EpochOf Γ) (GovActionOf prop)
            × (DepositOf prop)  govActionDeposit
            × validHFAction prop s (EnactStateOf Γ)
            × hasParent' (EnactStateOf Γ) s ((GovActionOf prop) .gaType) (GovProposal.prevAction prop)
            × NetworkIdOf (RewardAddressOf prop)  NetworkId
            × CredentialOf (RewardAddressOf prop)  (RewardCredentialsOf Γ) ¿
            ,′ isUpdateCommittee (GovActionOf prop)

        pattern gov-propose  {zz} xx = GOV-Propose {_} {_} {_} {_} {_} {_} {_} {_} {_} {zz} xx
        -- The inferred variables in both cases below are
        -- { Γ } { RewardAddressOf prop } { GovActionOf prop } { AnchorOf prop } { PolicyOf prop } { DepositOf prop } { (GovProposal.prevAction prop) } { s } { k }

        computeProof = case H of λ where
          (yes (wf , av , dep , vHFA , HasParent' en , goodAddr , regReturn) , yes (new , rem , q , refl)) 
            case ¿ ∀[ e  range new ] (EpochOf Γ) < e × dom new  rem ≡ᵉ  ¿ of λ where
              (yes newOk)  success (-, gov-propose {(new , rem , q)} (wf , av , dep , vHFA , en , goodAddr , regReturn))
              (no ¬p)      failure (genErrors ¬p)
          (yes (wf , av , dep , vHFA , HasParent' en , goodAddr , returnReg) , no notNewComm)  success
            (-, gov-propose {(GovActionOf prop) .gaData} (wf , av , dep , vHFA , en , goodAddr , returnReg))
          (no ¬p , _)  failure (genErrors ¬p)

        completeness :  s'  (Γ , k)  s ⇀⦇ inj₂ prop ,GOV⦈ s'  map proj₁ computeProof  success s'
        completeness s' (GOV-Propose (wf , av , dep , vHFA , en , goodAddr)) with H
        ... | (no ¬p , _) = ⊥-elim (¬p (wf , av , dep , vHFA , HasParent' en , goodAddr))
        ... | (yes (_ , _ , _ , _ , HasParent' _ , _) , no notNewComm) = refl
        ... | (yes (_ , (_ , (av₁ , av₂)) , _ , _ , HasParent' _ , _) , yes (new , rem , q , refl))
          rewrite dec-yes ¿ ∀[ e  range new ] (EpochOf Γ) < e × dom new  rem ≡ᵉ  ¿  { x  av₁ x , av₂ }) .proj₂ = refl

      computeProof : (sig : GovVote  GovProposal)  _
      computeProof (inj₁ s) = GoVote.computeProof s
      computeProof (inj₂ s) = GoProp.computeProof s

      completeness :  sig s'  (Γ , k)  s ⇀⦇ sig ,GOV⦈ s'  _
      completeness (inj₁ s) = GoVote.completeness s
      completeness (inj₂ s) = GoProp.completeness s

Computational-GOVS : Computational _⊢_⇀⦇_,GOVS⦈_ String
Computational-GOVS = it

allEnactable-singleton : {aid : GovActionID} {s : GovActionState} {es : EnactState}
   getHash (GovActionState.prevAction s)  getHashES es (GovActionTypeOf s)
   allEnactable es [ (aid , s) ]
allEnactable-singleton {aid} {s} {es} eq = helper All.∷ All.[]
  where
    module ≡ᵉ = IsEquivalence (≡ᵉ-isEquivalence th)

    helper : enactable es (getAidPairsList [ (aid , s) ]) (aid , s)
    helper with getHashES es (GovActionTypeOf s) | getHash (GovActionState.prevAction s)
    ... | just x | just x' with refl <- just-injective eq =
      [ (aid , x) ] , proj₁ ≡ᵉ.refl , All.[]  [] , inj₁ (refl , refl)
    ... | just x | nothing = case eq of λ ()
    ... | nothing | _ = _