{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fno-specialize #-}

module Hydra.Contract.HeadState where

import PlutusTx.Prelude

import GHC.Generics (Generic)
import Hydra.Data.ContestationPeriod (ContestationPeriod)
import Hydra.Data.Party (Party)
import PlutusLedgerApi.V3 (CurrencySymbol, POSIXTime, PubKeyHash, TxOutRef)
import PlutusTx qualified
import Text.Show (Show)

type SnapshotNumber = Integer

type SnapshotVersion = Integer

type Hash = BuiltinByteString

type Signature = BuiltinByteString

-- | Sub-type for the open state-machine state.
data OpenDatum = OpenDatum
  { OpenDatum -> CurrencySymbol
headId :: CurrencySymbol
  -- ^ Spec: cid
  , OpenDatum -> [Party]
parties :: [Party]
  -- ^ Spec: kH
  , OpenDatum -> ContestationPeriod
contestationPeriod :: ContestationPeriod
  -- ^ Spec: T
  , OpenDatum -> SnapshotVersion
version :: SnapshotVersion
  -- ^ Spec: v
  , OpenDatum -> Hash
utxoHash :: Hash
  -- ^ Spec: η
  }
  deriving stock ((forall x. OpenDatum -> Rep OpenDatum x)
-> (forall x. Rep OpenDatum x -> OpenDatum) -> Generic OpenDatum
forall x. Rep OpenDatum x -> OpenDatum
forall x. OpenDatum -> Rep OpenDatum x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. OpenDatum -> Rep OpenDatum x
from :: forall x. OpenDatum -> Rep OpenDatum x
$cto :: forall x. Rep OpenDatum x -> OpenDatum
to :: forall x. Rep OpenDatum x -> OpenDatum
Generic, Int -> OpenDatum -> ShowS
[OpenDatum] -> ShowS
OpenDatum -> String
(Int -> OpenDatum -> ShowS)
-> (OpenDatum -> String)
-> ([OpenDatum] -> ShowS)
-> Show OpenDatum
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> OpenDatum -> ShowS
showsPrec :: Int -> OpenDatum -> ShowS
$cshow :: OpenDatum -> String
show :: OpenDatum -> String
$cshowList :: [OpenDatum] -> ShowS
showList :: [OpenDatum] -> ShowS
Show)

PlutusTx.unstableMakeIsData ''OpenDatum

-- | Sub-type for the closed state-machine state.
data ClosedDatum = ClosedDatum
  { ClosedDatum -> CurrencySymbol
headId :: CurrencySymbol
  -- ^ Spec: cid
  , ClosedDatum -> [Party]
parties :: [Party]
  -- ^ Spec: kH
  , ClosedDatum -> ContestationPeriod
contestationPeriod :: ContestationPeriod
  -- ^ Spec: T
  , ClosedDatum -> SnapshotVersion
version :: SnapshotVersion
  -- ^ Spec: v
  , ClosedDatum -> SnapshotVersion
snapshotNumber :: SnapshotNumber
  -- ^ Spec: s
  , ClosedDatum -> Hash
utxoHash :: Hash
  -- ^ Spec: η. Digest of snapshotted UTxO
  , ClosedDatum -> Hash
deltaUTxOHash :: Hash
  -- ^ Spec: ηΔ. Digest of UTxO still to be distributed
  , ClosedDatum -> [PubKeyHash]
contesters :: [PubKeyHash]
  -- ^ Spec: C
  , ClosedDatum -> POSIXTime
contestationDeadline :: POSIXTime
  -- ^ Spec: tfinal
  }
  deriving stock ((forall x. ClosedDatum -> Rep ClosedDatum x)
-> (forall x. Rep ClosedDatum x -> ClosedDatum)
-> Generic ClosedDatum
forall x. Rep ClosedDatum x -> ClosedDatum
forall x. ClosedDatum -> Rep ClosedDatum x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ClosedDatum -> Rep ClosedDatum x
from :: forall x. ClosedDatum -> Rep ClosedDatum x
$cto :: forall x. Rep ClosedDatum x -> ClosedDatum
to :: forall x. Rep ClosedDatum x -> ClosedDatum
Generic, Int -> ClosedDatum -> ShowS
[ClosedDatum] -> ShowS
ClosedDatum -> String
(Int -> ClosedDatum -> ShowS)
-> (ClosedDatum -> String)
-> ([ClosedDatum] -> ShowS)
-> Show ClosedDatum
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ClosedDatum -> ShowS
showsPrec :: Int -> ClosedDatum -> ShowS
$cshow :: ClosedDatum -> String
show :: ClosedDatum -> String
$cshowList :: [ClosedDatum] -> ShowS
showList :: [ClosedDatum] -> ShowS
Show)

PlutusTx.unstableMakeIsData ''ClosedDatum

data State
  = Initial
      { State -> ContestationPeriod
contestationPeriod :: ContestationPeriod
      , State -> [Party]
parties :: [Party]
      , State -> CurrencySymbol
headId :: CurrencySymbol
      , State -> TxOutRef
seed :: TxOutRef
      }
  | Open OpenDatum
  | Closed ClosedDatum
  | Final
  deriving stock ((forall x. State -> Rep State x)
-> (forall x. Rep State x -> State) -> Generic State
forall x. Rep State x -> State
forall x. State -> Rep State x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. State -> Rep State x
from :: forall x. State -> Rep State x
$cto :: forall x. Rep State x -> State
to :: forall x. Rep State x -> State
Generic, Int -> State -> ShowS
[State] -> ShowS
State -> String
(Int -> State -> ShowS)
-> (State -> String) -> ([State] -> ShowS) -> Show State
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> State -> ShowS
showsPrec :: Int -> State -> ShowS
$cshow :: State -> String
show :: State -> String
$cshowList :: [State] -> ShowS
showList :: [State] -> ShowS
Show)

PlutusTx.unstableMakeIsData ''State

-- | Sub-type for close transition with auxiliary data as needed.
data CloseRedeemer
  = -- | Intial snapshot is used to close.
    CloseInitial
  | -- | Closing snapshot refers to the current state version
    CloseUnused
      { CloseRedeemer -> [Hash]
signature :: [Signature]
      -- ^ Multi-signature of a snapshot ξ
      }
  | -- | Closing snapshot refers to the previous state version
    CloseUsed
      { signature :: [Signature]
      -- ^ Multi-signature of a snapshot ξ
      , CloseRedeemer -> Hash
alreadyDecommittedUTxOHash :: Hash
      -- ^ UTxO which was already decommitted ηω
      }
  deriving stock (Int -> CloseRedeemer -> ShowS
[CloseRedeemer] -> ShowS
CloseRedeemer -> String
(Int -> CloseRedeemer -> ShowS)
-> (CloseRedeemer -> String)
-> ([CloseRedeemer] -> ShowS)
-> Show CloseRedeemer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CloseRedeemer -> ShowS
showsPrec :: Int -> CloseRedeemer -> ShowS
$cshow :: CloseRedeemer -> String
show :: CloseRedeemer -> String
$cshowList :: [CloseRedeemer] -> ShowS
showList :: [CloseRedeemer] -> ShowS
Show, (forall x. CloseRedeemer -> Rep CloseRedeemer x)
-> (forall x. Rep CloseRedeemer x -> CloseRedeemer)
-> Generic CloseRedeemer
forall x. Rep CloseRedeemer x -> CloseRedeemer
forall x. CloseRedeemer -> Rep CloseRedeemer x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CloseRedeemer -> Rep CloseRedeemer x
from :: forall x. CloseRedeemer -> Rep CloseRedeemer x
$cto :: forall x. Rep CloseRedeemer x -> CloseRedeemer
to :: forall x. Rep CloseRedeemer x -> CloseRedeemer
Generic)

PlutusTx.unstableMakeIsData ''CloseRedeemer

-- | Sub-type for contest transition with auxiliary data as needed.
data ContestRedeemer
  = -- | Contesting snapshot refers to the current state version
    ContestCurrent
      { ContestRedeemer -> [Hash]
signature :: [Signature]
      -- ^ Multi-signature of a snapshot ξ
      }
  | -- | Contesting snapshot refers to the previous state version
    ContestOutdated
      { signature :: [Signature]
      -- ^ Multi-signature of a snapshot ξ
      , ContestRedeemer -> Hash
alreadyDecommittedUTxOHash :: Hash
      -- ^ UTxO which was already decommitted ηω
      }
  deriving stock (Int -> ContestRedeemer -> ShowS
[ContestRedeemer] -> ShowS
ContestRedeemer -> String
(Int -> ContestRedeemer -> ShowS)
-> (ContestRedeemer -> String)
-> ([ContestRedeemer] -> ShowS)
-> Show ContestRedeemer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ContestRedeemer -> ShowS
showsPrec :: Int -> ContestRedeemer -> ShowS
$cshow :: ContestRedeemer -> String
show :: ContestRedeemer -> String
$cshowList :: [ContestRedeemer] -> ShowS
showList :: [ContestRedeemer] -> ShowS
Show, (forall x. ContestRedeemer -> Rep ContestRedeemer x)
-> (forall x. Rep ContestRedeemer x -> ContestRedeemer)
-> Generic ContestRedeemer
forall x. Rep ContestRedeemer x -> ContestRedeemer
forall x. ContestRedeemer -> Rep ContestRedeemer x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ContestRedeemer -> Rep ContestRedeemer x
from :: forall x. ContestRedeemer -> Rep ContestRedeemer x
$cto :: forall x. Rep ContestRedeemer x -> ContestRedeemer
to :: forall x. Rep ContestRedeemer x -> ContestRedeemer
Generic)

PlutusTx.unstableMakeIsData ''ContestRedeemer

-- | Sub-type for increment transition
-- TODO: add more fields as needed.
data IncrementRedeemer = IncrementRedeemer
  deriving stock (Int -> IncrementRedeemer -> ShowS
[IncrementRedeemer] -> ShowS
IncrementRedeemer -> String
(Int -> IncrementRedeemer -> ShowS)
-> (IncrementRedeemer -> String)
-> ([IncrementRedeemer] -> ShowS)
-> Show IncrementRedeemer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> IncrementRedeemer -> ShowS
showsPrec :: Int -> IncrementRedeemer -> ShowS
$cshow :: IncrementRedeemer -> String
show :: IncrementRedeemer -> String
$cshowList :: [IncrementRedeemer] -> ShowS
showList :: [IncrementRedeemer] -> ShowS
Show, (forall x. IncrementRedeemer -> Rep IncrementRedeemer x)
-> (forall x. Rep IncrementRedeemer x -> IncrementRedeemer)
-> Generic IncrementRedeemer
forall x. Rep IncrementRedeemer x -> IncrementRedeemer
forall x. IncrementRedeemer -> Rep IncrementRedeemer x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. IncrementRedeemer -> Rep IncrementRedeemer x
from :: forall x. IncrementRedeemer -> Rep IncrementRedeemer x
$cto :: forall x. Rep IncrementRedeemer x -> IncrementRedeemer
to :: forall x. Rep IncrementRedeemer x -> IncrementRedeemer
Generic)

PlutusTx.unstableMakeIsData ''IncrementRedeemer

-- | Sub-type for decrement transition with auxiliary data as needed.
data DecrementRedeemer = DecrementRedeemer
  { DecrementRedeemer -> [Hash]
signature :: [Signature]
  -- ^ Spec: ξ
  , DecrementRedeemer -> SnapshotVersion
snapshotNumber :: SnapshotNumber
  -- ^ Spec: s
  , DecrementRedeemer -> SnapshotVersion
numberOfDecommitOutputs :: Integer
  -- ^ Spec: m
  }
  deriving stock (Int -> DecrementRedeemer -> ShowS
[DecrementRedeemer] -> ShowS
DecrementRedeemer -> String
(Int -> DecrementRedeemer -> ShowS)
-> (DecrementRedeemer -> String)
-> ([DecrementRedeemer] -> ShowS)
-> Show DecrementRedeemer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DecrementRedeemer -> ShowS
showsPrec :: Int -> DecrementRedeemer -> ShowS
$cshow :: DecrementRedeemer -> String
show :: DecrementRedeemer -> String
$cshowList :: [DecrementRedeemer] -> ShowS
showList :: [DecrementRedeemer] -> ShowS
Show, (forall x. DecrementRedeemer -> Rep DecrementRedeemer x)
-> (forall x. Rep DecrementRedeemer x -> DecrementRedeemer)
-> Generic DecrementRedeemer
forall x. Rep DecrementRedeemer x -> DecrementRedeemer
forall x. DecrementRedeemer -> Rep DecrementRedeemer x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. DecrementRedeemer -> Rep DecrementRedeemer x
from :: forall x. DecrementRedeemer -> Rep DecrementRedeemer x
$cto :: forall x. Rep DecrementRedeemer x -> DecrementRedeemer
to :: forall x. Rep DecrementRedeemer x -> DecrementRedeemer
Generic)

PlutusTx.unstableMakeIsData ''DecrementRedeemer

data Input
  = CollectCom
  | Increment IncrementRedeemer
  | Decrement DecrementRedeemer
  | Close CloseRedeemer
  | Contest ContestRedeemer
  | Abort
  | Fanout
      { Input -> SnapshotVersion
numberOfFanoutOutputs :: Integer
      -- ^ Spec: m
      , Input -> SnapshotVersion
numberOfDecommitOutputs :: Integer
      -- ^ Spec: n
      }
  deriving stock ((forall x. Input -> Rep Input x)
-> (forall x. Rep Input x -> Input) -> Generic Input
forall x. Rep Input x -> Input
forall x. Input -> Rep Input x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Input -> Rep Input x
from :: forall x. Input -> Rep Input x
$cto :: forall x. Rep Input x -> Input
to :: forall x. Rep Input x -> Input
Generic, Int -> Input -> ShowS
[Input] -> ShowS
Input -> String
(Int -> Input -> ShowS)
-> (Input -> String) -> ([Input] -> ShowS) -> Show Input
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Input -> ShowS
showsPrec :: Int -> Input -> ShowS
$cshow :: Input -> String
show :: Input -> String
$cshowList :: [Input] -> ShowS
showList :: [Input] -> ShowS
Show)

PlutusTx.unstableMakeIsData ''Input