{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

-- | Test crypto for voting committee tests, based on BLS signatures.
module Test.Consensus.Committee.TestCrypto
  ( -- * Test crypto based on BLS signatures
    TestCrypto
  , VoteSignature (TestVoteSignature, unTestVoteSignature)
  , VRFElectionInput (TestVRFElectionInput, unTestVRFElectionInput)
  , VRFOutput (TestVRFOutput, unTestVRFOutput)

    -- * QuickCheck helpers
  , genElectionId
  , genVoteCandidate
  , genKeyPair

    -- * Smoke test properties
  , prop_SignAndVerifyVote
  , prop_SignAndVerifyAggregateVote
  , prop_EvalAndVerifyVRFOutput
  , prop_EvalAndVerifyAggregateVRFOutput
  , tests
  ) where

import Cardano.Crypto.DSIGN
  ( BLS12381MinSigDSIGN
  , DSIGNAlgorithm (..)
  )
import Cardano.Crypto.Hash (ByteString, Hash)
import qualified Cardano.Crypto.Hash as Hash
import Cardano.Ledger.BaseTypes (Nonce (..))
import Cardano.Ledger.Binary (runByteBuilder)
import Cardano.Ledger.Hashes (HASH)
import Control.Monad (when)
import Control.Monad.Zip (MonadZip (..))
import Data.Bifunctor (Bifunctor (..))
import qualified Data.ByteString as BS
import qualified Data.ByteString.Builder as BS
import qualified Data.ByteString.Builder.Extra as BS
import Data.Containers.NonEmpty (HasNonEmpty (..))
import Data.Either (fromRight)
import qualified Data.List.NonEmpty as NonEmpty
import Data.Maybe (fromMaybe)
import Data.Proxy (Proxy (..))
import Data.Word (Word64)
import GHC.Word (Word8)
import Ouroboros.Consensus.Committee.Crypto
  ( CryptoSupportsAggregateVoteSigning (..)
  , CryptoSupportsBatchVRFVerification (..)
  , CryptoSupportsVRF (..)
  , CryptoSupportsVoteSigning (..)
  , ElectionId
  , PrivateKey
  , PublicKey
  , VRFPoolContext (..)
  , VoteCandidate
  )
import Ouroboros.Consensus.Committee.Crypto.BLS (KeyRole (..))
import qualified Ouroboros.Consensus.Committee.Crypto.BLS as BLS
import Test.Consensus.Committee.Utils (genEpochNonce)
import Test.QuickCheck
  ( Arbitrary (..)
  , Gen
  , Property
  , Small (..)
  , Testable (..)
  , choose
  , counterexample
  , forAll
  , suchThat
  , tabulate
  , vectorOf
  , (===)
  )
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.QuickCheck (testProperty)
import Test.Util.TestEnv (adjustQuickCheckTests)

-- * Test crypto based on BLS signatures

data TestCrypto

type instance ElectionId TestCrypto = Word64
type instance VoteCandidate TestCrypto = ByteString -- 32 bytes long

type instance PrivateKey TestCrypto = (BLS.PrivateKey SIGN, BLS.PrivateKey VRF)
type instance PublicKey TestCrypto = (BLS.PublicKey SIGN, BLS.PublicKey VRF)

-- | Hash the message of a Peras vote
--
-- NOTE: this is inspired by the implementation used by the Praos VRF check in
-- 'Ouroboros.Consensus.Protocol.Praos.VRF.mkInputVRF'.
hashVoteSignature ::
  ElectionId TestCrypto ->
  VoteCandidate TestCrypto ->
  Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
hashVoteSignature :: ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
hashVoteSignature ElectionId TestCrypto
electionId VoteCandidate TestCrypto
candidate =
  Hash HASH ByteString -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
forall h a b. Hash h a -> Hash h b
Hash.castHash
    (Hash HASH ByteString -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN))
-> (Builder -> Hash HASH ByteString)
-> Builder
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> ByteString) -> ByteString -> Hash HASH ByteString
forall h a. HashAlgorithm h => (a -> ByteString) -> a -> Hash h a
Hash.hashWith ByteString -> ByteString
forall a. a -> a
id
    (ByteString -> Hash HASH ByteString)
-> (Builder -> ByteString) -> Builder -> Hash HASH ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder -> ByteString
runByteBuilder (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
32)
    (Builder -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN))
-> Builder -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
forall a b. (a -> b) -> a -> b
$ Builder
electionIdBytes Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
candidateBytes
 where
  electionIdBytes :: Builder
electionIdBytes =
    Word64 -> Builder
BS.word64BE Word64
ElectionId TestCrypto
electionId
  candidateBytes :: Builder
candidateBytes =
    ByteString -> Builder
BS.byteStringCopy ByteString
VoteCandidate TestCrypto
candidate

-- | Hash the input for the VRF used in Peras elections
--
-- NOTE: this is inspired by the implementation used by the Praos VRF check in
-- 'Ouroboros.Consensus.Protocol.Praos.VRF.mkInputVRF'.
hashVRFInput ::
  ElectionId TestCrypto ->
  Nonce ->
  Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
hashVRFInput :: ElectionId TestCrypto
-> Nonce -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
hashVRFInput ElectionId TestCrypto
electionId Nonce
epochNonce =
  Hash HASH ByteString -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
forall h a b. Hash h a -> Hash h b
Hash.castHash
    (Hash HASH ByteString -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN))
-> (Builder -> Hash HASH ByteString)
-> Builder
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> ByteString) -> ByteString -> Hash HASH ByteString
forall h a. HashAlgorithm h => (a -> ByteString) -> a -> Hash h a
Hash.hashWith ByteString -> ByteString
forall a. a -> a
id
    (ByteString -> Hash HASH ByteString)
-> (Builder -> ByteString) -> Builder -> Hash HASH ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder -> ByteString
runByteBuilder (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
32)
    (Builder -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN))
-> Builder -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
forall a b. (a -> b) -> a -> b
$ Builder
electionIdBytes Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
epochNonceBytes
 where
  electionIdBytes :: Builder
electionIdBytes =
    Word64 -> Builder
BS.word64BE Word64
ElectionId TestCrypto
electionId
  epochNonceBytes :: Builder
epochNonceBytes =
    case Nonce
epochNonce of
      Nonce
NeutralNonce -> Builder
forall a. Monoid a => a
mempty
      Nonce Hash HASH Nonce
h -> ByteString -> Builder
BS.byteStringCopy (Hash HASH Nonce -> ByteString
forall h a. Hash h a -> ByteString
Hash.hashToBytes Hash HASH Nonce
h)

-- * Crypto instances

instance CryptoSupportsVoteSigning TestCrypto where
  type VoteSigningKey TestCrypto = BLS.PrivateKey SIGN
  type VoteVerificationKey TestCrypto = BLS.PublicKey SIGN

  newtype VoteSignature TestCrypto
    = TestVoteSignature
    { VoteSignature TestCrypto -> Signature SIGN
unTestVoteSignature :: BLS.Signature SIGN
    }
    deriving newtype (Int -> VoteSignature TestCrypto -> ShowS
[VoteSignature TestCrypto] -> ShowS
VoteSignature TestCrypto -> String
(Int -> VoteSignature TestCrypto -> ShowS)
-> (VoteSignature TestCrypto -> String)
-> ([VoteSignature TestCrypto] -> ShowS)
-> Show (VoteSignature TestCrypto)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> VoteSignature TestCrypto -> ShowS
showsPrec :: Int -> VoteSignature TestCrypto -> ShowS
$cshow :: VoteSignature TestCrypto -> String
show :: VoteSignature TestCrypto -> String
$cshowList :: [VoteSignature TestCrypto] -> ShowS
showList :: [VoteSignature TestCrypto] -> ShowS
Show, VoteSignature TestCrypto -> VoteSignature TestCrypto -> Bool
(VoteSignature TestCrypto -> VoteSignature TestCrypto -> Bool)
-> (VoteSignature TestCrypto -> VoteSignature TestCrypto -> Bool)
-> Eq (VoteSignature TestCrypto)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VoteSignature TestCrypto -> VoteSignature TestCrypto -> Bool
== :: VoteSignature TestCrypto -> VoteSignature TestCrypto -> Bool
$c/= :: VoteSignature TestCrypto -> VoteSignature TestCrypto -> Bool
/= :: VoteSignature TestCrypto -> VoteSignature TestCrypto -> Bool
Eq)

  getVoteSigningKey :: Proxy TestCrypto
