-- | Things related to the Hydra smart contracts / script validators.
module Hydra.Contract where

import Hydra.Prelude

import Data.ByteString qualified as BS
import Hydra.Cardano.Api (
  ScriptHash,
  hashScript,
  serialiseToRawBytes,
  pattern PlutusScript,
 )
import Hydra.Contract.CRS qualified as CRS
import Hydra.Contract.Head qualified as Head
import Hydra.Contract.HeadTokens qualified as HeadTokens
import Hydra.Plutus (depositValidatorScript)
import PlutusLedgerApi.V3 (TxId (..), TxOutRef (..), toBuiltin)

-- | Information about relevant Hydra scripts.
data HydraScriptCatalogue = HydraScriptCatalogue
  { HydraScriptCatalogue -> ScriptHash
mintingScriptHash :: ScriptHash
  -- ^ Hash of the μHead minting script given some default parameters.
  , HydraScriptCatalogue -> Int
mintingScriptSize :: Int
  -- ^ Size of the μHead minting script given some default parameters.
  , HydraScriptCatalogue -> ScriptHash
headScriptHash :: ScriptHash
  , HydraScriptCatalogue -> Int
headScriptSize :: Int
  , HydraScriptCatalogue -> ScriptHash
depositScriptHash :: ScriptHash
  , HydraScriptCatalogue -> Int
depositScriptSize :: Int
  , HydraScriptCatalogue -> ScriptHash
crsScriptHash :: ScriptHash
  , HydraScriptCatalogue -> Int
crsScriptSize :: Int
  }
  deriving stock (HydraScriptCatalogue -> HydraScriptCatalogue -> Bool
(HydraScriptCatalogue -> HydraScriptCatalogue -> Bool)
-> (HydraScriptCatalogue -> HydraScriptCatalogue -> Bool)
-> Eq HydraScriptCatalogue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: HydraScriptCatalogue -> HydraScriptCatalogue -> Bool
== :: HydraScriptCatalogue -> HydraScriptCatalogue -> Bool
$c/= :: HydraScriptCatalogue -> HydraScriptCatalogue -> Bool
/= :: HydraScriptCatalogue -> HydraScriptCatalogue -> Bool
Eq, Int -> HydraScriptCatalogue -> ShowS
[HydraScriptCatalogue] -> ShowS
HydraScriptCatalogue -> String
(Int -> HydraScriptCatalogue -> ShowS)
-> (HydraScriptCatalogue -> String)
-> ([HydraScriptCatalogue] -> ShowS)
-> Show HydraScriptCatalogue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HydraScriptCatalogue -> ShowS
showsPrec :: Int -> HydraScriptCatalogue -> ShowS
$cshow :: HydraScriptCatalogue -> String
show :: HydraScriptCatalogue -> String
$cshowList :: [HydraScriptCatalogue] -> ShowS
showList :: [HydraScriptCatalogue] -> ShowS
Show, (forall x. HydraScriptCatalogue -> Rep HydraScriptCatalogue x)
-> (forall x. Rep HydraScriptCatalogue x -> HydraScriptCatalogue)
-> Generic HydraScriptCatalogue
forall x. Rep HydraScriptCatalogue x -> HydraScriptCatalogue
forall x. HydraScriptCatalogue -> Rep HydraScriptCatalogue x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. HydraScriptCatalogue -> Rep HydraScriptCatalogue x
from :: forall x. HydraScriptCatalogue -> Rep HydraScriptCatalogue x
$cto :: forall x. Rep HydraScriptCatalogue x -> HydraScriptCatalogue
to :: forall x. Rep HydraScriptCatalogue x -> HydraScriptCatalogue
Generic)
  deriving anyclass ([HydraScriptCatalogue] -> Value
[HydraScriptCatalogue] -> Encoding
HydraScriptCatalogue -> Bool
HydraScriptCatalogue -> Value
HydraScriptCatalogue -> Encoding
(HydraScriptCatalogue -> Value)
-> (HydraScriptCatalogue -> Encoding)
-> ([HydraScriptCatalogue] -> Value)
-> ([HydraScriptCatalogue] -> Encoding)
-> (HydraScriptCatalogue -> Bool)
-> ToJSON HydraScriptCatalogue
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: HydraScriptCatalogue -> Value
toJSON :: HydraScriptCatalogue -> Value
$ctoEncoding :: HydraScriptCatalogue -> Encoding
toEncoding :: HydraScriptCatalogue -> Encoding
$ctoJSONList :: [HydraScriptCatalogue] -> Value
toJSONList :: [HydraScriptCatalogue] -> Value
$ctoEncodingList :: [HydraScriptCatalogue] -> Encoding
toEncodingList :: [HydraScriptCatalogue] -> Encoding
$comitField :: HydraScriptCatalogue -> Bool
omitField :: HydraScriptCatalogue -> Bool
ToJSON)

