module Plutarch.Api.Internal.Hashing (
  hashScriptWithPrefix,
  hashData,
  hashLedgerBytes,
) where

import Codec.Serialise (serialise)
import Crypto.Hash (hashWith)
import Crypto.Hash.Algorithms (
  Blake2b_224 (Blake2b_224),
  Blake2b_256 (Blake2b_256),
  HashAlgorithm,
 )
import Data.ByteArray (convert)
import Data.ByteString (ByteString)
import Data.ByteString.Lazy (toStrict)
import Data.ByteString.Short (fromShort)

import Plutarch.Script (Script (unScript))
import PlutusLedgerApi.Common (serialiseUPLC)
import PlutusLedgerApi.V1 qualified as Plutus
import PlutusTx.Builtins qualified as PlutusTx

_plutusHashWith :: HashAlgorithm alg => alg -> ByteString -> PlutusTx.BuiltinByteString
_plutusHashWith :: forall alg.
HashAlgorithm alg =>
alg -> ByteString -> BuiltinByteString
_plutusHashWith alg
alg = forall a arep. ToBuiltin a arep => a -> arep
PlutusTx.toBuiltin forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert @_ @ByteString forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith alg
alg

hashBlake2b_224 :: ByteString -> PlutusTx.BuiltinByteString
hashBlake2b_224 :: ByteString -> BuiltinByteString
hashBlake2b_224 = forall alg.
HashAlgorithm alg =>
alg -> ByteString -> BuiltinByteString
_plutusHashWith Blake2b_224
Blake2b_224

hashBlake2b_256 :: ByteString -> PlutusTx.BuiltinByteString
hashBlake2b_256 :: ByteString -> BuiltinByteString
hashBlake2b_256 = forall alg.
HashAlgorithm alg =>
alg -> ByteString -> BuiltinByteString
_plutusHashWith Blake2b_256
Blake2b_256

-- | Hash a Script with the given version prefix
hashScriptWithPrefix :: ByteString -> Script -> Plutus.ScriptHash
hashScriptWithPrefix :: ByteString -> Script -> ScriptHash
hashScriptWithPrefix ByteString
prefix Script
scr =
  BuiltinByteString -> ScriptHash
Plutus.ScriptHash
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> BuiltinByteString
hashBlake2b_224
    forall a b. (a -> b) -> a -> b
$ ByteString
prefix forall a. Semigroup a => a -> a -> a
<> (ShortByteString -> ByteString
fromShort forall b c a. (b -> c) -> (a -> b) -> a -> c
. Program DeBruijn DefaultUni DefaultFun () -> ShortByteString
serialiseUPLC forall b c a. (b -> c) -> (a -> b) -> a -> c
. Script -> Program DeBruijn DefaultUni DefaultFun ()
unScript forall a b. (a -> b) -> a -> b
$ Script
scr)

-- | Hash Plutus 'Data'.
hashData :: Plutus.Data -> PlutusTx.BuiltinByteString
hashData :: Data -> BuiltinByteString
hashData = ByteString -> BuiltinByteString
hashBlake2b_256 forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
toStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Serialise a => a -> ByteString
serialise

-- | Hash 'LedgerBytes'.
hashLedgerBytes :: Plutus.LedgerBytes -> PlutusTx.BuiltinByteString
hashLedgerBytes :: LedgerBytes -> BuiltinByteString
hashLedgerBytes = ByteString -> BuiltinByteString
hashBlake2b_224 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall arep a. FromBuiltin arep a => arep -> a
Plutus.fromBuiltin forall b c a. (b -> c) -> (a -> b) -> a -> c
. LedgerBytes -> BuiltinByteString
Plutus.getLedgerBytes