-> PrivateKey TestCrypto -> VoteSigningKey TestCrypto
getVoteSigningKey Proxy TestCrypto
_ = (PrivateKey SIGN, PrivateKey VRF) -> PrivateKey SIGN
PrivateKey TestCrypto -> VoteSigningKey TestCrypto
forall a b. (a, b) -> a
fst
  getVoteVerificationKey :: Proxy TestCrypto
-> PublicKey TestCrypto -> VoteVerificationKey TestCrypto
getVoteVerificationKey Proxy TestCrypto
_ = (PublicKey SIGN, PublicKey VRF) -> PublicKey SIGN
PublicKey TestCrypto -> VoteVerificationKey TestCrypto
forall a b. (a, b) -> a
fst

  signVote :: VoteSigningKey TestCrypto
-> ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> VoteSignature TestCrypto
signVote VoteSigningKey TestCrypto
sk ElectionId TestCrypto
electionId VoteCandidate TestCrypto
candidate =
    Signature SIGN -> VoteSignature TestCrypto
TestVoteSignature
      (Signature SIGN -> VoteSignature TestCrypto)
-> (Hash HASH (SigDSIGN BLS12381MinSigDSIGN) -> Signature SIGN)
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
-> VoteSignature TestCrypto
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: KeyRole) msg.
(SignableRepresentation msg, HasBLSContext r) =>
PrivateKey r -> msg -> Signature r
BLS.signWithRole @SIGN VoteSigningKey TestCrypto
PrivateKey SIGN
sk
      (Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
 -> VoteSignature TestCrypto)
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
-> VoteSignature TestCrypto
forall a b. (a -> b) -> a -> b
$ ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
hashVoteSignature ElectionId TestCrypto
electionId VoteCandidate TestCrypto
candidate

  verifyVoteSignature :: VoteVerificationKey TestCrypto
-> ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> VoteSignature TestCrypto
-> Either String ()
verifyVoteSignature VoteVerificationKey TestCrypto
pk ElectionId TestCrypto
electionId VoteCandidate TestCrypto
candidate (TestVoteSignature Signature SIGN
sig) =
    forall (r :: KeyRole) msg.
(SignableRepresentation msg, HasBLSContext r) =>
PublicKey r -> msg -> Signature r -> Either String ()
BLS.verifyWithRole @SIGN
      VoteVerificationKey TestCrypto
PublicKey SIGN
pk
      (ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
hashVoteSignature ElectionId TestCrypto
electionId VoteCandidate TestCrypto
candidate)
      Signature SIGN
sig

instance CryptoSupportsAggregateVoteSigning TestCrypto where
  -- NOTE: in a real implementation, we would want to wrap these into newtypes
  type AggregateVoteVerificationKey TestCrypto = VoteVerificationKey TestCrypto
  type AggregateVoteSignature TestCrypto = VoteSignature TestCrypto

  aggregateVoteVerificationKeys :: Proxy TestCrypto
-> NE [VoteVerificationKey TestCrypto]
-> Either String (AggregateVoteVerificationKey TestCrypto)
aggregateVoteVerificationKeys Proxy TestCrypto
_ NE [VoteVerificationKey TestCrypto]
pks =
    forall (r :: KeyRole).
NE [PublicKey r] -> Either String (PublicKey r)
BLS.aggregatePublicKeys @SIGN NE [VoteVerificationKey TestCrypto]
NE [PublicKey SIGN]
pks

  aggregateVoteSignatures :: Proxy TestCrypto
-> NE [VoteSignature TestCrypto]
-> Either String (AggregateVoteSignature TestCrypto)
aggregateVoteSignatures Proxy TestCrypto
_ NE [VoteSignature TestCrypto]
sigs = do
    aggSig <-
      forall (r :: KeyRole).
NE [Signature r] -> Either String (Signature r)
BLS.aggregateSignatures @SIGN
        (NonEmpty (Signature SIGN) -> Either String (Signature SIGN))
-> (NE [VoteSignature TestCrypto] -> NonEmpty (Signature SIGN))
-> NE [VoteSignature TestCrypto]
-> Either String (Signature SIGN)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VoteSignature TestCrypto -> Signature SIGN)
-> NonEmpty (VoteSignature TestCrypto) -> NonEmpty (Signature SIGN)
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VoteSignature TestCrypto -> Signature SIGN
unTestVoteSignature
        (NE [VoteSignature TestCrypto] -> Either String (Signature SIGN))
-> NE [VoteSignature TestCrypto] -> Either String (Signature SIGN)
forall a b. (a -> b) -> a -> b
$ NE [VoteSignature TestCrypto]
sigs
    pure (TestVoteSignature aggSig)

  verifyAggregateVoteSignature :: Proxy TestCrypto
-> AggregateVoteVerificationKey TestCrypto
-> ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> AggregateVoteSignature TestCrypto
-> Either String ()
verifyAggregateVoteSignature
    Proxy TestCrypto
_
    AggregateVoteVerificationKey TestCrypto
aggPk
    ElectionId TestCrypto
electionId
    VoteCandidate TestCrypto
candidate
    AggregateVoteSignature TestCrypto
aggSig = do
      forall (r :: KeyRole) msg.
(SignableRepresentation msg, HasBLSContext r) =>
PublicKey r -> msg -> Signature r -> Either String ()
BLS.verifyWithRole @SIGN
        AggregateVoteVerificationKey TestCrypto
PublicKey SIGN
aggPk
        (ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
hashVoteSignature ElectionId TestCrypto
electionId VoteCandidate TestCrypto
candidate)
        (VoteSignature TestCrypto -> Signature SIGN
unTestVoteSignature AggregateVoteSignature TestCrypto
VoteSignature TestCrypto
aggSig)

instance CryptoSupportsVRF TestCrypto where
  type VRFSigningKey TestCrypto = BLS.PrivateKey VRF
  type VRFVerificationKey TestCrypto = BLS.PublicKey VRF

  newtype VRFElectionInput TestCrypto
    = TestVRFElectionInput
    { VRFElectionInput TestCrypto
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
unTestVRFElectionInput ::
        Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
    }
    deriving newtype (Int -> VRFElectionInput TestCrypto -> ShowS
[VRFElectionInput TestCrypto] -> ShowS
VRFElectionInput TestCrypto -> String
(Int -> VRFElectionInput TestCrypto -> ShowS)
-> (VRFElectionInput TestCrypto -> String)
-> ([VRFElectionInput TestCrypto] -> ShowS)
-> Show (VRFElectionInput TestCrypto)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> VRFElectionInput TestCrypto -> ShowS
showsPrec :: Int -> VRFElectionInput TestCrypto -> ShowS
$cshow :: VRFElectionInput TestCrypto -> String
show :: VRFElectionInput TestCrypto -> String
$cshowList :: [VRFElectionInput TestCrypto] -> ShowS
showList :: [VRFElectionInput TestCrypto] -> ShowS
Show, VRFElectionInput TestCrypto -> VRFElectionInput TestCrypto -> Bool
(VRFElectionInput TestCrypto
 -> VRFElectionInput TestCrypto -> Bool)
-> (VRFElectionInput TestCrypto
    -> VRFElectionInput TestCrypto -> Bool)
-> Eq (VRFElectionInput TestCrypto)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VRFElectionInput TestCrypto -> VRFElectionInput TestCrypto -> Bool
== :: VRFElectionInput TestCrypto -> VRFElectionInput TestCrypto -> Bool
$c/= :: VRFElectionInput TestCrypto -> VRFElectionInput TestCrypto -> Bool
/= :: VRFElectionInput TestCrypto -> VRFElectionInput TestCrypto -> Bool
Eq)

  newtype VRFOutput TestCrypto
    = TestVRFOutput
    { VRFOutput TestCrypto -> Signature VRF
unTestVRFOutput ::
        BLS.Signature VRF
    }
    deriving newtype (Int -> VRFOutput TestCrypto -> ShowS
[VRFOutput TestCrypto] -> ShowS
VRFOutput TestCrypto -> String
(Int -> VRFOutput TestCrypto -> ShowS)
-> (VRFOutput TestCrypto -> String)
-> ([VRFOutput TestCrypto] -> ShowS)
-> Show (VRFOutput TestCrypto)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> VRFOutput TestCrypto -> ShowS
showsPrec :: Int -> VRFOutput TestCrypto -> ShowS
$cshow :: VRFOutput TestCrypto -> String
show :: VRFOutput TestCrypto -> String
$cshowList :: [VRFOutput TestCrypto] -> ShowS
showList :: [VRFOutput TestCrypto] -> ShowS
Show, VRFOutput TestCrypto -> VRFOutput TestCrypto -> Bool
(VRFOutput TestCrypto -> VRFOutput TestCrypto -> Bool)
-> (VRFOutput TestCrypto -> VRFOutput TestCrypto -> Bool)
-> Eq (VRFOutput TestCrypto)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VRFOutput TestCrypto -> VRFOutput TestCrypto -> Bool
== :: VRFOutput TestCrypto -> VRFOutput TestCrypto -> Bool
$c/= :: VRFOutput TestCrypto -> VRFOutput TestCrypto -> Bool
/= :: VRFOutput TestCrypto -> VRFOutput TestCrypto -> Bool
Eq)

  getVRFSigningKey :: Proxy TestCrypto