-- | Gather 'HydraScriptCatalogue' from the current Hydra scripts. This is useful to
-- determine changes in between version of 'hydra-plutus'.
hydraScriptCatalogue :: HydraScriptCatalogue
hydraScriptCatalogue :: HydraScriptCatalogue
hydraScriptCatalogue =
  HydraScriptCatalogue
    { mintingScriptHash :: ScriptHash
mintingScriptHash = PlutusScript -> ScriptHash
scriptHash (PlutusScript -> ScriptHash) -> PlutusScript -> ScriptHash
forall a b. (a -> b) -> a -> b
$ TxOutRef -> PlutusScript
HeadTokens.mintingPolicyScript TxOutRef
defaultOutRef
    , mintingScriptSize :: Int
mintingScriptSize = PlutusScript -> Int
scriptSize (PlutusScript -> Int) -> PlutusScript -> Int
forall a b. (a -> b) -> a -> b
$ TxOutRef -> PlutusScript
HeadTokens.mintingPolicyScript TxOutRef
defaultOutRef
    , headScriptHash :: ScriptHash
headScriptHash = PlutusScript -> ScriptHash
scriptHash PlutusScript
Head.validatorScript
    , headScriptSize :: Int
headScriptSize = PlutusScript -> Int
scriptSize PlutusScript
Head.validatorScript
    , depositScriptHash :: ScriptHash
depositScriptHash = PlutusScript -> ScriptHash
scriptHash PlutusScript
depositValidatorScript
    , depositScriptSize :: Int
depositScriptSize = PlutusScript -> Int
scriptSize PlutusScript
depositValidatorScript
    , crsScriptHash :: ScriptHash
crsScriptHash = PlutusScript -> ScriptHash
scriptHash PlutusScript
CRS.validatorScript
    , crsScriptSize :: Int
crsScriptSize = PlutusScript -> Int
scriptSize PlutusScript
CRS.validatorScript
    }
 where
  scriptHash :: PlutusScript -> ScriptHash
scriptHash = Script PlutusScriptV3 -> ScriptHash
forall lang. Script lang -> ScriptHash
hashScript (Script PlutusScriptV3 -> ScriptHash)
-> (PlutusScript -> Script PlutusScriptV3)
-> PlutusScript
-> ScriptHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PlutusScript -> Script PlutusScriptV3
PlutusScript

  scriptSize :: PlutusScript -> Int
scriptSize = ByteString -> Int
BS.length (ByteString -> Int)
-> (PlutusScript -> ByteString) -> PlutusScript -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PlutusScript -> ByteString
forall a. SerialiseAsRawBytes a => a -> ByteString
serialiseToRawBytes

  defaultOutRef :: TxOutRef
defaultOutRef =
    TxOutRef
      { txOutRefId :: TxId
txOutRefId = BuiltinByteString -> TxId
TxId (ByteString -> BuiltinByteString
ByteString -> ToBuiltin ByteString
forall a. HasToBuiltin a => a -> ToBuiltin a
toBuiltin (ByteString -> BuiltinByteString)
-> ([Word8] -> ByteString) -> [Word8] -> BuiltinByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
BS.pack ([Word8] -> BuiltinByteString) -> [Word8] -> BuiltinByteString
forall a b. (a -> b) -> a -> b
$ Int -> Word8 -> [Word8]
forall a. Int -> a -> [a]
replicate Int
32 Word8
0)
      , txOutRefIdx :: Integer
txOutRefIdx = Integer
0
      }