-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA

module Hedgehog.Gen.Tezos.Crypto
  ( genPublicKey
  , genSecretKey
  , genSignature
  , genKeyHashTag
  , genKeyHash
  , genPublicKey'
  , genSecretKey'
  , genKeyHash'
  , genKeyType
  ) where

import Hedgehog (MonadGen)
import Hedgehog.Gen qualified as Gen
import Hedgehog.Range qualified as Range

import Morley.Tezos.Crypto

import Hedgehog.Gen.Tezos.Crypto.BLS qualified as BLS
import Hedgehog.Gen.Tezos.Crypto.Ed25519 qualified as Ed25519
import Hedgehog.Gen.Tezos.Crypto.P256 qualified as P256
import Hedgehog.Gen.Tezos.Crypto.Secp256k1 qualified as Secp256k1

genKeyType :: MonadGen m => m KeyType
genKeyType :: forall (m :: * -> *). MonadGen m => m KeyType
genKeyType = [m KeyType] -> m KeyType
forall (m :: * -> *) a. MonadGen m => [m a] -> m a
Gen.choice ([m KeyType] -> m KeyType) -> [m KeyType] -> m KeyType
forall a b. (a -> b) -> a -> b
$ KeyType -> m KeyType
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (KeyType -> m KeyType) -> [KeyType] -> [m KeyType]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [KeyType
forall a. Bounded a => a
minBound..]

genPublicKey :: MonadGen m => m PublicKey
genPublicKey :: forall (m :: * -> *). MonadGen m => m PublicKey
genPublicKey = m KeyType -> m PublicKey
forall (m :: * -> *). MonadGen m => m KeyType -> m PublicKey
genPublicKey' m KeyType
forall (m :: * -> *). MonadGen m => m KeyType
genKeyType

genPublicKey' :: MonadGen m => m KeyType -> m PublicKey
genPublicKey' :: forall (m :: * -> *). MonadGen m => m KeyType -> m PublicKey
genPublicKey' m KeyType
keyType = SecretKey -> PublicKey
toPublic (SecretKey -> PublicKey) -> m SecretKey -> m PublicKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m KeyType -> m SecretKey
forall (m :: * -> *). MonadGen m => m KeyType -> m SecretKey
genSecretKey' m KeyType
keyType

genSecretKey :: MonadGen m => m SecretKey
genSecretKey :: forall (m :: * -> *). MonadGen m => m SecretKey
genSecretKey = m KeyType -> m SecretKey
forall (m :: * -> *). MonadGen m => m KeyType -> m SecretKey
genSecretKey' m KeyType
forall (m :: * -> *). MonadGen m => m KeyType
genKeyType

genSecretKey' :: MonadGen m => m KeyType -> m SecretKey
genSecretKey' :: forall (m :: * -> *). MonadGen m => m KeyType -> m SecretKey
genSecretKey' m KeyType
keyType = KeyType -> ByteString -> SecretKey
detSecretKey' (KeyType -> ByteString -> SecretKey)
-> m KeyType -> m (ByteString -> SecretKey)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m KeyType
keyType m (ByteString -> SecretKey) -> m ByteString -> m SecretKey
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Range Int -> m ByteString
forall (m :: * -> *). MonadGen m => Range Int -> m ByteString
Gen.bytes (Int -> Range Int
forall a. a -> Range a
Range.singleton Int
32)

genSignature :: MonadGen m => m Signature
genSignature :: forall (m :: * -> *). MonadGen m => m Signature
genSignature = [m Signature] -> m Signature
forall (m :: * -> *) a. MonadGen m => [m a] -> m a
Gen.choice
  [ Signature -> Signature
SignatureEd25519 (Signature -> Signature) -> m Signature -> m Signature
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Signature
forall (m :: * -> *). MonadGen m => m Signature
Ed25519.genSignature
  , Signature -> Signature
SignatureSecp256k1 (Signature -> Signature) -> m Signature -> m Signature
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Signature
forall (m :: * -> *). MonadGen m => m Signature
Secp256k1.genSignature
  , Signature -> Signature
SignatureP256 (Signature -> Signature) -> m Signature -> m Signature
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Signature
forall (m :: * -> *). MonadGen m => m Signature
P256.genSignature
  , Signature -> Signature
SignatureBLS (Signature -> Signature) -> m Signature -> m Signature
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Signature
forall (m :: * -> *). MonadGen m => m Signature
BLS.genSignature
  , ByteString -> Signature
SignatureGeneric (ByteString -> Signature) -> m ByteString -> m Signature
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int -> m ByteString
forall (m :: * -> *). MonadGen m => Range Int -> m ByteString
Gen.bytes (Int -> Range Int
forall a. a -> Range a
Range.singleton Int
forall n. (HasCallStack, Integral n) => n
signatureLengthBytes)
  ]

genKeyHashTag :: MonadGen m => m KeyHashTag
genKeyHashTag :: forall (m :: * -> *). MonadGen m => m KeyHashTag
genKeyHashTag = [KeyHashTag] -> m KeyHashTag
forall (m :: * -> *) a. MonadGen m => [a] -> m a
Gen.element ([KeyHashTag] -> m KeyHashTag) -> [KeyHashTag] -> m KeyHashTag
forall a b. (a -> b) -> a -> b
$ NonEmpty KeyHashTag -> [Element (NonEmpty KeyHashTag)]
forall t. Container t => t -> [Element t]
toList NonEmpty KeyHashTag
forall (kind :: HashKind).
AllHashTags kind =>
NonEmpty (HashTag kind)
allHashTags

genKeyHash :: MonadGen m => m KeyHash
genKeyHash :: forall (m :: * -> *). MonadGen m => m KeyHash
genKeyHash = m KeyType -> m KeyHash
forall (m :: * -> *). MonadGen m => m KeyType -> m KeyHash
genKeyHash' m KeyType
forall (m :: * -> *). MonadGen m => m KeyType
genKeyType

genKeyHash' :: MonadGen m => m KeyType -> m KeyHash
genKeyHash' :: forall (m :: * -> *). MonadGen m => m KeyType -> m KeyHash
genKeyHash' m KeyType
keyType = PublicKey -> KeyHash
hashKey (PublicKey -> KeyHash) -> m PublicKey -> m KeyHash
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m KeyType -> m PublicKey
forall (m :: * -> *). MonadGen m => m KeyType -> m PublicKey
genPublicKey' m KeyType
keyType