-> PrivateKey TestCrypto -> VRFSigningKey TestCrypto
getVRFSigningKey Proxy TestCrypto
_ = (PrivateKey SIGN, PrivateKey VRF) -> PrivateKey VRF
PrivateKey TestCrypto -> VRFSigningKey TestCrypto
forall a b. (a, b) -> b
snd
  getVRFVerificationKey :: Proxy TestCrypto
-> PublicKey TestCrypto -> VRFVerificationKey TestCrypto
getVRFVerificationKey Proxy TestCrypto
_ = (PublicKey SIGN, PublicKey VRF) -> PublicKey VRF
PublicKey TestCrypto -> VRFVerificationKey TestCrypto
forall a b. (a, b) -> b
snd

  mkVRFElectionInput :: Nonce -> ElectionId TestCrypto -> VRFElectionInput TestCrypto
mkVRFElectionInput Nonce
epochNonce ElectionId TestCrypto
electionId =
    Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
-> VRFElectionInput TestCrypto
TestVRFElectionInput (Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
 -> VRFElectionInput TestCrypto)
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
-> VRFElectionInput TestCrypto
forall a b. (a -> b) -> a -> b
$
      ElectionId TestCrypto
-> Nonce -> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
hashVRFInput ElectionId TestCrypto
electionId Nonce
epochNonce

  evalVRF :: VRFPoolContext TestCrypto
-> VRFElectionInput TestCrypto
-> Either String (VRFOutput TestCrypto)
evalVRF VRFPoolContext TestCrypto
context (TestVRFElectionInput Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
input) =
    case VRFPoolContext TestCrypto
context of
      VRFSignContext VRFSigningKey TestCrypto
sk -> do
        let sig :: Signature VRF
sig = forall (r :: KeyRole) msg.
(SignableRepresentation msg, HasBLSContext r) =>
PrivateKey r -> msg -> Signature r
BLS.signWithRole @VRF VRFSigningKey TestCrypto
PrivateKey VRF
sk Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
input
        VRFOutput TestCrypto -> Either String (VRFOutput TestCrypto)
forall a. a -> Either String a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (VRFOutput TestCrypto -> Either String (VRFOutput TestCrypto))
-> VRFOutput TestCrypto -> Either String (VRFOutput TestCrypto)
forall a b. (a -> b) -> a -> b
$ Signature VRF -> VRFOutput TestCrypto
TestVRFOutput Signature VRF
sig
      VRFVerifyContext VRFVerificationKey TestCrypto
pk (TestVRFOutput Signature VRF
sig) -> do
        forall (r :: KeyRole) msg.
(SignableRepresentation msg, HasBLSContext r) =>
PublicKey r -> msg -> Signature r -> Either String ()
BLS.verifyWithRole @VRF VRFVerificationKey TestCrypto
PublicKey VRF
pk Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
input Signature VRF
sig
        VRFOutput TestCrypto -> Either String (VRFOutput TestCrypto)
forall a. a -> Either String a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (VRFOutput TestCrypto -> Either String (VRFOutput TestCrypto))
-> VRFOutput TestCrypto -> Either String (VRFOutput TestCrypto)
forall a b. (a -> b) -> a -> b
$ Signature VRF -> VRFOutput TestCrypto
TestVRFOutput Signature VRF
sig

  normalizeVRFOutput :: VRFOutput TestCrypto -> NormalizedVRFOutput
normalizeVRFOutput (TestVRFOutput Signature VRF
sig) =
    Signature VRF -> NormalizedVRFOutput
BLS.toNormalizedVRFOutput Signature VRF
sig

instance CryptoSupportsBatchVRFVerification TestCrypto where
  batchVerifyVRFOutputs :: NE [VRFVerificationKey TestCrypto]
-> VRFElectionInput TestCrypto
-> NE [VRFOutput TestCrypto]
-> Either String ()
batchVerifyVRFOutputs
    NE [VRFVerificationKey TestCrypto]
pks
    (TestVRFElectionInput Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
input)
    NE [VRFOutput TestCrypto]
sigs = do
      NE [PublicKey VRF]
-> Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
-> NE [Signature VRF]
-> Either String ()
forall msg.
SignableRepresentation msg =>
NE [PublicKey VRF] -> msg -> NE [Signature VRF] -> Either String ()
BLS.linearizeAndVerifyVRFs
        NE [VRFVerificationKey TestCrypto]
NE [PublicKey VRF]
pks
        Hash HASH (SigDSIGN BLS12381MinSigDSIGN)
input
        (NonEmpty (Signature VRF) -> Either String ())
-> (NE [VRFOutput TestCrypto] -> NonEmpty (Signature VRF))
-> NE [VRFOutput TestCrypto]
-> Either String ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VRFOutput TestCrypto -> Signature VRF)
-> NonEmpty (VRFOutput TestCrypto) -> NonEmpty (Signature VRF)
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VRFOutput TestCrypto -> Signature VRF
unTestVRFOutput
        (NE [VRFOutput TestCrypto] -> Either String ())
-> NE [VRFOutput TestCrypto] -> Either String ()
forall a b. (a -> b) -> a -> b
$ NE [VRFOutput TestCrypto]
sigs

-- * QuickCheck helpers

genElectionId :: Gen (ElectionId TestCrypto)
genElectionId :: Gen (ElectionId TestCrypto)
genElectionId =
  Small Word64 -> Word64
forall a. Small a -> a
getSmall (Small Word64 -> Word64) -> Gen (Small Word64) -> Gen Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (Small Word64)
forall a. Arbitrary a => Gen a
arbitrary

genVoteCandidate :: Gen (VoteCandidate TestCrypto)
genVoteCandidate :: Gen (VoteCandidate TestCrypto)
genVoteCandidate =
  [Word8] -> ByteString
BS.pack ([Word8] -> ByteString) -> Gen [Word8] -> Gen ByteString
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 (forall a. Arbitrary a => Gen a
arbitrary @Word8)

genKeyPair :: Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair :: Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair = do
  voteSigningKey <- forall (r :: KeyRole). Gen (PrivateKey r)
genPrivateKey @SIGN
  vrfSigningKey <- genPrivateKey @VRF
  let voteVerificationKey = PrivateKey SIGN -> PublicKey SIGN
forall (r :: KeyRole). PrivateKey r -> PublicKey r
BLS.derivePublicKey PrivateKey SIGN
voteSigningKey
  let vrfVerificationKey = PrivateKey VRF -> PublicKey VRF
