]> Git — Sourcephile - majurity.git/blob - hjugement-protocol/tests/HUnit/Trustee/Indispensable.hs
protocol: polish tally
[majurity.git] / hjugement-protocol / tests / HUnit / Trustee / Indispensable.hs
1 {-# LANGUAGE AllowAmbiguousTypes #-}
2 {-# LANGUAGE DataKinds #-}
3 {-# LANGUAGE OverloadedStrings #-}
4 {-# LANGUAGE PatternSynonyms #-}
5 module HUnit.Trustee.Indispensable where
6
7 import Test.Tasty.HUnit
8 import qualified System.Random as Random
9 import qualified Text.Printf as Printf
10
11 import Voting.Protocol
12
13 import Utils
14
15 hunit :: TestTree
16 hunit = testGroup "Indispensable"
17 [ testGroup "verifyIndispensableTrusteePublicKey" $
18 [ testsVerifyIndispensableTrusteePublicKey @WeakParams
19 ]
20 , testGroup "verifyTally" $
21 [ testsVerifyTally @WeakParams
22 , testsVerifyTally @BeleniosParams
23 ]
24 ]
25
26 testsVerifyIndispensableTrusteePublicKey :: forall q. Params q => TestTree
27 testsVerifyIndispensableTrusteePublicKey =
28 testGroup (paramsName @q)
29 [ testVerifyIndispensableTrusteePublicKey @q 0 (Right ())
30 ]
31
32 testVerifyIndispensableTrusteePublicKey ::
33 forall q. Params q =>
34 Int -> Either ErrorTrusteePublicKey () -> TestTree
35 testVerifyIndispensableTrusteePublicKey seed exp =
36 let got =
37 runExcept $
38 (`evalStateT` Random.mkStdGen seed) $ do
39 trusteeSecKey :: SecretKey q <- randomSecretKey
40 trusteePubKey <- proveIndispensableTrusteePublicKey trusteeSecKey
41 lift $ verifyIndispensableTrusteePublicKey trusteePubKey
42 in
43 testCase (show (paramsName @q)) $
44 got @?= exp
45
46 testsVerifyTally :: forall q. Params q => TestTree
47 testsVerifyTally =
48 testGroup (paramsName @q)
49 [ testVerifyTally @q 0 1 1 1
50 , testVerifyTally @q 0 2 1 1
51 , testVerifyTally @q 0 1 2 1
52 , testVerifyTally @q 0 2 2 1
53 , testVerifyTally @q 0 5 10 5
54 ]
55
56 testVerifyTally ::
57 forall q. Params q =>
58 Int -> Natural -> Natural -> Natural -> TestTree
59 testVerifyTally seed nTrustees nQuests nChoices =
60 let clearTallyResult = dummyTallyResult nQuests nChoices in
61 let decryptedTallyResult :: Either ErrorTally [[Natural]] =
62 runExcept $
63 (`evalStateT` Random.mkStdGen seed) $ do
64 secKeyByTrustee :: [SecretKey q] <-
65 replicateM (fromIntegral nTrustees) $ randomSecretKey
66 trusteePubKeys <- forM secKeyByTrustee $ proveIndispensableTrusteePublicKey
67 let pubKeyByTrustee = trustee_PublicKey <$> trusteePubKeys
68 let elecPubKey = combineIndispensableTrusteePublicKeys trusteePubKeys
69 (encTally, countMax) <- encryptTallyResult elecPubKey clearTallyResult
70 decShareByTrustee <- forM secKeyByTrustee $ proveDecryptionShare encTally
71 lift $ verifyDecryptionShareByTrustee encTally pubKeyByTrustee decShareByTrustee
72 tally@Tally{..} <- lift $
73 proveTally (encTally, countMax) decShareByTrustee $
74 combineIndispensableDecryptionShares pubKeyByTrustee
75 lift $ verifyTally tally $
76 combineIndispensableDecryptionShares pubKeyByTrustee
77 return tally_countByChoiceByQuest
78 in
79 testCase (Printf.printf "nT=%i,nQ=%i,nC=%i (%i maxCount)"
80 nTrustees nQuests nChoices
81 (dummyTallyCount nQuests nChoices)) $
82 decryptedTallyResult @?= Right clearTallyResult
83
84 dummyTallyCount :: Natural -> Natural -> Natural
85 dummyTallyCount quest choice = quest * choice
86
87 dummyTallyResult :: Natural -> Natural -> [[Natural]]
88 dummyTallyResult nQuests nChoices =
89 [ [ dummyTallyCount q c | c <- [1..nChoices] ]
90 | q <- [1..nQuests]
91 ]
92
93 encryptTallyResult ::
94 Monad m => RandomGen r => SubGroup q =>
95 PublicKey q -> [[Natural]] -> StateT r m (EncryptedTally q, Natural)
96 encryptTallyResult pubKey countByChoiceByQuest =
97 (`runStateT` 0) $
98 forM countByChoiceByQuest $
99 mapM $ \count -> do
100 modify' $ max count
101 (_encNonce, enc) <- lift $ encrypt pubKey (fromNatural count)
102 return enc
103