{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

-- | The 'IsPerasCert' projection/injection class.
module Ouroboros.Consensus.Peras.Cert.Class
  ( IsPerasCert (..)
  ) where

import Ouroboros.Consensus.Block.Abstract (Point)
import Ouroboros.Consensus.BlockchainTime.WallClock.Types (WithArrivalTime (..))
import Ouroboros.Consensus.Peras.Types
  ( BoostedBlock
  , BoostedBlockCompatibleWithPoint (..)
  , PerasRoundNo
  )

-- | Types that support being treated as Peras certificates
class
  BoostedBlockCompatibleWithPoint (BoostedBlock cert) blk =>
  IsPerasCert cert blk
    | cert -> blk
  where
  getPerasCertRound :: cert -> PerasRoundNo
  getPerasCertBlock :: cert -> BoostedBlock cert

  getPerasCertPoint :: cert -> Point blk
  getPerasCertPoint = BoostedBlock cert -> Point blk
forall boostedBlock blk.
BoostedBlockCompatibleWithPoint boostedBlock blk =>
boostedBlock -> Point blk
boostedBlockToPoint (BoostedBlock cert -> Point blk)
-> (cert -> BoostedBlock cert) -> cert -> Point blk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. cert -> BoostedBlock cert
forall cert blk. IsPerasCert cert blk => cert -> BoostedBlock cert
getPerasCertBlock

instance
  IsPerasCert cert blk =>
  IsPerasCert (WithArrivalTime cert) blk
  where
  getPerasCertRound :: WithArrivalTime cert -> PerasRoundNo
getPerasCertRound = cert -> PerasRoundNo
forall cert blk. IsPerasCert cert blk => cert -> PerasRoundNo
getPerasCertRound (cert -> PerasRoundNo)
-> (WithArrivalTime cert -> cert)
-> WithArrivalTime cert
-> PerasRoundNo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WithArrivalTime cert -> cert
forall a. WithArrivalTime a -> a
forgetArrivalTime
  getPerasCertBlock :: WithArrivalTime cert -> BoostedBlock (WithArrivalTime cert)
getPerasCertBlock = cert -> BoostedBlock cert
forall cert blk. IsPerasCert cert blk => cert -> BoostedBlock cert
getPerasCertBlock (cert -> BoostedBlock cert)
-> (WithArrivalTime cert -> cert)
-> WithArrivalTime cert
-> BoostedBlock cert
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WithArrivalTime cert -> cert
forall a. WithArrivalTime a -> a
forgetArrivalTime