forall (r :: KeyRole). PrivateKey r -> PublicKey r
BLS.derivePublicKey PrivateKey VRF
vrfSigningKey
  return
    ( (voteSigningKey, vrfSigningKey)
    , (voteVerificationKey, vrfVerificationKey)
    )
 where
  genPrivateKey :: forall r. Gen (BLS.PrivateKey r)
  genPrivateKey :: forall (r :: KeyRole). Gen (PrivateKey r)
genPrivateKey = do
    PrivateKey r -> Maybe (PrivateKey r) -> PrivateKey r
forall a. a -> Maybe a -> a
fromMaybe (String -> PrivateKey r
forall a. HasCallStack => String -> a
error String
"Failed to generate BLS private key")
      (Maybe (PrivateKey r) -> PrivateKey r)
-> ([Word8] -> Maybe (PrivateKey r)) -> [Word8] -> PrivateKey r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: KeyRole).
ByteString -> ByteString -> Maybe (PrivateKey r)
BLS.rawDeserialisePrivateKey @r ByteString
"TEST"
      (ByteString -> Maybe (PrivateKey r))
-> ([Word8] -> ByteString) -> [Word8] -> Maybe (PrivateKey r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
BS.pack
      ([Word8] -> PrivateKey r) -> Gen [Word8] -> Gen (PrivateKey r)
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 (forall a. Arbitrary a => Gen a
arbitrary @Word8)

-- | Swap two distinct elements in a non-empty list.
--
-- PRECONDITION: the input list must have at least two elements.
swapTwoElements :: NE [a] -> Gen (Int, Int, NE [a])
swapTwoElements :: forall a. NE [a] -> Gen (Int, Int, NE [a])
swapTwoElements NE [a]
xs = do
  let len :: Int
len = NonEmpty a -> Int
forall a. NonEmpty a -> Int
NonEmpty.length NonEmpty a
NE [a]
xs
  Bool -> Gen () -> Gen ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2) (Gen () -> Gen ()) -> Gen () -> Gen ()
forall a b. (a -> b) -> a -> b
$
    String -> Gen ()
forall a. HasCallStack => String -> a
error String
"swapTwoElements requires a list with at least two elements"

  i <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
0, Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
  j <- choose (0, len - 1) `suchThat` (/= i)
  let maybeSwap Int
k
        | Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
i = NonEmpty a -> Int -> a
forall a. HasCallStack => NonEmpty a -> Int -> a
(NonEmpty.!!) NonEmpty a
NE [a]
xs Int
j
        | Int
k Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
j = NonEmpty a -> Int -> a
forall a. HasCallStack => NonEmpty a -> Int -> a
(NonEmpty.!!) NonEmpty a
NE [a]
xs Int
i
        | Bool
otherwise = NonEmpty a -> Int -> a
forall a. HasCallStack => NonEmpty a -> Int -> a
(NonEmpty.!!) NonEmpty a
NE [a]
xs Int
k
  let xs' =
        [a] -> NonEmpty a
forall a. HasCallStack => [a] -> NonEmpty a
NonEmpty.fromList
          [ Int -> a
maybeSwap Int
k
          | Int
k <- [Int
0 .. Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
          ]
  return (i, j, xs')

-- * Smoke test properties

-- | Round trip test for vote signatures
prop_SignAndVerifyVote :: Property
prop_SignAndVerifyVote :: Property
prop_SignAndVerifyVote =
  Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Word64
Gen (ElectionId TestCrypto)
genElectionId ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
electionId ->
    Gen ByteString -> (ByteString -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen ByteString
Gen (VoteCandidate TestCrypto)
genVoteCandidate ((ByteString -> Property) -> Property)
-> (ByteString -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \ByteString
candidate ->
      Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair ((((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
  -> Property)
 -> Property)
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \((PrivateKey SIGN, PrivateKey VRF)
sk, (PublicKey SIGN, PublicKey VRF)
pk) -> do
        let voteSigningKey :: VoteSigningKey TestCrypto
voteSigningKey = Proxy TestCrypto
-> PrivateKey TestCrypto -> VoteSigningKey TestCrypto
forall crypto.
CryptoSupportsVoteSigning crypto =>
Proxy crypto -> PrivateKey crypto -> VoteSigningKey crypto
getVoteSigningKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto) (PrivateKey SIGN, PrivateKey VRF)
PrivateKey TestCrypto
sk
        let voteVerificationKey :: VoteVerificationKey TestCrypto
voteVerificationKey = Proxy TestCrypto
-> PublicKey TestCrypto -> VoteVerificationKey TestCrypto
forall crypto.
CryptoSupportsVoteSigning crypto =>
Proxy crypto -> PublicKey crypto -> VoteVerificationKey crypto
getVoteVerificationKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto) (PublicKey SIGN, PublicKey VRF)
PublicKey TestCrypto
pk
        let sig :: VoteSignature TestCrypto
sig = forall crypto.
CryptoSupportsVoteSigning crypto =>
VoteSigningKey crypto
-> ElectionId crypto
-> VoteCandidate crypto
-> VoteSignature crypto
signVote @TestCrypto VoteSigningKey TestCrypto
voteSigningKey Word64
ElectionId TestCrypto
electionId ByteString
VoteCandidate TestCrypto
candidate
        case ( forall crypto.
CryptoSupportsVoteSigning crypto =>
VoteVerificationKey crypto
-> ElectionId crypto
-> VoteCandidate crypto
-> VoteSignature crypto
-> Either String ()
verifyVoteSignature @TestCrypto
                 VoteVerificationKey TestCrypto
voteVerificationKey
                 Word64
ElectionId TestCrypto
electionId
                 ByteString
VoteCandidate TestCrypto
candidate
                 VoteSignature TestCrypto
sig
             ) of
          Left String
err ->
            String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
              (String
"Round trip verification failed: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err)
              (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
          Right () ->
            Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True

-- | Round trip test for aggregate vote signatures
prop_SignAndVerifyAggregateVote :: Property
prop_SignAndVerifyAggregateVote :: Property
prop_SignAndVerifyAggregateVote =
  Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Word64
Gen (ElectionId TestCrypto)
genElectionId ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
electionId ->
    Gen ByteString -> (ByteString -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen ByteString
Gen (VoteCandidate TestCrypto)
genVoteCandidate ((ByteString -> Property) -> Property)
-> (ByteString -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \ByteString
candidate ->
      Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll ((Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
10)) ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
numSigners ->
        Gen
  [((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))]
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Int
-> Gen
     ((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))
-> Gen
     [((PrivateKey SIGN, PrivateKey VRF),
       (PublicKey SIGN, PublicKey VRF))]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
numSigners Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair) (([((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))]
  -> Property)
 -> Property)
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \[((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))]
keyPairs -> do
          let (NonEmpty (PrivateKey SIGN)
voteSigningKeys, NonEmpty (PublicKey SIGN)
voteVerificationKeys) =
                NonEmpty (PrivateKey SIGN, PublicKey SIGN)
-> (NonEmpty (PrivateKey SIGN), NonEmpty (PublicKey SIGN))
forall a b. NonEmpty (a, b) -> (NonEmpty a, NonEmpty b)
forall (m :: * -> *) a b. MonadZip m => m (a, b) -> (m a, m b)
munzip
                  (NonEmpty (PrivateKey SIGN, PublicKey SIGN)
 -> (NonEmpty (PrivateKey SIGN), NonEmpty (PublicKey SIGN)))
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> NonEmpty (PrivateKey SIGN, PublicKey SIGN))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> (NonEmpty (PrivateKey SIGN), NonEmpty (PublicKey SIGN))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(PrivateKey SIGN, PublicKey SIGN)]
-> NonEmpty (PrivateKey SIGN, PublicKey SIGN)
forall a. HasCallStack => [a] -> NonEmpty a
NonEmpty.fromList
                  ([(PrivateKey SIGN, PublicKey SIGN)]
 -> NonEmpty (PrivateKey SIGN, PublicKey SIGN))
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> [(PrivateKey SIGN, PublicKey SIGN)])
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> NonEmpty (PrivateKey SIGN, PublicKey SIGN)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((PrivateKey SIGN, PrivateKey VRF), PublicKey SIGN)
 -> (PrivateKey SIGN, PublicKey SIGN))
-> [((PrivateKey SIGN, PrivateKey VRF), PublicKey SIGN)]
-> [(PrivateKey SIGN, PublicKey SIGN)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((PrivateKey SIGN, PrivateKey VRF) -> PrivateKey SIGN)
-> ((PrivateKey SIGN, PrivateKey VRF), PublicKey SIGN)
-> (PrivateKey SIGN, PublicKey SIGN)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (Proxy TestCrypto
-> PrivateKey TestCrypto -> VoteSigningKey TestCrypto
forall crypto.
CryptoSupportsVoteSigning crypto =>
Proxy crypto -> PrivateKey crypto -> VoteSigningKey crypto
getVoteSigningKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)))
                  ([((PrivateKey SIGN, PrivateKey VRF), PublicKey SIGN)]
 -> [(PrivateKey SIGN, PublicKey SIGN)])
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> [((PrivateKey SIGN, PrivateKey VRF), PublicKey SIGN)])
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> [(PrivateKey SIGN, PublicKey SIGN)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))
 -> ((PrivateKey SIGN, PrivateKey VRF), PublicKey SIGN))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> [((PrivateKey SIGN, PrivateKey VRF), PublicKey SIGN)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((PublicKey SIGN, PublicKey VRF) -> PublicKey SIGN)
-> ((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))
-> ((PrivateKey SIGN, PrivateKey VRF), PublicKey SIGN)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (Proxy TestCrypto
-> PublicKey TestCrypto -> VoteVerificationKey TestCrypto
forall crypto.
CryptoSupportsVoteSigning crypto =>
Proxy crypto -> PublicKey crypto -> VoteVerificationKey crypto
getVoteVerificationKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)))
                  ([((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))]
 -> (NonEmpty (PrivateKey SIGN), NonEmpty (PublicKey SIGN)))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> (NonEmpty (PrivateKey SIGN), NonEmpty (PublicKey SIGN))
