-- | 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.Deposit qualified as Deposit
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
  , ScriptInfo -> ScriptHash
depositScriptHash :: ScriptHash
  , ScriptInfo -> Int64
depositScriptSize :: 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
    , depositScriptHash :: ScriptHash
depositScriptHash = SerialisedScript -> ScriptHash
plutusScriptHash SerialisedScript
Deposit.validatorScript
    , depositScriptSize :: Int64
depositScriptSize = SerialisedScript -> Int64
scriptSize SerialisedScript
Deposit.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
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
      }