{-# OPTIONS_GHC -Wno-orphans #-}

module Hydra.Cardano.Api.BlockHeader where

import Hydra.Cardano.Api.Prelude

import Data.ByteString qualified as BS
import Test.QuickCheck (vectorOf)

-- * Generators

-- | Fully arbitrary block header with completely random hash.
genBlockHeader :: Gen BlockHeader
genBlockHeader :: Gen BlockHeader
genBlockHeader = do
  SlotNo
slotNo <- Word64 -> SlotNo
SlotNo (Word64 -> SlotNo) -> Gen Word64 -> Gen SlotNo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word64
forall a. Arbitrary a => Gen a
arbitrary
  SlotNo -> Gen BlockHeader
genBlockHeaderAt SlotNo
slotNo

-- | Generate a random block header with completely random hash, but at a
-- certain slot.
genBlockHeaderAt :: SlotNo -> Gen BlockHeader
genBlockHeaderAt :: SlotNo -> Gen BlockHeader
genBlockHeaderAt SlotNo
slotNo = do
  Hash BlockHeader
headerHash <- Gen (Hash BlockHeader)
genBlockHeaderHash
  BlockNo
blockNo <- Word64 -> BlockNo
BlockNo (Word64 -> BlockNo) -> Gen Word64 -> Gen BlockNo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word64
forall a. Arbitrary a => Gen a
arbitrary
  BlockHeader -> Gen BlockHeader
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BlockHeader -> Gen BlockHeader) -> BlockHeader -> Gen BlockHeader
forall a b. (a -> b) -> a -> b
$ SlotNo -> Hash BlockHeader -> BlockNo -> BlockHeader
BlockHeader SlotNo
slotNo Hash BlockHeader
headerHash BlockNo
blockNo

-- | Generate a random block header hash.
genBlockHeaderHash :: Gen (Hash BlockHeader)
genBlockHeaderHash :: Gen (Hash BlockHeader)
genBlockHeaderHash =
  ByteString -> Hash BlockHeader
forall {a}. SerialiseAsRawBytes a => ByteString -> a
unsafeBlockHeaderHashFromBytes (ByteString -> Hash BlockHeader)
-> ([Word8] -> ByteString) -> [Word8] -> Hash BlockHeader
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
BS.pack ([Word8] -> Hash BlockHeader)
-> Gen [Word8] -> Gen (Hash BlockHeader)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen Word8 -> Gen [Word8]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
32 Gen Word8
forall a. Arbitrary a => Gen a
arbitrary
 where
  unsafeBlockHeaderHashFromBytes :: ByteString -> a
unsafeBlockHeaderHashFromBytes ByteString
bytes =
    case AsType a -> ByteString -> Either SerialiseAsRawBytesError a
forall a.
SerialiseAsRawBytes a =>
AsType a -> ByteString -> Either SerialiseAsRawBytesError a
deserialiseFromRawBytes (Proxy a -> AsType a
forall t. HasTypeProxy t => Proxy t -> AsType t
proxyToAsType Proxy a
forall {k} (t :: k). Proxy t
Proxy) ByteString
bytes of
      Left SerialiseAsRawBytesError
e ->
        [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$
          [Char]
"unsafeBlockHeaderHashFromBytes: failed on bytes "
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> ByteString -> [Char]
forall a. Show a => a -> [Char]
show ByteString
bytes
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" with error "
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> SerialiseAsRawBytesError -> [Char]
forall a. Show a => a -> [Char]
show SerialiseAsRawBytesError
e
      Right a
h -> a
h

-- * Orphans

instance Arbitrary BlockHeader where
  arbitrary :: Gen BlockHeader
arbitrary = Gen BlockHeader
genBlockHeader