forall a b. (a -> b) -> a -> b
$ [((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))]
keyPairs
          let aggVoteSignature :: VoteSignature TestCrypto
aggVoteSignature =
                VoteSignature TestCrypto
-> Either String (VoteSignature TestCrypto)
-> VoteSignature TestCrypto
forall b a. b -> Either a b -> b
fromRight (String -> VoteSignature TestCrypto
forall a. HasCallStack => String -> a
error String
"Failed to aggregate vote signatures")
                  (Either String (VoteSignature TestCrypto)
 -> VoteSignature TestCrypto)
-> (NonEmpty (PrivateKey SIGN)
    -> Either String (VoteSignature TestCrypto))
-> NonEmpty (PrivateKey SIGN)
-> VoteSignature TestCrypto
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy TestCrypto
-> NE [VoteSignature TestCrypto]
-> Either String (AggregateVoteSignature TestCrypto)
forall crypto.
CryptoSupportsAggregateVoteSigning crypto =>
Proxy crypto
-> NE [VoteSignature crypto]
-> Either String (AggregateVoteSignature crypto)
aggregateVoteSignatures (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)
                  (NonEmpty (VoteSignature TestCrypto)
 -> Either String (VoteSignature TestCrypto))
-> (NonEmpty (PrivateKey SIGN)
    -> NonEmpty (VoteSignature TestCrypto))
-> NonEmpty (PrivateKey SIGN)
-> Either String (VoteSignature TestCrypto)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PrivateKey SIGN -> VoteSignature TestCrypto)
-> NonEmpty (PrivateKey SIGN)
-> NonEmpty (VoteSignature TestCrypto)
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\PrivateKey SIGN
sk -> forall crypto.
CryptoSupportsVoteSigning crypto =>
VoteSigningKey crypto
-> ElectionId crypto
-> VoteCandidate crypto
-> VoteSignature crypto
signVote @TestCrypto VoteSigningKey TestCrypto
PrivateKey SIGN
sk Word64
ElectionId TestCrypto
electionId ByteString
VoteCandidate TestCrypto
candidate)
                  (NonEmpty (PrivateKey SIGN) -> VoteSignature TestCrypto)
-> NonEmpty (PrivateKey SIGN) -> VoteSignature TestCrypto
forall a b. (a -> b) -> a -> b
$ NonEmpty (PrivateKey SIGN)
voteSigningKeys
          let aggVoteVerificationKey :: PublicKey SIGN
aggVoteVerificationKey =
                PublicKey SIGN -> Either String (PublicKey SIGN) -> PublicKey SIGN
forall b a. b -> Either a b -> b
fromRight (String -> PublicKey SIGN
forall a. HasCallStack => String -> a
error String
"Failed to aggregate vote verification keys")
                  (Either String (PublicKey SIGN) -> PublicKey SIGN)
-> (NonEmpty (PublicKey SIGN) -> Either String (PublicKey SIGN))
-> NonEmpty (PublicKey SIGN)
-> PublicKey SIGN
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy TestCrypto
-> NE [VoteVerificationKey TestCrypto]
-> Either String (AggregateVoteVerificationKey TestCrypto)
forall crypto.
CryptoSupportsAggregateVoteSigning crypto =>
Proxy crypto
-> NE [VoteVerificationKey crypto]
-> Either String (AggregateVoteVerificationKey crypto)
aggregateVoteVerificationKeys (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)
                  (NonEmpty (PublicKey SIGN) -> PublicKey SIGN)
-> NonEmpty (PublicKey SIGN) -> PublicKey SIGN
forall a b. (a -> b) -> a -> b
$ NonEmpty (PublicKey SIGN)
voteVerificationKeys
          String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate String
