{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}

{- FOURMOLU_DISABLE -}

module Bench.Crypto.DSIGN
  ( benchmarks
  ) where

import Data.Proxy
import Data.ByteString (ByteString)

import Control.DeepSeq

import Cardano.Crypto.DSIGN.Class
import Cardano.Crypto.DSIGN.Ed25519
#ifdef SECP256K1_ENABLED
import Cardano.Crypto.DSIGN.EcdsaSecp256k1
import Cardano.Crypto.DSIGN.SchnorrSecp256k1
import Cardano.Crypto.Hash.Blake2b
#endif

import Criterion

import Bench.Crypto.BenchData


benchmarks :: Benchmark
benchmarks :: Benchmark
benchmarks = String -> [Benchmark] -> Benchmark
bgroup String
"DSIGN"
  [ Proxy Ed25519DSIGN -> String -> Benchmark
forall v a.
(DSIGNAlgorithm v, ContextDSIGN v ~ (), Signable v a,
 ExampleSignable v a, NFData (SignKeyDSIGN v),
 NFData (VerKeyDSIGN v), NFData (SigDSIGN v)) =>
Proxy v -> String -> Benchmark
benchDSIGN (Proxy Ed25519DSIGN
forall {k} (t :: k). Proxy t
Proxy :: Proxy Ed25519DSIGN) String
"Ed25519"
#ifdef SECP256K1_ENABLED
  , Proxy EcdsaSecp256k1DSIGN -> String -> Benchmark
forall v a.
(DSIGNAlgorithm v, ContextDSIGN v ~ (), Signable v a,
 ExampleSignable v a, NFData (SignKeyDSIGN v),
 NFData (VerKeyDSIGN v), NFData (SigDSIGN v)) =>
Proxy v -> String -> Benchmark
benchDSIGN (Proxy EcdsaSecp256k1DSIGN
forall {k} (t :: k). Proxy t
Proxy :: Proxy EcdsaSecp256k1DSIGN) String
"EcdsaSecp256k1"
  , Proxy SchnorrSecp256k1DSIGN -> String -> Benchmark
forall v a.
(DSIGNAlgorithm v, ContextDSIGN v ~ (), Signable v a,
 ExampleSignable v a, NFData (SignKeyDSIGN v),
 NFData (VerKeyDSIGN v), NFData (SigDSIGN v)) =>
Proxy v -> String -> Benchmark
benchDSIGN (Proxy SchnorrSecp256k1DSIGN
forall {k} (t :: k). Proxy t
Proxy :: Proxy SchnorrSecp256k1DSIGN) String
"SchnorrSecp256k1"
#endif
  ]

benchDSIGN :: forall v a
           . ( DSIGNAlgorithm v
             , ContextDSIGN v ~ ()
             , Signable v a
             , ExampleSignable v a
             , NFData (SignKeyDSIGN v)
             , NFData (VerKeyDSIGN v)
             , NFData (SigDSIGN v)
             )
          => Proxy v
          -> String
          -> Benchmark
benchDSIGN :: forall v a.
(DSIGNAlgorithm v, ContextDSIGN v ~ (), Signable v a,
 ExampleSignable v a, NFData (SignKeyDSIGN v),
 NFData (VerKeyDSIGN v), NFData (SigDSIGN v)) =>
Proxy v -> String -> Benchmark
benchDSIGN Proxy v
_ String
lbl =
  String -> [Benchmark] -> Benchmark
