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

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

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

import Morley.Tezos.Crypto
  (KeyHash, KeyHashTag, PublicKey, SecretKey(..), Signature(..), allHashTags, hashKey,
  signatureLengthBytes, toPublic)

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

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

genSecretKey :: MonadGen m => m SecretKey
genSecretKey :: forall (m :: * -> *). MonadGen m => m SecretKey
genSecretKey = [m SecretKey] -> m SecretKey
forall (m :: * -> *) a. MonadGen m => [m a] -> m a
Gen.choice
  [ SecretKey -> SecretKey
SecretKeyEd25519 (SecretKey -> SecretKey) -> m SecretKey -> m SecretKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m SecretKey
forall (m :: * -> *). MonadGen m => m SecretKey
Ed25519.genSecretKey
  , SecretKey -> SecretKey
SecretKeySecp256k1 (SecretKey -> SecretKey) -> m SecretKey -> m SecretKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m SecretKey
forall (m :: * -> *). MonadGen m => m SecretKey
Secp256k1.genSecretKey
  , SecretKey -> SecretKey
SecretKeyP256 (SecretKey -> SecretKey) -> m SecretKey -> m SecretKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m SecretKey
forall (m :: * -> *). MonadGen m => m SecretKey
P256.genSecretKey
  ]

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
  , 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 = PublicKey -> KeyHash
hashKey (PublicKey -> KeyHash) -> m PublicKey -> m KeyHash
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m PublicKey
forall (m :: * -> *). MonadGen m => m PublicKey
genPublicKey