"Number of vote signers" [Int -> String
forall a. Show a => a -> String
show Int
numSigners] (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
            case ( Proxy TestCrypto
-> AggregateVoteVerificationKey TestCrypto
-> ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> AggregateVoteSignature TestCrypto
-> Either String ()
forall crypto.
CryptoSupportsAggregateVoteSigning crypto =>
Proxy crypto
-> AggregateVoteVerificationKey crypto
-> ElectionId crypto
-> VoteCandidate crypto
-> AggregateVoteSignature crypto
-> Either String ()
verifyAggregateVoteSignature
                     (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)
                     AggregateVoteVerificationKey TestCrypto
PublicKey SIGN
aggVoteVerificationKey
                     Word64
ElectionId TestCrypto
electionId
                     ByteString
VoteCandidate TestCrypto
candidate
                     AggregateVoteSignature TestCrypto
VoteSignature TestCrypto
aggVoteSignature
                 ) of
              Left String
err ->
                String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
                  (String
"Aggregate vote verification failed: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err)
                  (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
              Right () ->
                Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True

-- | Round trip test for VRF evaluation
prop_EvalAndVerifyVRFOutput :: Property
prop_EvalAndVerifyVRFOutput :: Property
prop_EvalAndVerifyVRFOutput =
  Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Word64
Gen (ElectionId TestCrypto)
genElectionId ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
electionId ->
    Gen Nonce -> (Nonce -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Nonce
genEpochNonce ((Nonce -> Property) -> Property)
-> (Nonce -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Nonce
epochNonce ->
      Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair ((((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
  -> Property)
 -> Property)
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \((PrivateKey SIGN, PrivateKey VRF)
sk, (PublicKey SIGN, PublicKey VRF)
pk) -> do
        let vrfSigningKey :: VRFSigningKey TestCrypto
vrfSigningKey = Proxy TestCrypto
-> PrivateKey TestCrypto -> VRFSigningKey TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Proxy crypto -> PrivateKey crypto -> VRFSigningKey crypto
getVRFSigningKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto) (PrivateKey SIGN, PrivateKey VRF)
PrivateKey TestCrypto
sk
        let vrfVerificationKey :: VRFVerificationKey TestCrypto
vrfVerificationKey = Proxy TestCrypto
-> PublicKey TestCrypto -> VRFVerificationKey TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Proxy crypto -> PublicKey crypto -> VRFVerificationKey crypto
getVRFVerificationKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto) (PublicKey SIGN, PublicKey VRF)
PublicKey TestCrypto
pk
        let input :: VRFElectionInput TestCrypto
input = forall crypto.
CryptoSupportsVRF crypto =>
Nonce -> ElectionId crypto -> VRFElectionInput crypto
mkVRFElectionInput @TestCrypto Nonce
epochNonce Word64
ElectionId TestCrypto
electionId
        case ( forall crypto.
CryptoSupportsVRF crypto =>
VRFPoolContext crypto
-> VRFElectionInput crypto -> Either String (VRFOutput crypto)
evalVRF @TestCrypto
                 (VRFSigningKey TestCrypto -> VRFPoolContext TestCrypto
forall crypto. VRFSigningKey crypto -> VRFPoolContext crypto
VRFSignContext VRFSigningKey TestCrypto
vrfSigningKey)
                 VRFElectionInput TestCrypto
input
             ) of
          Left String
err ->
            String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
              (String
"VRF evaluation failed: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err)
              (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
          Right VRFOutput TestCrypto
output ->
            case ( forall crypto.
CryptoSupportsVRF crypto =>
VRFPoolContext crypto
-> VRFElectionInput crypto -> Either String (VRFOutput crypto)
evalVRF @TestCrypto
                     (VRFVerificationKey TestCrypto
-> VRFOutput TestCrypto -> VRFPoolContext TestCrypto
forall crypto.
VRFVerificationKey crypto
-> VRFOutput crypto -> VRFPoolContext crypto
VRFVerifyContext VRFVerificationKey TestCrypto
vrfVerificationKey VRFOutput TestCrypto
output)
                     VRFElectionInput TestCrypto
input
                 ) of
              Left String
err ->
                String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
                  (String
"VRF verification failed: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err)
                  (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
              Right VRFOutput TestCrypto
output' ->
                String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
                  String
"VRF output mismatch"
                  (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ VRFOutput TestCrypto
output VRFOutput TestCrypto -> VRFOutput TestCrypto -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== VRFOutput TestCrypto
output'

-- | Round trip test for aggregate VRF evaluation
prop_EvalAndVerifyAggregateVRFOutput :: Property
prop_EvalAndVerifyAggregateVRFOutput :: Property
prop_EvalAndVerifyAggregateVRFOutput =
  Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Word64
Gen (ElectionId TestCrypto)
genElectionId ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
electionId ->
    Gen Nonce -> (Nonce -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Nonce
genEpochNonce ((Nonce -> Property) -> Property)
-> (Nonce -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Nonce
epochNonce ->
      Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll ((Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
10)) ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
numSigners ->
        Gen
  [((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))]
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Int
-> Gen
     ((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))
-> Gen
     [((PrivateKey SIGN, PrivateKey VRF),
       (PublicKey SIGN, PublicKey VRF))]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
numSigners Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair) (([((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))]
  -> Property)
 -> Property)
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \[((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))]
keyPairs -> do
          let (NonEmpty (PrivateKey VRF)
vrfSigningKeys, NonEmpty (PublicKey VRF)
vrfVerificationKeys) =
                NonEmpty (PrivateKey VRF, PublicKey VRF)
-> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF))
forall a b. NonEmpty (a, b) -> (NonEmpty a, NonEmpty b)
forall (m :: * -> *) a b. MonadZip m => m (a, b) -> (m a, m b)
munzip
                  (NonEmpty (PrivateKey VRF, PublicKey VRF)
 -> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF)))
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> NonEmpty (PrivateKey VRF, PublicKey VRF))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(PrivateKey VRF, PublicKey VRF)]
-> NonEmpty (PrivateKey VRF, PublicKey VRF)
forall a. HasCallStack => [a] -> NonEmpty a
NonEmpty.fromList
                  ([(PrivateKey VRF, PublicKey VRF)]
 -> NonEmpty (PrivateKey VRF, PublicKey VRF))
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> [(PrivateKey VRF, PublicKey VRF)])
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> NonEmpty (PrivateKey VRF, PublicKey VRF)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)
 -> (PrivateKey VRF, PublicKey VRF))
-> [((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)]
-> [(PrivateKey VRF, PublicKey VRF)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((PrivateKey SIGN, PrivateKey VRF) -> PrivateKey VRF)
-> ((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)
-> (PrivateKey VRF, PublicKey VRF)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (Proxy TestCrypto
-> PrivateKey TestCrypto -> VRFSigningKey TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Proxy crypto -> PrivateKey crypto -> VRFSigningKey crypto
getVRFSigningKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)))
                  ([((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)]
 -> [(PrivateKey VRF, PublicKey VRF)])
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> [((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)])
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> [(PrivateKey VRF, PublicKey VRF)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))
 -> ((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> [((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((PublicKey SIGN, PublicKey VRF) -> PublicKey VRF)
-> ((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))
-> ((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (Proxy TestCrypto
-> PublicKey TestCrypto -> VRFVerificationKey TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Proxy crypto -> PublicKey crypto -> VRFVerificationKey crypto
getVRFVerificationKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)))
                  ([((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))]
 -> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF)))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF))
forall a b. (a -> b) -> a -> b
$ [((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))]
keyPairs
          let input :: VRFElectionInput TestCrypto
input = forall crypto.
CryptoSupportsVRF crypto =>
Nonce -> ElectionId crypto -> VRFElectionInput crypto
mkVRFElectionInput @TestCrypto Nonce
epochNonce Word64
ElectionId TestCrypto
electionId
          String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate String
"Number of VRF signers" [Int -> String
forall a. Show a => a -> String
show Int
numSigners] (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
            case ( (PrivateKey VRF -> Either String (VRFOutput TestCrypto))
-> NonEmpty (PrivateKey VRF)
-> Either String (NonEmpty (VRFOutput TestCrypto))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> NonEmpty a -> f (NonEmpty b)
traverse
                     (\PrivateKey VRF
sk -> forall crypto.
CryptoSupportsVRF crypto =>
VRFPoolContext crypto
-> VRFElectionInput crypto -> Either String (VRFOutput crypto)
evalVRF @TestCrypto (VRFSigningKey TestCrypto -> VRFPoolContext TestCrypto
forall crypto. VRFSigningKey crypto -> VRFPoolContext crypto
VRFSignContext VRFSigningKey TestCrypto
PrivateKey VRF
sk) VRFElectionInput TestCrypto
input)
                     NonEmpty (PrivateKey VRF)
vrfSigningKeys
                 ) of
              Left String
err ->
                String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
                  (String
"VRF evaluation failed: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err)
                  (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
              Right NonEmpty (VRFOutput TestCrypto)
vrfOutputs -> do
                case ( forall crypto.
CryptoSupportsBatchVRFVerification crypto =>
NE [VRFVerificationKey crypto]
-> VRFElectionInput crypto
-> NE [VRFOutput crypto]
-> Either String ()
batchVerifyVRFOutputs @TestCrypto
                         NonEmpty (PublicKey VRF)
NE [VRFVerificationKey TestCrypto]
vrfVerificationKeys
                         VRFElectionInput TestCrypto
input
                         NonEmpty (VRFOutput TestCrypto)
NE [VRFOutput TestCrypto]
vrfOutputs
                     ) of
                  Left String
err ->
                    String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
                      (String
"Aggregate VRF verification failed: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err)
                      (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
                  Right () ->
                    Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True

-- | Test resilience against swap attacks on aggregate VRF verification
prop_SwapAttackOnAggregateVRF :: Property
prop_SwapAttackOnAggregateVRF :: Property
prop_SwapAttackOnAggregateVRF =
  Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Word64
Gen (ElectionId TestCrypto)
genElectionId ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
electionId ->
    Gen Nonce -> (Nonce -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Nonce
genEpochNonce ((Nonce -> Property) -> Property)
-> (Nonce -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Nonce
epochNonce ->
      Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll ((Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
2, Int
10)) ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
numSigners ->
        Gen
  [((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))]
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Int
-> Gen
     ((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))
-> Gen
     [((PrivateKey SIGN, PrivateKey VRF),
       (PublicKey SIGN, PublicKey VRF))]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
numSigners Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair) (([((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))]
  -> Property)
 -> Property)
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \[((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))]
keyPairs -> do
          let (NonEmpty (PrivateKey VRF)
vrfSigningKeys, NonEmpty (PublicKey VRF)
vrfVerificationKeys) =
                NonEmpty (PrivateKey VRF, PublicKey VRF)
-> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF))
forall a b. NonEmpty (a, b) -> (NonEmpty a, NonEmpty b)
forall (m :: * -> *) a b. MonadZip m => m (a, b) -> (m a, m b)
munzip
                  (NonEmpty (PrivateKey VRF, PublicKey VRF)
 -> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF)))
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> NonEmpty (PrivateKey VRF, PublicKey VRF))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(PrivateKey VRF, PublicKey VRF)]
-> NonEmpty (PrivateKey VRF, PublicKey VRF)
forall a. HasCallStack => [a] -> NonEmpty a
NonEmpty.fromList
                  ([(PrivateKey VRF, PublicKey VRF)]
 -> NonEmpty (PrivateKey VRF, PublicKey VRF))
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> [(PrivateKey VRF, PublicKey VRF)])
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> NonEmpty (PrivateKey VRF, PublicKey VRF)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)
 -> (PrivateKey VRF, PublicKey VRF))
-> [((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)]
-> [(PrivateKey VRF, PublicKey VRF)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((PrivateKey SIGN, PrivateKey VRF) -> PrivateKey VRF)
-> ((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)
-> (PrivateKey VRF, PublicKey VRF)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (Proxy TestCrypto
-> PrivateKey TestCrypto -> VRFSigningKey TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Proxy crypto -> PrivateKey crypto -> VRFSigningKey crypto
getVRFSigningKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)))
                  ([((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)]
 -> [(PrivateKey VRF, PublicKey VRF)])
-> ([((PrivateKey SIGN, PrivateKey VRF),
      (PublicKey SIGN, PublicKey VRF))]
    -> [((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)])
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> [(PrivateKey VRF, PublicKey VRF)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))
 -> ((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> [((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((PublicKey SIGN, PublicKey VRF) -> PublicKey VRF)
-> ((PrivateKey SIGN, PrivateKey VRF),
    (PublicKey SIGN, PublicKey VRF))
-> ((PrivateKey SIGN, PrivateKey VRF), PublicKey VRF)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (Proxy TestCrypto
-> PublicKey TestCrypto -> VRFVerificationKey TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Proxy crypto -> PublicKey crypto -> VRFVerificationKey crypto
getVRFVerificationKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)))
                  ([((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))]
 -> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF)))
-> [((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))]
-> (NonEmpty (PrivateKey VRF), NonEmpty (PublicKey VRF))
forall a b. (a -> b) -> a -> b
$ [((PrivateKey SIGN, PrivateKey VRF),
  (PublicKey SIGN, PublicKey VRF))]
keyPairs
          let input :: VRFElectionInput TestCrypto
input = forall crypto.
CryptoSupportsVRF crypto =>
Nonce -> ElectionId crypto -> VRFElectionInput crypto
mkVRFElectionInput @TestCrypto Nonce
epochNonce Word64
ElectionId TestCrypto
electionId
          String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate String
"Number of VRF signers" [Int -> String
forall a. Show a => a -> String
show Int
numSigners] (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
            case ( (PrivateKey VRF -> Either String (VRFOutput TestCrypto))
-> NonEmpty (PrivateKey VRF)
-> Either String (NonEmpty (VRFOutput TestCrypto))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> NonEmpty a -> f (NonEmpty b)
traverse
                     (\PrivateKey VRF
sk -> forall crypto.
CryptoSupportsVRF crypto =>
VRFPoolContext crypto
-> VRFElectionInput crypto -> Either String (VRFOutput crypto)
evalVRF @TestCrypto (VRFSigningKey TestCrypto -> VRFPoolContext TestCrypto
forall crypto. VRFSigningKey crypto -> VRFPoolContext crypto
VRFSignContext VRFSigningKey TestCrypto
PrivateKey VRF
sk) VRFElectionInput TestCrypto
input)
                     NonEmpty (PrivateKey VRF)
vrfSigningKeys
                 ) of
              Left String
err ->
                String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
                  (String
"VRF evaluation failed: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err)
                  (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
              Right NonEmpty (VRFOutput TestCrypto)
vrfOutputs -> do
                Gen (Int, Int, NonEmpty (VRFOutput TestCrypto))
-> ((Int, Int, NonEmpty (VRFOutput TestCrypto)) -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (NE [VRFOutput TestCrypto]
-> Gen (Int, Int, NE [VRFOutput TestCrypto])
forall a. NE [a] -> Gen (Int, Int, NE [a])
swapTwoElements NonEmpty (VRFOutput TestCrypto)
NE [VRFOutput TestCrypto]
vrfOutputs) (((Int, Int, NonEmpty (VRFOutput TestCrypto)) -> Property)
 -> Property)
-> ((Int, Int, NonEmpty (VRFOutput TestCrypto)) -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \(Int
i, Int
j, NonEmpty (VRFOutput TestCrypto)
swappedVRFOutputs) -> do
                  case ( forall crypto.
CryptoSupportsBatchVRFVerification crypto =>
NE [VRFVerificationKey crypto]
-> VRFElectionInput crypto
-> NE [VRFOutput crypto]
-> Either String ()
batchVerifyVRFOutputs @TestCrypto
                           NonEmpty (PublicKey VRF)
NE [VRFVerificationKey TestCrypto]
vrfVerificationKeys
                           VRFElectionInput TestCrypto
input
                           NonEmpty (VRFOutput TestCrypto)
NE [VRFOutput TestCrypto]
swappedVRFOutputs
                       ) of
                    Left String
_ ->
                      Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True
                    Right () ->
                      String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
                        ( String
"Aggregate VRF verification should have failed when "
                            String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"swapping outputs at indices "
                            String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i
                            String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" and "
                            String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
j
                        )
                        (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False

-- | Associativity of aggregate vote verification keys.
--
-- NOTE: this is desirable if we want aggregate keys to be a closed Semigroup
-- under real BLS aggregation (modulo rare aggregation failures). This means
-- that we can either choose to collect all keys and aggregate them at once, or
-- we can partially aggregate them as we go, keeping only a single aggregate key
-- in memory at any time.
prop_AssociativityOfAggregateKeys :: Property
prop_AssociativityOfAggregateKeys :: Property
prop_AssociativityOfAggregateKeys =
  Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair ((((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
  -> Property)
 -> Property)
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pk1) ->
    Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair ((((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
  -> Property)
 -> Property)
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pk2) ->
      Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair ((((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
  -> Property)
 -> Property)
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pk3) -> do
        let toAggKey :: (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey SIGN)
toAggKey (PublicKey SIGN, PublicKey VRF)
pk =
              PublicKey SIGN -> NonEmpty (PublicKey SIGN)
forall a. a -> NonEmpty a
NonEmpty.singleton
                (PublicKey SIGN -> NonEmpty (PublicKey SIGN))
-> ((PublicKey SIGN, PublicKey VRF) -> PublicKey SIGN)
-> (PublicKey SIGN, PublicKey VRF)
-> NonEmpty (PublicKey SIGN)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy TestCrypto
-> PublicKey TestCrypto -> VoteVerificationKey TestCrypto
forall crypto.
CryptoSupportsVoteSigning crypto =>
Proxy crypto -> PublicKey crypto -> VoteVerificationKey crypto
getVoteVerificationKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)
                ((PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey SIGN))
-> (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey SIGN)
forall a b. (a -> b) -> a -> b
$ (PublicKey SIGN, PublicKey VRF)
pk
        let pk1' :: NonEmpty (PublicKey SIGN)
pk1' = (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey SIGN)
toAggKey (PublicKey SIGN, PublicKey VRF)
pk1
        let pk2' :: NonEmpty (PublicKey SIGN)
pk2' = (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey SIGN)
toAggKey (PublicKey SIGN, PublicKey VRF)
pk2
        let pk3' :: NonEmpty (PublicKey SIGN)
pk3' = (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey SIGN)
toAggKey (PublicKey SIGN, PublicKey VRF)
pk3
        let lhs :: Either String (PublicKey SIGN)
lhs = do
              pk12' <- PublicKey SIGN -> NonEmpty (PublicKey SIGN)
forall a. a -> NonEmpty a
NonEmpty.singleton (PublicKey SIGN -> NonEmpty (PublicKey SIGN))
-> Either String (PublicKey SIGN)
-> Either String (NonEmpty (PublicKey SIGN))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NE [PublicKey SIGN] -> Either String (PublicKey SIGN)
forall (r :: KeyRole).
NE [PublicKey r] -> Either String (PublicKey r)
BLS.aggregatePublicKeys (NonEmpty (PublicKey SIGN)
pk1' NonEmpty (PublicKey SIGN)
-> NonEmpty (PublicKey SIGN) -> NonEmpty (PublicKey SIGN)
forall a. Semigroup a => a -> a -> a
<> NonEmpty (PublicKey SIGN)
pk2')
              BLS.aggregatePublicKeys (pk12' <> pk3')
        let rhs :: Either String (PublicKey SIGN)
rhs = do
              pk23' <- PublicKey SIGN -> NonEmpty (PublicKey SIGN)
forall a. a -> NonEmpty a
NonEmpty.singleton (PublicKey SIGN -> NonEmpty (PublicKey SIGN))
-> Either String (PublicKey SIGN)
-> Either String (NonEmpty (PublicKey SIGN))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NE [PublicKey SIGN] -> Either String (PublicKey SIGN)
forall (r :: KeyRole).
NE [PublicKey r] -> Either String (PublicKey r)
BLS.aggregatePublicKeys (NonEmpty (PublicKey SIGN)
pk2' NonEmpty (PublicKey SIGN)
-> NonEmpty (PublicKey SIGN) -> NonEmpty (PublicKey SIGN)
forall a. Semigroup a => a -> a -> a
<> NonEmpty (PublicKey SIGN)
pk3')
              BLS.aggregatePublicKeys (pk1' <> pk23')
        String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
          String
"Aggregate vote verification keys should be associative"
          (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Either String (PublicKey SIGN)
lhs Either String (PublicKey SIGN)
-> Either String (PublicKey SIGN) -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Either String (PublicKey SIGN)
rhs

-- | Associativity of aggregate VRF verification keys.
--
-- NOTE: this is desirable if we want aggregate keys to be a closed Semigroup
-- under real BLS aggregation (modulo rare aggregation failures). This means
-- that we can either choose to collect all keys and aggregate them at once, or
-- we can partially aggregate them as we go, keeping only a single aggregate key
-- in memory at any time.
prop_AssociativityOfAggregateVRFKeys :: Property
prop_AssociativityOfAggregateVRFKeys :: Property
prop_AssociativityOfAggregateVRFKeys =
  Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair ((((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
  -> Property)
 -> Property)
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pk1) ->
    Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair ((((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
  -> Property)
 -> Property)
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pk2) ->
      Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen
  ((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
genKeyPair ((((PrivateKey SIGN, PrivateKey VRF),
   (PublicKey SIGN, PublicKey VRF))
  -> Property)
 -> Property)
-> (((PrivateKey SIGN, PrivateKey VRF),
     (PublicKey SIGN, PublicKey VRF))
    -> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pk3) -> do
        let toAggKey :: (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey VRF)
toAggKey (PublicKey SIGN, PublicKey VRF)
pk =
              PublicKey VRF -> NonEmpty (PublicKey VRF)
forall a. a -> NonEmpty a
NonEmpty.singleton
                (PublicKey VRF -> NonEmpty (PublicKey VRF))
-> ((PublicKey SIGN, PublicKey VRF) -> PublicKey VRF)
-> (PublicKey SIGN, PublicKey VRF)
-> NonEmpty (PublicKey VRF)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy TestCrypto
-> PublicKey TestCrypto -> VRFVerificationKey TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Proxy crypto -> PublicKey crypto -> VRFVerificationKey crypto
getVRFVerificationKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto)
                ((PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey VRF))
-> (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey VRF)
forall a b. (a -> b) -> a -> b
$ (PublicKey SIGN, PublicKey VRF)
pk
        let pk1' :: NonEmpty (PublicKey VRF)
pk1' = (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey VRF)
toAggKey (PublicKey SIGN, PublicKey VRF)
pk1
        let pk2' :: NonEmpty (PublicKey VRF)
pk2' = (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey VRF)
toAggKey (PublicKey SIGN, PublicKey VRF)
pk2
        let pk3' :: NonEmpty (PublicKey VRF)
pk3' = (PublicKey SIGN, PublicKey VRF) -> NonEmpty (PublicKey VRF)
toAggKey (PublicKey SIGN, PublicKey VRF)
pk3
        let lhs :: Either String (PublicKey VRF)
lhs = do
              pk12' <- PublicKey VRF -> NonEmpty (PublicKey VRF)
forall a. a -> NonEmpty a
NonEmpty.singleton (PublicKey VRF -> NonEmpty (PublicKey VRF))
-> Either String (PublicKey VRF)
-> Either String (NonEmpty (PublicKey VRF))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NE [PublicKey VRF] -> Either String (PublicKey VRF)
forall (r :: KeyRole).
NE [PublicKey r] -> Either String (PublicKey r)
BLS.aggregatePublicKeys (NonEmpty (PublicKey VRF)
pk1' NonEmpty (PublicKey VRF)
-> NonEmpty (PublicKey VRF) -> NonEmpty (PublicKey VRF)
forall a. Semigroup a => a -> a -> a
<> NonEmpty (PublicKey VRF)
pk2')
              BLS.aggregatePublicKeys (pk12' <> pk3')
        let rhs :: Either String (PublicKey VRF)
rhs = do
              pk23' <- PublicKey VRF -> NonEmpty (PublicKey VRF)
forall a. a -> NonEmpty a
NonEmpty.singleton (PublicKey VRF -> NonEmpty (PublicKey VRF))
-> Either String (PublicKey VRF)
-> Either String (NonEmpty (PublicKey VRF))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NE [PublicKey VRF] -> Either String (PublicKey VRF)
forall (r :: KeyRole).
NE [PublicKey r] -> Either String (PublicKey r)
BLS.aggregatePublicKeys (NonEmpty (PublicKey VRF)
pk2' NonEmpty (PublicKey VRF)
-> NonEmpty (PublicKey VRF) -> NonEmpty (PublicKey VRF)
forall a. Semigroup a => a -> a -> a
<> NonEmpty (PublicKey VRF)
pk3')
              BLS.aggregatePublicKeys (pk1' <> pk23')
        String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
          String
"Aggregate VRF verification keys should be associative"
          (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Either String (PublicKey VRF)
lhs Either String (PublicKey VRF)
-> Either String (PublicKey VRF) -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Either String (PublicKey VRF)
rhs

tests :: TestTree
tests :: TestTree
tests =
  String -> [TestTree] -> TestTree
testGroup
    String
"TestCrypto properties"
    [ (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
        String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
          String
"prop_SignAndVerifyVote"
          Property
prop_SignAndVerifyVote
    , (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
        String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
          String
"prop_SignAndVerifyAggregateVote"
          Property
prop_SignAndVerifyAggregateVote
    , (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
        String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
          String
"prop_EvalAndVerifyVRFOutput"
          Property
prop_EvalAndVerifyVRFOutput
    , (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
        String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
          String
"prop_EvalAndVerifyAggregateVRFOutput"
          Property
prop_EvalAndVerifyAggregateVRFOutput
    , (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
        String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
          String
"prop_SwapAttackOnAggregateVRF"
          Property
prop_SwapAttackOnAggregateVRF
    , (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
        String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
          String
"prop_AssociativityOfAggregateKeys"
          Property
prop_AssociativityOfAggregateKeys
    , (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
        String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
          String
"prop_AssociativityOfAggregateVRFKeys"
          Property
prop_AssociativityOfAggregateVRFKeys
    ]