{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-ambiguous-fields #-}

module Hydra.HeadLogic.State where

import Hydra.Prelude

import Data.Map qualified as Map
import Hydra.Chain.ChainState (ChainSlot, ChainStateType)
import Hydra.Tx (
  HeadId,
  HeadParameters,
  HeadSeed,
  IsTx (..),
  Party,
 )
import Hydra.Tx.Crypto (Signature)
import Hydra.Tx.IsTx (ArbitraryIsTx)
import Hydra.Tx.Snapshot (
  ConfirmedSnapshot,
  Snapshot (..),
  SnapshotNumber,
  SnapshotVersion,
 )

-- | The main state of the Hydra protocol state machine. It holds both, the
-- overall protocol state, but also the off-chain 'CoordinatedHeadState'.
--
-- Each of the sub-types (InitialState, OpenState, etc.) contain a black-box
-- 'chainState' corresponding to the 'ChainEvent' that has been observed leading
-- to the state.
--
-- Note that rollbacks are currently not fully handled in the head logic and
-- only this internal chain state gets replaced with the "rolled back to"
-- version.
--
-- TODO: chainState would actualy not be needed in the HeadState anymore as we
-- do not persist the 'HeadState' and not access it in the HeadLogic either.
data HeadState tx
  = Idle (IdleState tx)
  | Initial (InitialState tx)
  | Open (OpenState tx)
  | Closed (ClosedState tx)
  deriving stock ((forall x. HeadState tx -> Rep (HeadState tx) x)
-> (forall x. Rep (HeadState tx) x -> HeadState tx)
-> Generic (HeadState tx)
forall x. Rep (HeadState tx) x -> HeadState tx
forall x. HeadState tx -> Rep (HeadState tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall tx x. Rep (HeadState tx) x -> HeadState tx
forall tx x. HeadState tx -> Rep (HeadState tx) x
$cfrom :: forall tx x. HeadState tx -> Rep (HeadState tx) x
from :: forall x. HeadState tx -> Rep (HeadState tx) x
$cto :: forall tx x. Rep (HeadState tx) x -> HeadState tx
to :: forall x. Rep (HeadState tx) x -> HeadState tx
Generic)

instance (ArbitraryIsTx tx, Arbitrary (ChainStateType tx)) => Arbitrary (HeadState tx) where
  arbitrary :: Gen (HeadState tx)
arbitrary = Gen (HeadState tx)
forall a.
(Generic a, GA UnsizedOpts (Rep a),
 UniformWeight (Weights_ (Rep a))) =>
Gen a
genericArbitrary

deriving stock instance (IsTx tx, Eq (ChainStateType tx)) => Eq (HeadState tx)
deriving stock instance (IsTx tx, Show (ChainStateType tx)) => Show (HeadState tx)
deriving anyclass instance (IsTx tx, ToJSON (ChainStateType tx)) => ToJSON (HeadState tx)
deriving anyclass instance (IsTx tx, FromJSON (ChainStateType tx)) => FromJSON (HeadState tx)

-- | Update the chain state in any 'HeadState'.
setChainState :: ChainStateType tx -> HeadState tx -> HeadState tx
setChainState :: forall tx. ChainStateType tx -> HeadState tx -> HeadState tx
setChainState ChainStateType tx
chainState = \case
  Idle IdleState tx
st -> IdleState tx -> HeadState tx
forall tx. IdleState tx -> HeadState tx
Idle IdleState tx
st{chainState}
  Initial InitialState tx
st -> InitialState tx -> HeadState tx
forall tx. InitialState tx -> HeadState tx
Initial InitialState tx
st{chainState}
  Open OpenState tx
st -> OpenState tx -> HeadState tx
forall tx. OpenState tx -> HeadState tx
Open OpenState tx
st{chainState}
  Closed ClosedState tx
st -> ClosedState tx -> HeadState tx
forall tx. ClosedState tx -> HeadState tx
Closed ClosedState tx
st{chainState}

-- | Get the head parameters in any 'HeadState'.
getHeadParameters :: HeadState tx -> Maybe HeadParameters
getHeadParameters :: forall tx. HeadState tx -> Maybe HeadParameters
getHeadParameters = \case
  Idle IdleState tx
_ -> Maybe HeadParameters
forall a. Maybe a
Nothing
  Initial InitialState{HeadParameters
parameters :: HeadParameters
$sel:parameters:InitialState :: forall tx. InitialState tx -> HeadParameters
parameters} -> HeadParameters -> Maybe HeadParameters
forall a. a -> Maybe a
Just HeadParameters
parameters
  Open OpenState{HeadParameters
parameters :: HeadParameters
$sel:parameters:OpenState :: forall tx. OpenState tx -> HeadParameters
parameters} -> HeadParameters -> Maybe HeadParameters
forall a. a -> Maybe a
Just HeadParameters
parameters
  Closed ClosedState{HeadParameters
parameters :: HeadParameters
$sel:parameters:ClosedState :: forall tx. ClosedState tx -> HeadParameters
parameters} -> HeadParameters -> Maybe HeadParameters
forall a. a -> Maybe a
Just HeadParameters
parameters

-- ** Idle

-- | An 'Idle' head only having a chain state with things seen on chain so far.
newtype IdleState tx = IdleState {forall tx. IdleState tx -> ChainStateType tx
chainState :: ChainStateType tx}
  deriving stock ((forall x. IdleState tx -> Rep (IdleState tx) x)
-> (forall x. Rep (IdleState tx) x -> IdleState tx)
-> Generic (IdleState tx)
forall x. Rep (IdleState tx) x -> IdleState tx
forall x. IdleState tx -> Rep (IdleState tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall tx x. Rep (IdleState tx) x -> IdleState tx
forall tx x. IdleState tx -> Rep (IdleState tx) x
$cfrom :: forall tx x. IdleState tx -> Rep (IdleState tx) x
from :: forall x. IdleState tx -> Rep (IdleState tx) x
$cto :: forall tx x. Rep (IdleState tx) x -> IdleState tx
to :: forall x. Rep (IdleState tx) x -> IdleState tx
Generic)

deriving stock instance Eq (ChainStateType tx) => Eq (IdleState tx)
deriving stock instance Show (ChainStateType tx) => Show (IdleState tx)
deriving anyclass instance ToJSON (ChainStateType tx) => ToJSON (IdleState tx)
deriving anyclass instance FromJSON (ChainStateType tx) => FromJSON (IdleState tx)

instance Arbitrary (ChainStateType tx) => Arbitrary (IdleState tx) where
  arbitrary :: Gen (IdleState tx)
arbitrary = Gen (IdleState tx)
forall a.
(Generic a, GA UnsizedOpts (Rep a),
 UniformWeight (Weights_ (Rep a))) =>
Gen a
genericArbitrary

-- ** Initial

-- | An 'Initial' head which already has an identity and is collecting commits.
data InitialState tx = InitialState
  { forall tx. InitialState tx -> HeadParameters
parameters :: HeadParameters
  , forall tx. InitialState tx -> PendingCommits
pendingCommits :: PendingCommits
  , forall tx. InitialState tx -> Committed tx
committed :: Committed tx
  , forall tx. InitialState tx -> ChainStateType tx
chainState :: ChainStateType tx
  , forall tx. InitialState tx -> HeadId
headId :: HeadId
  , forall tx. InitialState tx -> HeadSeed
headSeed :: HeadSeed
  }
  deriving stock ((forall x. InitialState tx -> Rep (InitialState tx) x)
-> (forall x. Rep (InitialState tx) x -> InitialState tx)
-> Generic (InitialState tx)
forall x. Rep (InitialState tx) x -> InitialState tx
forall x. InitialState tx -> Rep (InitialState tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall tx x. Rep (InitialState tx) x -> InitialState tx
forall tx x. InitialState tx -> Rep (InitialState tx) x
$cfrom :: forall tx x. InitialState tx -> Rep (InitialState tx) x
from :: forall x. InitialState tx -> Rep (InitialState tx) x
$cto :: forall tx x. Rep (InitialState tx) x -> InitialState tx
to :: forall x. Rep (InitialState tx) x -> InitialState tx
Generic)

deriving stock instance (IsTx tx, Eq (ChainStateType tx)) => Eq (InitialState tx)
deriving stock instance (IsTx tx, Show (ChainStateType tx)) => Show (InitialState tx)
deriving anyclass instance (IsTx tx, ToJSON (ChainStateType tx)) => ToJSON (InitialState tx)
deriving anyclass instance (IsTx tx, FromJSON (ChainStateType tx)) => FromJSON (InitialState tx)

instance (ArbitraryIsTx tx, Arbitrary (ChainStateType tx)) => Arbitrary (InitialState tx) where
  arbitrary :: Gen (InitialState tx)
arbitrary = do
    HeadParameters
-> PendingCommits
-> Map Party (UTxOType tx)
-> ChainStateType tx
-> HeadId
-> HeadSeed
-> InitialState tx
forall tx.
HeadParameters
-> PendingCommits
-> Committed tx
-> ChainStateType tx
-> HeadId
-> HeadSeed
-> InitialState tx
InitialState
      (HeadParameters
 -> PendingCommits
 -> Map Party (UTxOType tx)
 -> ChainStateType tx
 -> HeadId
 -> HeadSeed
 -> InitialState tx)
-> Gen HeadParameters
-> Gen
     (PendingCommits
      -> Map Party (UTxOType tx)
      -> ChainStateType tx
      -> HeadId
      -> HeadSeed
      -> InitialState tx)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen HeadParameters
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (PendingCommits
   -> Map Party (UTxOType tx)
   -> ChainStateType tx
   -> HeadId
   -> HeadSeed
   -> InitialState tx)
-> Gen PendingCommits
-> Gen
     (Map Party (UTxOType tx)
      -> ChainStateType tx -> HeadId -> HeadSeed -> InitialState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen PendingCommits
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Map Party (UTxOType tx)
   -> ChainStateType tx -> HeadId -> HeadSeed -> InitialState tx)
-> Gen (Map Party (UTxOType tx))
-> Gen (ChainStateType tx -> HeadId -> HeadSeed -> InitialState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Map Party (UTxOType tx))
forall a. Arbitrary a => Gen a
arbitrary
      Gen (ChainStateType tx -> HeadId -> HeadSeed -> InitialState tx)
-> Gen (ChainStateType tx)
-> Gen (HeadId -> HeadSeed -> InitialState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (ChainStateType tx)
forall a. Arbitrary a => Gen a
arbitrary
      Gen (HeadId -> HeadSeed -> InitialState tx)
-> Gen HeadId -> Gen (HeadSeed -> InitialState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen HeadId
forall a. Arbitrary a => Gen a
arbitrary
      Gen (HeadSeed -> InitialState tx)
-> Gen HeadSeed -> Gen (InitialState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen HeadSeed
forall a. Arbitrary a => Gen a
arbitrary

type PendingCommits = Set Party

type Committed tx = Map Party (UTxOType tx)

-- ** Open

-- | An 'Open' head with a 'CoordinatedHeadState' tracking off-chain
-- transactions.
data OpenState tx = OpenState
  { forall tx. OpenState tx -> HeadParameters
parameters :: HeadParameters
  , forall tx. OpenState tx -> CoordinatedHeadState tx
coordinatedHeadState :: CoordinatedHeadState tx
  , forall tx. OpenState tx -> ChainStateType tx
chainState :: ChainStateType tx
  , forall tx. OpenState tx -> HeadId
headId :: HeadId
  , forall tx. OpenState tx -> ChainSlot
currentSlot :: ChainSlot
  , forall tx. OpenState tx -> HeadSeed
headSeed :: HeadSeed
  }
  deriving stock ((forall x. OpenState tx -> Rep (OpenState tx) x)
-> (forall x. Rep (OpenState tx) x -> OpenState tx)
-> Generic (OpenState tx)
forall x. Rep (OpenState tx) x -> OpenState tx
forall x. OpenState tx -> Rep (OpenState tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall tx x. Rep (OpenState tx) x -> OpenState tx
forall tx x. OpenState tx -> Rep (OpenState tx) x
$cfrom :: forall tx x. OpenState tx -> Rep (OpenState tx) x
from :: forall x. OpenState tx -> Rep (OpenState tx) x
$cto :: forall tx x. Rep (OpenState tx) x -> OpenState tx
to :: forall x. Rep (OpenState tx) x -> OpenState tx
Generic)

deriving stock instance (IsTx tx, Eq (ChainStateType tx)) => Eq (OpenState tx)
deriving stock instance (IsTx tx, Show (ChainStateType tx)) => Show (OpenState tx)
deriving anyclass instance (IsTx tx, ToJSON (ChainStateType tx)) => ToJSON (OpenState tx)
deriving anyclass instance (IsTx tx, FromJSON (ChainStateType tx)) => FromJSON (OpenState tx)

instance (ArbitraryIsTx tx, Arbitrary (ChainStateType tx)) => Arbitrary (OpenState tx) where
  arbitrary :: Gen (OpenState tx)
arbitrary =
    HeadParameters
-> CoordinatedHeadState tx
-> ChainStateType tx
-> HeadId
-> ChainSlot
-> HeadSeed
-> OpenState tx
forall tx.
HeadParameters
-> CoordinatedHeadState tx
-> ChainStateType tx
-> HeadId
-> ChainSlot
-> HeadSeed
-> OpenState tx
OpenState
      (HeadParameters
 -> CoordinatedHeadState tx
 -> ChainStateType tx
 -> HeadId
 -> ChainSlot
 -> HeadSeed
 -> OpenState tx)
-> Gen HeadParameters
-> Gen
     (CoordinatedHeadState tx
      -> ChainStateType tx
      -> HeadId
      -> ChainSlot
      -> HeadSeed
      -> OpenState tx)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen HeadParameters
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (CoordinatedHeadState tx
   -> ChainStateType tx
   -> HeadId
   -> ChainSlot
   -> HeadSeed
   -> OpenState tx)
-> Gen (CoordinatedHeadState tx)
-> Gen
     (ChainStateType tx
      -> HeadId -> ChainSlot -> HeadSeed -> OpenState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (CoordinatedHeadState tx)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (ChainStateType tx
   -> HeadId -> ChainSlot -> HeadSeed -> OpenState tx)
-> Gen (ChainStateType tx)
-> Gen (HeadId -> ChainSlot -> HeadSeed -> OpenState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (ChainStateType tx)
forall a. Arbitrary a => Gen a
arbitrary
      Gen (HeadId -> ChainSlot -> HeadSeed -> OpenState tx)
-> Gen HeadId -> Gen (ChainSlot -> HeadSeed -> OpenState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen HeadId
forall a. Arbitrary a => Gen a
arbitrary
      Gen (ChainSlot -> HeadSeed -> OpenState tx)
-> Gen ChainSlot -> Gen (HeadSeed -> OpenState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen ChainSlot
forall a. Arbitrary a => Gen a
arbitrary
      Gen (HeadSeed -> OpenState tx)
-> Gen HeadSeed -> Gen (OpenState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen HeadSeed
forall a. Arbitrary a => Gen a
arbitrary

-- | Off-chain state of the Coordinated Head protocol.
data CoordinatedHeadState tx = CoordinatedHeadState
  { forall tx. CoordinatedHeadState tx -> UTxOType tx
localUTxO :: UTxOType tx
  -- ^ The latest UTxO resulting from applying 'localTxs' to
  -- 'confirmedSnapshot'. Spec: L̂
  , forall tx. CoordinatedHeadState tx -> [tx]
localTxs :: [tx]
  -- ^ List of transactions applied locally and pending inclusion in a snapshot.
  -- Ordering in this list is important as transactions are added in order of
  -- application. Spec: T̂
  , forall tx. CoordinatedHeadState tx -> Map (TxIdType tx) tx
allTxs :: Map.Map (TxIdType tx) tx
  -- ^ Map containing all the transactions ever seen by this node and not yet
  -- included in a snapshot. Spec: Tall
  , forall tx. CoordinatedHeadState tx -> ConfirmedSnapshot tx
confirmedSnapshot :: ConfirmedSnapshot tx
  -- ^ The latest confirmed snapshot. Spec: S̅
  , forall tx. CoordinatedHeadState tx -> SeenSnapshot tx
seenSnapshot :: SeenSnapshot tx
  -- ^ Last seen snapshot and signatures accumulator. Spec: Û, ŝ and Σ̂
  , forall tx.
CoordinatedHeadState tx -> Map (TxIdType tx) (UTxOType tx)
pendingDeposits :: Map (TxIdType tx) (UTxOType tx)
  -- ^ Pending deposit UTxO. Spec: Uα
  , forall tx. CoordinatedHeadState tx -> Maybe tx
decommitTx :: Maybe tx
  -- ^ Pending decommit transaction. Spec: txω
  , forall tx. CoordinatedHeadState tx -> SnapshotVersion
version :: SnapshotVersion
  -- ^ Last seen open state version. Spec: ̂v
  }
  deriving stock ((forall x.
 CoordinatedHeadState tx -> Rep (CoordinatedHeadState tx) x)
-> (forall x.
    Rep (CoordinatedHeadState tx) x -> CoordinatedHeadState tx)
-> Generic (CoordinatedHeadState tx)
forall x.
Rep (CoordinatedHeadState tx) x -> CoordinatedHeadState tx
forall x.
CoordinatedHeadState tx -> Rep (CoordinatedHeadState tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall tx x.
Rep (CoordinatedHeadState tx) x -> CoordinatedHeadState tx
forall tx x.
CoordinatedHeadState tx -> Rep (CoordinatedHeadState tx) x
$cfrom :: forall tx x.
CoordinatedHeadState tx -> Rep (CoordinatedHeadState tx) x
from :: forall x.
CoordinatedHeadState tx -> Rep (CoordinatedHeadState tx) x
$cto :: forall tx x.
Rep (CoordinatedHeadState tx) x -> CoordinatedHeadState tx
to :: forall x.
Rep (CoordinatedHeadState tx) x -> CoordinatedHeadState tx
Generic)

deriving stock instance IsTx tx => Eq (CoordinatedHeadState tx)
deriving stock instance IsTx tx => Show (CoordinatedHeadState tx)
deriving anyclass instance IsTx tx => ToJSON (CoordinatedHeadState tx)
deriving anyclass instance IsTx tx => FromJSON (CoordinatedHeadState tx)

instance ArbitraryIsTx tx => Arbitrary (CoordinatedHeadState tx) where
  arbitrary :: Gen (CoordinatedHeadState tx)
arbitrary = Gen (CoordinatedHeadState tx)
forall a.
(Generic a, GA UnsizedOpts (Rep a),
 UniformWeight (Weights_ (Rep a))) =>
Gen a
genericArbitrary

-- | Data structure to help in tracking whether we have seen or requested a
-- ReqSn already and if seen, the signatures we collected already.
data SeenSnapshot tx
  = -- | Never saw a ReqSn.
    NoSeenSnapshot
  | -- | No snapshot in flight with last seen snapshot number as given.
    LastSeenSnapshot {forall tx. SeenSnapshot tx -> SnapshotNumber
lastSeen :: SnapshotNumber}
  | -- | ReqSn was sent out and it should be considered already in flight.
    RequestedSnapshot
      { lastSeen :: SnapshotNumber
      , forall tx. SeenSnapshot tx -> SnapshotNumber
requested :: SnapshotNumber
      }
  | -- | ReqSn for given snapshot was received.
    SeenSnapshot
      { forall tx. SeenSnapshot tx -> Snapshot tx
snapshot :: Snapshot tx
      , forall tx. SeenSnapshot tx -> Map Party (Signature (Snapshot tx))
signatories :: Map Party (Signature (Snapshot tx))
      -- ^ Collected signatures and so far.
      }
  deriving stock ((forall x. SeenSnapshot tx -> Rep (SeenSnapshot tx) x)
-> (forall x. Rep (SeenSnapshot tx) x -> SeenSnapshot tx)
-> Generic (SeenSnapshot tx)
forall x. Rep (SeenSnapshot tx) x -> SeenSnapshot tx
forall x. SeenSnapshot tx -> Rep (SeenSnapshot tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall tx x. Rep (SeenSnapshot tx) x -> SeenSnapshot tx
forall tx x. SeenSnapshot tx -> Rep (SeenSnapshot tx) x
$cfrom :: forall tx x. SeenSnapshot tx -> Rep (SeenSnapshot tx) x
from :: forall x. SeenSnapshot tx -> Rep (SeenSnapshot tx) x
$cto :: forall tx x. Rep (SeenSnapshot tx) x -> SeenSnapshot tx
to :: forall x. Rep (SeenSnapshot tx) x -> SeenSnapshot tx
Generic)

instance ArbitraryIsTx tx => Arbitrary (SeenSnapshot tx) where
  arbitrary :: Gen (SeenSnapshot tx)
arbitrary = Gen (SeenSnapshot tx)
forall a.
(Generic a, GA UnsizedOpts (Rep a),
 UniformWeight (Weights_ (Rep a))) =>
Gen a
genericArbitrary

deriving stock instance IsTx tx => Eq (SeenSnapshot tx)
deriving stock instance IsTx tx => Show (SeenSnapshot tx)
deriving anyclass instance IsTx tx => ToJSON (SeenSnapshot tx)
deriving anyclass instance IsTx tx => FromJSON (SeenSnapshot tx)

-- | Get the last seen snapshot number given a 'SeenSnapshot'.
seenSnapshotNumber :: SeenSnapshot tx -> SnapshotNumber
seenSnapshotNumber :: forall tx. SeenSnapshot tx -> SnapshotNumber
seenSnapshotNumber = \case
  SeenSnapshot tx
NoSeenSnapshot -> SnapshotNumber
0
  LastSeenSnapshot{SnapshotNumber
$sel:lastSeen:NoSeenSnapshot :: forall tx. SeenSnapshot tx -> SnapshotNumber
lastSeen :: SnapshotNumber
lastSeen} -> SnapshotNumber
lastSeen
  RequestedSnapshot{SnapshotNumber
$sel:lastSeen:NoSeenSnapshot :: forall tx. SeenSnapshot tx -> SnapshotNumber
lastSeen :: SnapshotNumber
lastSeen} -> SnapshotNumber
lastSeen
  SeenSnapshot{$sel:snapshot:NoSeenSnapshot :: forall tx. SeenSnapshot tx -> Snapshot tx
snapshot = Snapshot{SnapshotNumber
number :: SnapshotNumber
$sel:number:Snapshot :: forall tx. Snapshot tx -> SnapshotNumber
number}} -> SnapshotNumber
number

-- ** Closed

-- | An 'Closed' head with an current candidate 'ConfirmedSnapshot', which may
-- be contested before the 'contestationDeadline'.
data ClosedState tx = ClosedState
  { forall tx. ClosedState tx -> HeadParameters
parameters :: HeadParameters
  , forall tx. ClosedState tx -> ConfirmedSnapshot tx
confirmedSnapshot :: ConfirmedSnapshot tx
  , forall tx. ClosedState tx -> UTCTime
contestationDeadline :: UTCTime
  , forall tx. ClosedState tx -> Bool
readyToFanoutSent :: Bool
  -- ^ Tracks whether we have informed clients already about being
  -- 'ReadyToFanout'.
  , forall tx. ClosedState tx -> ChainStateType tx
chainState :: ChainStateType tx
  , forall tx. ClosedState tx -> HeadId
headId :: HeadId
  , forall tx. ClosedState tx -> HeadSeed
headSeed :: HeadSeed
  , forall tx. ClosedState tx -> SnapshotVersion
version :: SnapshotVersion
  }
  deriving stock ((forall x. ClosedState tx -> Rep (ClosedState tx) x)
-> (forall x. Rep (ClosedState tx) x -> ClosedState tx)
-> Generic (ClosedState tx)
forall x. Rep (ClosedState tx) x -> ClosedState tx
forall x. ClosedState tx -> Rep (ClosedState tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall tx x. Rep (ClosedState tx) x -> ClosedState tx
forall tx x. ClosedState tx -> Rep (ClosedState tx) x
$cfrom :: forall tx x. ClosedState tx -> Rep (ClosedState tx) x
from :: forall x. ClosedState tx -> Rep (ClosedState tx) x
$cto :: forall tx x. Rep (ClosedState tx) x -> ClosedState tx
to :: forall x. Rep (ClosedState tx) x -> ClosedState tx
Generic)

deriving stock instance (IsTx tx, Eq (ChainStateType tx)) => Eq (ClosedState tx)
deriving stock instance (IsTx tx, Show (ChainStateType tx)) => Show (ClosedState tx)
deriving anyclass instance (IsTx tx, ToJSON (ChainStateType tx)) => ToJSON (ClosedState tx)
deriving anyclass instance (IsTx tx, FromJSON (ChainStateType tx)) => FromJSON (ClosedState tx)

instance (ArbitraryIsTx tx, Arbitrary (ChainStateType tx)) => Arbitrary (ClosedState tx) where
  arbitrary :: Gen (ClosedState tx)
arbitrary =
    HeadParameters
-> ConfirmedSnapshot tx
-> UTCTime
-> Bool
-> ChainStateType tx
-> HeadId
-> HeadSeed
-> SnapshotVersion
-> ClosedState tx
forall tx.
HeadParameters
-> ConfirmedSnapshot tx
-> UTCTime
-> Bool
-> ChainStateType tx
-> HeadId
-> HeadSeed
-> SnapshotVersion
-> ClosedState tx
ClosedState
      (HeadParameters
 -> ConfirmedSnapshot tx
 -> UTCTime
 -> Bool
 -> ChainStateType tx
 -> HeadId
 -> HeadSeed
 -> SnapshotVersion
 -> ClosedState tx)
-> Gen HeadParameters
-> Gen
     (ConfirmedSnapshot tx
      -> UTCTime
      -> Bool
      -> ChainStateType tx
      -> HeadId
      -> HeadSeed
      -> SnapshotVersion
      -> ClosedState tx)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen HeadParameters
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (ConfirmedSnapshot tx
   -> UTCTime
   -> Bool
   -> ChainStateType tx
   -> HeadId
   -> HeadSeed
   -> SnapshotVersion
   -> ClosedState tx)
-> Gen (ConfirmedSnapshot tx)
-> Gen
     (UTCTime
      -> Bool
      -> ChainStateType tx
      -> HeadId
      -> HeadSeed
      -> SnapshotVersion
      -> ClosedState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (ConfirmedSnapshot tx)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (UTCTime
   -> Bool
   -> ChainStateType tx
   -> HeadId
   -> HeadSeed
   -> SnapshotVersion
   -> ClosedState tx)
-> Gen UTCTime
-> Gen
     (Bool
      -> ChainStateType tx
      -> HeadId
      -> HeadSeed
      -> SnapshotVersion
      -> ClosedState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen UTCTime
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Bool
   -> ChainStateType tx
   -> HeadId
   -> HeadSeed
   -> SnapshotVersion
   -> ClosedState tx)
-> Gen Bool
-> Gen
     (ChainStateType tx
      -> HeadId -> HeadSeed -> SnapshotVersion -> ClosedState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Bool
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (ChainStateType tx
   -> HeadId -> HeadSeed -> SnapshotVersion -> ClosedState tx)
-> Gen (ChainStateType tx)
-> Gen (HeadId -> HeadSeed -> SnapshotVersion -> ClosedState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (ChainStateType tx)
forall a. Arbitrary a => Gen a
arbitrary
      Gen (HeadId -> HeadSeed -> SnapshotVersion -> ClosedState tx)
-> Gen HeadId
-> Gen (HeadSeed -> SnapshotVersion -> ClosedState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen HeadId
forall a. Arbitrary a => Gen a
arbitrary
      Gen (HeadSeed -> SnapshotVersion -> ClosedState tx)
-> Gen HeadSeed -> Gen (SnapshotVersion -> ClosedState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen HeadSeed
forall a. Arbitrary a => Gen a
arbitrary
      Gen (SnapshotVersion -> ClosedState tx)
-> Gen SnapshotVersion -> Gen (ClosedState tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen SnapshotVersion
forall a. Arbitrary a => Gen a
arbitrary