hjugement-protocol-0.0.8.20191027: benchmarks/Election.hs
{-# LANGUAGE OverloadedStrings #-}
module Election where
import Control.DeepSeq (NFData)
import qualified Data.List as List
import qualified Data.Text as Text
import qualified Text.Printf as Printf
import qualified Data.Aeson as JSON
import Voting.Protocol
import Utils
makeElection ::
forall crypto v c.
Reifies v Version =>
Reifies c crypto =>
JSON.ToJSON crypto =>
JSON.ToJSON (FieldElement crypto c) =>
Key crypto =>
Int -> Int -> Election crypto v c
makeElection nQuests nChoices = elec
where
election_uuid = UUID "xLcs7ev6Jy6FHH"
elec = Election
{ election_name = Text.pack $ "elec"<>show nQuests<>show nChoices
, election_description = "benchmarkable election"
, election_uuid
, election_crypto = reflect (Proxy @c)
, election_public_key =
let secKey = credentialSecretKey election_uuid (Credential "xLcs7ev6Jy6FHHE") in
publicKey secKey
, election_hash = hashElection elec
, election_version = Just (reflect (Proxy @v))
, election_questions =
(<$> [1..nQuests]) $ \quest -> Question
{ question_text = Text.pack $ "quest"<>show quest
, question_choices = (<$> [1..nChoices]) $ \choice -> Text.pack $ "choice"<>show choice
, question_mini = one
, question_maxi = one -- sum $ List.replicate nChoices one
}
}
makeVotes :: Election crypto v c -> [[Bool]]
makeVotes Election{..} =
[ True : List.tail [ False | _choice <- question_choices quest ]
| quest <- election_questions
]
makeBallot ::
Reifies v Version =>
Reifies c crypto =>
Group crypto =>
Key crypto =>
Multiplicative (FieldElement crypto c) =>
ToNatural (FieldElement crypto c) =>
Election crypto v c -> Ballot crypto v c
makeBallot elec =
case runExcept $ (`evalStateT` mkStdGen seed) $ do
ballotSecKey <- randomSecretKey
encryptBallot elec (Just ballotSecKey) $
makeVotes elec of
Right ballot -> ballot
Left err -> error ("encryptBallot: "<>show err)
where
seed = 0
titleElection :: Election crypto v c -> String
titleElection Election{..} =
Printf.printf "(questions=%i)×(choices=%i)==%i"
nQuests nChoices (nQuests * nChoices)
where
nQuests = List.length election_questions
nChoices = List.foldr max 0 $ List.length . question_choices <$> election_questions
benchEncryptBallot ::
forall crypto v c.
Reifies v Version =>
Reifies c crypto =>
JSON.ToJSON crypto =>
Group crypto =>
Key crypto =>
NFData crypto =>
NFData (FieldElement crypto c) =>
Multiplicative (FieldElement crypto c) =>
ToNatural (FieldElement crypto c) =>
JSON.ToJSON (FieldElement crypto c) =>
Proxy v -> Proxy c -> Int -> Int -> Benchmark
benchEncryptBallot (_v::Proxy v) (_c::Proxy c) nQuests nChoices =
let setupEnv = do
let elec :: Election crypto v c = makeElection nQuests nChoices
return elec in
env setupEnv $ \ ~(elec) ->
bench (titleElection elec) $
nf makeBallot elec
benchVerifyBallot ::
forall crypto v c.
Reifies v Version =>
Reifies c crypto =>
JSON.ToJSON crypto =>
Group crypto =>
Key crypto =>
NFData crypto =>
NFData (FieldElement crypto c) =>
Multiplicative (FieldElement crypto c) =>
ToNatural (FieldElement crypto c) =>
JSON.ToJSON (FieldElement crypto c) =>
Proxy v -> Proxy c -> Int -> Int -> Benchmark
benchVerifyBallot (_v::Proxy v) (_c::Proxy c) nQuests nChoices =
let setupEnv = do
let elec :: Election crypto v c = makeElection nQuests nChoices
let ballot = makeBallot elec
return (elec,ballot) in
env setupEnv $ \ ~(elec, ballot) ->
bench (titleElection elec) $
nf (verifyBallot elec) ballot
benchmarks :: [Benchmark]
benchmarks =
let inputs =
[ (nQ,nC)
| nQ <- [1,5,10,15,20,25]
, nC <- [5,7]
] in
[ bgroup "stableVersion" $ reify stableVersion $ \v ->
[ bgroup "weakFFC" $ reify weakFFC $ \c ->
[ bgroup "encryptBallot"
[ benchEncryptBallot v c nQuests nChoices
| (nQuests,nChoices) <- inputs
]
, bgroup "verifyBallot"
[ benchVerifyBallot v c nQuests nChoices
| (nQuests,nChoices) <- inputs
]
]
, bgroup "beleniosFFC" $ reify beleniosFFC $ \c ->
[ bgroup "encryptBallot"
[ benchEncryptBallot v c nQuests nChoices
| (nQuests,nChoices) <- inputs
]
, bgroup "verifyBallot"
[ benchVerifyBallot v c nQuests nChoices
| (nQuests,nChoices) <- inputs
]
]
]
]