bgroup String
lbl
    [ String -> Benchmarkable -> Benchmark
bench String
"genKeyDSIGN" (Benchmarkable -> Benchmark) -> Benchmarkable -> Benchmark
forall a b. (a -> b) -> a -> b
$
        (Seed -> SignKeyDSIGN v) -> Seed -> Benchmarkable
forall b a. NFData b => (a -> b) -> a -> Benchmarkable
nf (forall v. DSIGNAlgorithm v => Seed -> SignKeyDSIGN v
genKeyDSIGN @v) Seed
testSeed

    , IO (SignKeyDSIGN v) -> (SignKeyDSIGN v -> Benchmark) -> Benchmark
forall env. NFData env => IO env -> (env -> Benchmark) -> Benchmark
env (SignKeyDSIGN v -> IO (SignKeyDSIGN v)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (forall v. DSIGNAlgorithm v => Seed -> SignKeyDSIGN v
genKeyDSIGN @v Seed
testSeed)) ((SignKeyDSIGN v -> Benchmark) -> Benchmark)
-> (SignKeyDSIGN v -> Benchmark) -> Benchmark
forall a b. (a -> b) -> a -> b
$ \SignKeyDSIGN v
signKey ->
      String -> Benchmarkable -> Benchmark
bench String
"signDSIGN" (Benchmarkable -> Benchmark) -> Benchmarkable -> Benchmark
forall a b. (a -> b) -> a -> b
$
        (SignKeyDSIGN v -> SigDSIGN v) -> SignKeyDSIGN v -> Benchmarkable
forall b a. NFData b => (a -> b) -> a -> Benchmarkable
nf (forall v a.
(DSIGNAlgorithm v, Signable v a, HasCallStack) =>
ContextDSIGN v -> a -> SignKeyDSIGN v -> SigDSIGN v
signDSIGN @v () (Proxy v -> a
forall v a. (ExampleSignable v a, Signable v a) => Proxy v -> a
exampleSignable (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @v))) SignKeyDSIGN v
signKey

    , IO (VerKeyDSIGN v, SigDSIGN v)
-> ((VerKeyDSIGN v, SigDSIGN v) -> Benchmark) -> Benchmark
forall env. NFData env => IO env -> (env -> Benchmark) -> Benchmark
env (let signKey :: SignKeyDSIGN v
signKey = forall v. DSIGNAlgorithm v => Seed -> SignKeyDSIGN v
genKeyDSIGN @v Seed
testSeed
               verKey :: VerKeyDSIGN v
verKey  = SignKeyDSIGN v -> VerKeyDSIGN v
forall v. DSIGNAlgorithm v => SignKeyDSIGN v -> VerKeyDSIGN v
deriveVerKeyDSIGN SignKeyDSIGN v
signKey
               sig :: SigDSIGN v
sig     = forall v a.
(DSIGNAlgorithm v, Signable v a, HasCallStack) =>
ContextDSIGN v -> a -> SignKeyDSIGN v -> SigDSIGN v
signDSIGN @v () (Proxy v -> a
forall v a. (ExampleSignable v a, Signable v a) => Proxy v -> a
exampleSignable (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @v)) SignKeyDSIGN v
signKey
            in (VerKeyDSIGN v, SigDSIGN v) -> IO (VerKeyDSIGN v, SigDSIGN v)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (VerKeyDSIGN v
verKey, SigDSIGN v
sig)
          ) (((VerKeyDSIGN v, SigDSIGN v) -> Benchmark) -> Benchmark)
-> ((VerKeyDSIGN v, SigDSIGN v) -> Benchmark) -> Benchmark
forall a b. (a -> b) -> a -> b
$ \ ~(VerKeyDSIGN v
verKey, SigDSIGN v
sig) ->
      String -> Benchmarkable -> Benchmark
bench String
"verifyDSIGN" (Benchmarkable -> Benchmark) -> Benchmarkable -> Benchmark
forall a b. (a -> b) -> a -> b
$
        (SigDSIGN v -> Either String ()) -> SigDSIGN v -> Benchmarkable
forall b a. NFData b => (a -> b) -> a -> Benchmarkable
nf (forall v a.
(DSIGNAlgorithm v, Signable v a, HasCallStack) =>
ContextDSIGN v
-> VerKeyDSIGN v -> a -> SigDSIGN v -> Either String ()
verifyDSIGN @v () VerKeyDSIGN v
verKey (Proxy v -> a
forall v a. (ExampleSignable v a, Signable v a) => Proxy v -> a
exampleSignable (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @v))) SigDSIGN v
sig
    ]

-- | A helper class to gloss over the differences in the 'Signable' constraint
-- for different 'DSIGNAlgorithm' instances. Some use 'ByteString', some use
-- 'MessageHash'.
class ExampleSignable v a | v -> a where
  exampleSignable :: Signable v a => Proxy v -> a

instance ExampleSignable Ed25519DSIGN ByteString where
  exampleSignable :: Signable Ed25519DSIGN ByteString =>
Proxy Ed25519DSIGN -> ByteString
exampleSignable Proxy Ed25519DSIGN
_ = ByteString
typicalMsg

#ifdef SECP256K1_ENABLED
instance ExampleSignable EcdsaSecp256k1DSIGN MessageHash where
  exampleSignable :: Signable EcdsaSecp256k1DSIGN MessageHash =>
Proxy EcdsaSecp256k1DSIGN -> MessageHash
exampleSignable Proxy EcdsaSecp256k1DSIGN
_ = Proxy Blake2b_256 -> ByteString -> MessageHash
forall h.
(HashAlgorithm h, SizeHash h ~ SECP256K1_ECDSA_MESSAGE_BYTES) =>
Proxy h -> ByteString -> MessageHash
hashAndPack (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @Blake2b_256) ByteString
typicalMsg

instance ExampleSignable SchnorrSecp256k1DSIGN ByteString where
  exampleSignable :: Signable SchnorrSecp256k1DSIGN ByteString =>
Proxy SchnorrSecp256k1DSIGN -> ByteString
exampleSignable Proxy SchnorrSecp256k1DSIGN
_ = ByteString
typicalMsg
#endif