{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Test.Cardano.Ledger.Conformance.Utils where

import Cardano.Crypto.Hash (ByteString, Hash, HashAlgorithm, hashFromBytes, hashToBytes, sizeHash)
import Cardano.Crypto.Util (bytesToNatural, naturalToBytes)
import Cardano.Ledger.Hashes (ADDRHASH, HASH)
import qualified Data.ByteString.Base16 as B16
import Data.Data (Proxy (..))
import Test.Cardano.Ledger.TreeDiff (Expr, ToExpr (..))

standardHashSize :: Int
standardHashSize :: Int
standardHashSize = Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Int) -> (Proxy HASH -> Word) -> Proxy HASH -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy HASH -> Word
forall h (proxy :: * -> *). HashAlgorithm h => proxy h -> Word
sizeHash (Proxy HASH -> Int) -> Proxy HASH -> Int
forall a b. (a -> b) -> a -> b
$ forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @HASH

standardAddrHashSize :: Int
standardAddrHashSize :: Int
standardAddrHashSize = Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Int) -> (Proxy ADDRHASH -> Word) -> Proxy ADDRHASH -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy ADDRHASH -> Word
forall h (proxy :: * -> *). HashAlgorithm h => proxy h -> Word
sizeHash (Proxy ADDRHASH -> Int) -> Proxy ADDRHASH -> Int
forall a b. (a -> b) -> a -> b
$ forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @ADDRHASH

agdaHashToBytes :: Int -> Integer -> ByteString
agdaHashToBytes :: Int -> Integer -> ByteString
agdaHashToBytes Int
hs = ByteString -> ByteString
B16.encode (ByteString -> ByteString)
-> (Integer -> ByteString) -> Integer -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Natural -> ByteString
naturalToBytes Int
hs (Natural -> ByteString)
-> (Integer -> Natural) -> Integer -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Natural
forall a. Num a => Integer -> a
fromInteger

agdaHashToExpr :: Int -> Integer -> Expr
agdaHashToExpr :: Int -> Integer -> Expr
agdaHashToExpr Int
hs = ByteString -> Expr
forall a. ToExpr a => a -> Expr
toExpr (ByteString -> Expr) -> (Integer -> ByteString) -> Integer -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer -> ByteString
agdaHashToBytes Int
hs

hashToInteger :: Hash a b -> Integer
hashToInteger :: forall a b. Hash a b -> Integer
hashToInteger = Natural -> Integer
forall a. Integral a => a -> Integer
toInteger (Natural -> Integer)
-> (Hash a b -> Natural) -> Hash a b -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Natural
bytesToNatural (ByteString -> Natural)
-> (Hash a b -> ByteString) -> Hash a b -> Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash a b -> ByteString
forall h a. Hash h a -> ByteString
hashToBytes

integerToHash :: forall h a. HashAlgorithm h => Integer -> Maybe (Hash h a)
integerToHash :: forall h a. HashAlgorithm h => Integer -> Maybe (Hash h a)
integerToHash = ByteString -> Maybe (Hash h a)
forall h a. HashAlgorithm h => ByteString -> Maybe (Hash h a)
hashFromBytes (ByteString -> Maybe (Hash h a))
-> (Integer -> ByteString) -> Integer -> Maybe (Hash h a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Natural -> ByteString
naturalToBytes (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Int) -> (Proxy h -> Word) -> Proxy h -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy h -> Word
forall h (proxy :: * -> *). HashAlgorithm h => proxy h -> Word
sizeHash (Proxy h -> Int) -> Proxy h -> Int
forall a b. (a -> b) -> a -> b
$ forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @h) (Natural -> ByteString)
-> (Integer -> Natural) -> Integer -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Natural
forall a. Num a => Integer -> a
fromInteger