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

import Hydra.Prelude

import Codec.Serialise (serialise)
import Data.ByteString qualified as BS
import Data.ByteString.Lazy qualified as BSL
import Hydra.Cardano.Api (
  ScriptHash,
  fromPlutusScript,
  hashScript,
  pattern PlutusScript,
 )
import Hydra.Contract.Commit qualified as Commit
import Hydra.Contract.Head qualified as Head
import Hydra.Contract.HeadTokens qualified as HeadTokens
import Hydra.Contract.Initial qualified as Initial
import PlutusLedgerApi.V2 (TxId (..), TxOutRef (..), toBuiltin)

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

-- | Gather 'ScriptInfo' from the current Hydra scripts. This is useful to
-- determine changes in between version of 'hydra-plutus'.
scriptInfo :: ScriptInfo
scriptInfo :: ScriptInfo
scriptInfo =
  ScriptInfo
    { mintingScriptHash :: ScriptHash
mintingScriptHash = SerialisedScript -> ScriptHash
plutusScriptHash (SerialisedScript -> ScriptHash) -> SerialisedScript -> ScriptHash
forall a b. (a -> b) -> a -> b
$ TxOutRef -> SerialisedScript
HeadTokens.mintingPolicyScript TxOutRef
defaultOutRef
    , mintingScriptSize :: Int64
mintingScriptSize = SerialisedScript -> Int64
scriptSize (SerialisedScript -> Int64) -> SerialisedScript -> Int64
forall a b. (a -> b) -> a -> b
$ TxOutRef -> SerialisedScript
HeadTokens.mintingPolicyScript TxOutRef
defaultOutRef
    , initialScriptHash :: ScriptHash
initialScriptHash = SerialisedScript -> ScriptHash
plutusScriptHash SerialisedScript
Initial.validatorScript
    , initialScriptSize :: Int64
initialScriptSize = SerialisedScript -> Int64
scriptSize SerialisedScript
Initial.validatorScript
    , commitScriptHash :: ScriptHash
commitScriptHash = SerialisedScript -> ScriptHash
plutusScriptHash SerialisedScript
Commit.validatorScript
    , commitScriptSize :: Int64
commitScriptSize = SerialisedScript -> Int64
scriptSize SerialisedScript
Commit.validatorScript
    , headScriptHash :: ScriptHash
headScriptHash = SerialisedScript -> ScriptHash
plutusScriptHash SerialisedScript
Head.validatorScript
    , headScriptSize :: Int64
headScriptSize = SerialisedScript -> Int64
scriptSize SerialisedScript
Head.validatorScript
    }
 where
  plutusScriptHash :: SerialisedScript -> ScriptHash
plutusScriptHash =
    Script PlutusScriptV2 -> ScriptHash
forall lang. Script lang -> ScriptHash
hashScript (Script PlutusScriptV2 -> ScriptHash)
-> (SerialisedScript -> Script PlutusScriptV2)
-> SerialisedScript
-> ScriptHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PlutusScript -> Script PlutusScriptV2
PlutusScript (PlutusScript -> Script PlutusScriptV2)
-> (SerialisedScript -> PlutusScript)
-> SerialisedScript
-> Script PlutusScriptV2
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SerialisedScript -> PlutusScript
forall lang. SerialisedScript -> PlutusScript lang
fromPlutusScript

  scriptSize :: SerialisedScript -> Int64
scriptSize = ByteString -> Int64
BSL.length (ByteString -> Int64)
-> (SerialisedScript -> ByteString) -> SerialisedScript -> Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SerialisedScript -> ByteString
forall a. Serialise a => a -> ByteString
serialise

  defaultOutRef :: TxOutRef
defaultOutRef =
    TxOutRef
      { txOutRefId :: TxId
txOutRefId = BuiltinByteString -> TxId
TxId (ByteString -> BuiltinByteString
forall a arep. ToBuiltin a arep => a -> arep
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
      }