{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE UndecidableInstances #-} -- for Reifies instances
module Voting.Protocol.Tally where

import Control.DeepSeq (NFData)
import Control.Monad (Monad(..), mapM, unless)
import Control.Monad.Trans.Except (Except, ExceptT, throwE)
import Data.Aeson (ToJSON(..), FromJSON(..), (.:), (.=))
import Data.Eq (Eq(..))
import Data.Function (($), (.))
import Data.Functor ((<$>))
import Data.Maybe (maybe)
import Data.Semigroup (Semigroup(..))
import Data.Reflection (Reifies(..))
import Data.Tuple (fst, snd)
import GHC.Generics (Generic)
import Numeric.Natural (Natural)
import System.Random (RandomGen)
import Text.Show (Show(..))
import qualified Data.Aeson as JSON
import qualified Data.Aeson.Types as JSON
import qualified Data.Aeson.Encoding as JSON
import qualified Control.Monad.Trans.State.Strict as S
import qualified Data.ByteString as BS
import qualified Data.List as List
import qualified Data.Map.Strict as Map

import Voting.Protocol.Utils
import Voting.Protocol.Arithmetic
import Voting.Protocol.Version
import Voting.Protocol.Cryptography
import Voting.Protocol.Credential
import Voting.Protocol.Election

-- * Type 'Tally'
data Tally crypto v c = Tally
 { Tally crypto v c -> Natural
tally_countMax :: !Natural
   -- ^ The maximal number of supportive 'Opinion's that a choice can get,
   -- which is here the same as the number of 'Ballot's.
   --
   -- Used in 'proveTally' to decrypt the actual
   -- count of votes obtained by a choice,
   -- by precomputing all powers of 'groupGen's up to it.
 , Tally crypto v c -> EncryptedTally crypto v c
tally_encByChoiceByQuest :: !(EncryptedTally crypto v c)
   -- ^ 'Encryption' by 'Question' by 'Ballot'.
 , Tally crypto v c -> [DecryptionShare crypto v c]
tally_decShareByTrustee :: ![DecryptionShare crypto v c]
   -- ^ 'DecryptionShare' by trustee.
 , Tally crypto v c -> [[Natural]]
tally_countByChoiceByQuest :: ![[Natural]]
   -- ^ The decrypted count of supportive 'Opinion's, by choice by 'Question'.
 } deriving ((forall x. Tally crypto v c -> Rep (Tally crypto v c) x)
-> (forall x. Rep (Tally crypto v c) x -> Tally crypto v c)
-> Generic (Tally crypto v c)
forall x. Rep (Tally crypto v c) x -> Tally crypto v c
forall x. Tally crypto v c -> Rep (Tally crypto v c) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall crypto v c x. Rep (Tally crypto v c) x -> Tally crypto v c
forall crypto v c x. Tally crypto v c -> Rep (Tally crypto v c) x
$cto :: forall crypto v c x. Rep (Tally crypto v c) x -> Tally crypto v c
$cfrom :: forall crypto v c x. Tally crypto v c -> Rep (Tally crypto v c) x
Generic)
deriving instance Eq (G crypto c) => Eq (Tally crypto v c)
deriving instance (Show (G crypto c), Show (G crypto c)) => Show (Tally crypto v c)
deriving instance NFData (G crypto c) => NFData (Tally crypto v c)
instance
 ( Reifies v Version
 , CryptoParams crypto c
 ) => ToJSON (Tally crypto v c) where
	toJSON :: Tally crypto v c -> Value
toJSON Tally{Natural
[[Natural]]
EncryptedTally crypto v c
[DecryptionShare crypto v c]
tally_countByChoiceByQuest :: [[Natural]]
tally_decShareByTrustee :: [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: EncryptedTally crypto v c
tally_countMax :: Natural
tally_countByChoiceByQuest :: forall crypto v c. Tally crypto v c -> [[Natural]]
tally_decShareByTrustee :: forall crypto v c. Tally crypto v c -> [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: forall crypto v c. Tally crypto v c -> EncryptedTally crypto v c
tally_countMax :: forall crypto v c. Tally crypto v c -> Natural
..} =
		[Pair] -> Value
JSON.object
		 [ Text
"num_tallied"         Text -> Natural -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Natural
tally_countMax
		 , Text
"encrypted_tally"     Text -> EncryptedTally crypto v c -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= EncryptedTally crypto v c
tally_encByChoiceByQuest
		 , Text
"partial_decryptions" Text -> [DecryptionShare crypto v c] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [DecryptionShare crypto v c]
tally_decShareByTrustee
		 , Text
"result"              Text -> [[Natural]] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [[Natural]]
tally_countByChoiceByQuest
		 ]
	toEncoding :: Tally crypto v c -> Encoding
toEncoding Tally{Natural
[[Natural]]
EncryptedTally crypto v c
[DecryptionShare crypto v c]
tally_countByChoiceByQuest :: [[Natural]]
tally_decShareByTrustee :: [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: EncryptedTally crypto v c
tally_countMax :: Natural
tally_countByChoiceByQuest :: forall crypto v c. Tally crypto v c -> [[Natural]]
tally_decShareByTrustee :: forall crypto v c. Tally crypto v c -> [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: forall crypto v c. Tally crypto v c -> EncryptedTally crypto v c
tally_countMax :: forall crypto v c. Tally crypto v c -> Natural
..} =
		Series -> Encoding
JSON.pairs
		 (  Text
"num_tallied"         Text -> Natural -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Natural
tally_countMax
		 Series -> Series -> Series
forall a. Semigroup a => a -> a -> a
<> Text
"encrypted_tally"     Text -> EncryptedTally crypto v c -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= EncryptedTally crypto v c
tally_encByChoiceByQuest
		 Series -> Series -> Series
forall a. Semigroup a => a -> a -> a
<> Text
"partial_decryptions" Text -> [DecryptionShare crypto v c] -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [DecryptionShare crypto v c]
tally_decShareByTrustee
		 Series -> Series -> Series
forall a. Semigroup a => a -> a -> a
<> Text
"result"              Text -> [[Natural]] -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= [[Natural]]
tally_countByChoiceByQuest
		 )
instance
 ( Reifies v Version
 , CryptoParams crypto c
 ) => FromJSON (Tally crypto v c) where
	parseJSON :: Value -> Parser (Tally crypto v c)
parseJSON = String
-> (Object -> Parser (Tally crypto v c))
-> Value
-> Parser (Tally crypto v c)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
JSON.withObject String
"Tally" ((Object -> Parser (Tally crypto v c))
 -> Value -> Parser (Tally crypto v c))
-> (Object -> Parser (Tally crypto v c))
-> Value
-> Parser (Tally crypto v c)
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
		Natural
tally_countMax             <- Object
o Object -> Text -> Parser Natural
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"num_tallied"
		EncryptedTally crypto v c
tally_encByChoiceByQuest   <- Object
o Object -> Text -> Parser (EncryptedTally crypto v c)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"encrypted_tally"
		[DecryptionShare crypto v c]
tally_decShareByTrustee    <- Object
o Object -> Text -> Parser [DecryptionShare crypto v c]
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"partial_decryptions"
		[[Natural]]
tally_countByChoiceByQuest <- Object
o Object -> Text -> Parser [[Natural]]
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"result"
		Tally crypto v c -> Parser (Tally crypto v c)
forall (m :: * -> *) a. Monad m => a -> m a
return Tally :: forall crypto v c.
Natural
-> EncryptedTally crypto v c
-> [DecryptionShare crypto v c]
-> [[Natural]]
-> Tally crypto v c
Tally{Natural
[[Natural]]
EncryptedTally crypto v c
[DecryptionShare crypto v c]
tally_countByChoiceByQuest :: [[Natural]]
tally_decShareByTrustee :: [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: EncryptedTally crypto v c
tally_countMax :: Natural
tally_countByChoiceByQuest :: [[Natural]]
tally_decShareByTrustee :: [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: EncryptedTally crypto v c
tally_countMax :: Natural
..}

-- ** Type 'EncryptedTally'
-- | 'Encryption' by choice by 'Question'.
type EncryptedTally crypto v c = [[Encryption crypto v c]]

-- | @('encryptedTally' ballots)@
-- returns the sum of the 'Encryption's of the given @ballots@,
-- along with the number of 'Ballot's.
encryptedTally ::
 CryptoParams crypto c =>
 [Ballot crypto v c] -> (EncryptedTally crypto v c, Natural)
encryptedTally :: [Ballot crypto v c] -> (EncryptedTally crypto v c, Natural)
encryptedTally = (Ballot crypto v c
 -> (EncryptedTally crypto v c, Natural)
 -> (EncryptedTally crypto v c, Natural))
-> (EncryptedTally crypto v c, Natural)
-> [Ballot crypto v c]
-> (EncryptedTally crypto v c, Natural)
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr Ballot crypto v c
-> (EncryptedTally crypto v c, Natural)
-> (EncryptedTally crypto v c, Natural)
forall crypto c v.
CryptoParams crypto c =>
Ballot crypto v c
-> (EncryptedTally crypto v c, Natural)
-> (EncryptedTally crypto v c, Natural)
insertEncryptedTally (EncryptedTally crypto v c, Natural)
forall crypto c v.
CryptoParams crypto c =>
(EncryptedTally crypto v c, Natural)
emptyEncryptedTally

-- | The initial 'EncryptedTally' which tallies no 'Ballot'.
emptyEncryptedTally ::
 CryptoParams crypto c =>
 (EncryptedTally crypto v c, Natural)
emptyEncryptedTally :: (EncryptedTally crypto v c, Natural)
emptyEncryptedTally = ([Encryption crypto v c] -> EncryptedTally crypto v c
forall a. a -> [a]
List.repeat (Encryption crypto v c -> [Encryption crypto v c]
forall a. a -> [a]
List.repeat Encryption crypto v c
forall a. Additive a => a
zero), Natural
0)

-- | @('insertEncryptedTally' ballot encTally)@
-- returns the 'EncryptedTally' adding the votes of the given @(ballot)@
-- to those of the given @(encTally)@.
insertEncryptedTally ::
 CryptoParams crypto c =>
 Ballot crypto v c ->
 (EncryptedTally crypto v c, Natural) ->
 (EncryptedTally crypto v c, Natural)
insertEncryptedTally :: Ballot crypto v c
-> (EncryptedTally crypto v c, Natural)
-> (EncryptedTally crypto v c, Natural)
insertEncryptedTally Ballot{[Answer crypto v c]
Maybe (Signature crypto v c)
Base64SHA256
UUID
ballot_election_hash :: forall crypto v c. Ballot crypto v c -> Base64SHA256
ballot_election_uuid :: forall crypto v c. Ballot crypto v c -> UUID
ballot_signature :: forall crypto v c.
Ballot crypto v c -> Maybe (Signature crypto v c)
ballot_answers :: forall crypto v c. Ballot crypto v c -> [Answer crypto v c]
ballot_election_hash :: Base64SHA256
ballot_election_uuid :: UUID
ballot_signature :: Maybe (Signature crypto v c)
ballot_answers :: [Answer crypto v c]
..} (EncryptedTally crypto v c
encTally, Natural
numBallots) =
	( (Answer crypto v c
 -> [Encryption crypto v c] -> [Encryption crypto v c])
-> [Answer crypto v c]
-> EncryptedTally crypto v c
-> EncryptedTally crypto v c
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
List.zipWith
		 (\Answer{[(Encryption crypto v c, DisjProof crypto v c)]
DisjProof crypto v c
answer_sumProof :: forall crypto v c. Answer crypto v c -> DisjProof crypto v c
answer_opinions :: forall crypto v c.
Answer crypto v c
-> [(Encryption crypto v c, DisjProof crypto v c)]
answer_sumProof :: DisjProof crypto v c
answer_opinions :: [(Encryption crypto v c, DisjProof crypto v c)]
..} -> (Encryption crypto v c
 -> Encryption crypto v c -> Encryption crypto v c)
-> [Encryption crypto v c]
-> [Encryption crypto v c]
-> [Encryption crypto v c]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
List.zipWith Encryption crypto v c
-> Encryption crypto v c -> Encryption crypto v c
forall a. Additive a => a -> a -> a
(+) ((Encryption crypto v c, DisjProof crypto v c)
-> Encryption crypto v c
forall a b. (a, b) -> a
fst ((Encryption crypto v c, DisjProof crypto v c)
 -> Encryption crypto v c)
-> [(Encryption crypto v c, DisjProof crypto v c)]
-> [Encryption crypto v c]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Encryption crypto v c, DisjProof crypto v c)]
answer_opinions))
		 [Answer crypto v c]
ballot_answers
		 EncryptedTally crypto v c
encTally
	, Natural
numBallotsNatural -> Natural -> Natural
forall a. Additive a => a -> a -> a
+Natural
1
	)

-- ** Type 'DecryptionShareCombinator'
type DecryptionShareCombinator crypto v c =
 EncryptedTally crypto v c ->
 [DecryptionShare crypto v c] ->
 Except ErrorTally [[DecryptionFactor crypto c]]

proveTally ::
 CryptoParams crypto c =>
 (EncryptedTally crypto v c, Natural) -> [DecryptionShare crypto v c] ->
 DecryptionShareCombinator crypto v c -> Except ErrorTally (Tally crypto v c)
proveTally :: (EncryptedTally crypto v c, Natural)
-> [DecryptionShare crypto v c]
-> DecryptionShareCombinator crypto v c
-> Except ErrorTally (Tally crypto v c)
proveTally
 (EncryptedTally crypto v c
tally_encByChoiceByQuest, Natural
tally_countMax)
 [DecryptionShare crypto v c]
tally_decShareByTrustee
 DecryptionShareCombinator crypto v c
decShareCombinator = do
	[[DecryptionFactor crypto c]]
decFactorByChoiceByQuest <-
		DecryptionShareCombinator crypto v c
decShareCombinator
		 EncryptedTally crypto v c
tally_encByChoiceByQuest
		 [DecryptionShare crypto v c]
tally_decShareByTrustee
	[[DecryptionFactor crypto c]]
dec <- ExceptT ErrorTally Identity ()
-> ([Encryption crypto v c]
    -> [DecryptionFactor crypto c]
    -> ExceptT ErrorTally Identity [DecryptionFactor crypto c])
-> EncryptedTally crypto v c
-> [[DecryptionFactor crypto c]]
-> ExceptT ErrorTally Identity [[DecryptionFactor crypto c]]
forall (f :: * -> *) a b c.
Applicative f =>
f () -> (a -> b -> f c) -> [a] -> [b] -> f [c]
isoZipWithM (ErrorTally -> ExceptT ErrorTally Identity ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfQuestions)
	 (ExceptT ErrorTally Identity [DecryptionFactor crypto c]
-> ([DecryptionFactor crypto c]
    -> ExceptT ErrorTally Identity [DecryptionFactor crypto c])
-> Maybe [DecryptionFactor crypto c]
-> ExceptT ErrorTally Identity [DecryptionFactor crypto c]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ErrorTally
-> ExceptT ErrorTally Identity [DecryptionFactor crypto c]
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfChoices) [DecryptionFactor crypto c]
-> ExceptT ErrorTally Identity [DecryptionFactor crypto c]
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe [DecryptionFactor crypto c]
 -> ExceptT ErrorTally Identity [DecryptionFactor crypto c])
-> ([Encryption crypto v c]
    -> [DecryptionFactor crypto c]
    -> Maybe [DecryptionFactor crypto c])
-> [Encryption crypto v c]
-> [DecryptionFactor crypto c]
-> ExceptT ErrorTally Identity [DecryptionFactor crypto c]
forall c d a b. (c -> d) -> (a -> b -> c) -> a -> b -> d
`o2`
		(Encryption crypto v c
 -> DecryptionFactor crypto c -> DecryptionFactor crypto c)
-> [Encryption crypto v c]
-> [DecryptionFactor crypto c]
-> Maybe [DecryptionFactor crypto c]
forall a b c. (a -> b -> c) -> [a] -> [b] -> Maybe [c]
isoZipWith (\Encryption{DecryptionFactor crypto c
encryption_vault :: forall crypto k (v :: k) c. Encryption crypto v c -> G crypto c
encryption_nonce :: forall crypto k (v :: k) c. Encryption crypto v c -> G crypto c
encryption_vault :: DecryptionFactor crypto c
encryption_nonce :: DecryptionFactor crypto c
..} DecryptionFactor crypto c
decFactor -> DecryptionFactor crypto c
encryption_vault DecryptionFactor crypto c
-> DecryptionFactor crypto c -> DecryptionFactor crypto c
forall a. EuclideanRing a => a -> a -> a
/ DecryptionFactor crypto c
decFactor))
	 EncryptedTally crypto v c
tally_encByChoiceByQuest
	 [[DecryptionFactor crypto c]]
decFactorByChoiceByQuest
	let logMap :: Map (DecryptionFactor crypto c) Natural
logMap = [(DecryptionFactor crypto c, Natural)]
-> Map (DecryptionFactor crypto c) Natural
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(DecryptionFactor crypto c, Natural)]
 -> Map (DecryptionFactor crypto c) Natural)
-> [(DecryptionFactor crypto c, Natural)]
-> Map (DecryptionFactor crypto c) Natural
forall a b. (a -> b) -> a -> b
$ [DecryptionFactor crypto c]
-> [Natural] -> [(DecryptionFactor crypto c, Natural)]
forall a b. [a] -> [b] -> [(a, b)]
List.zip [DecryptionFactor crypto c]
forall crypto c. CryptoParams crypto c => [G crypto c]
groupGenPowers [Natural
0..Natural
tally_countMax]
	let log :: DecryptionFactor crypto c -> ExceptT ErrorTally Identity Natural
log DecryptionFactor crypto c
x =
		ExceptT ErrorTally Identity Natural
-> (Natural -> ExceptT ErrorTally Identity Natural)
-> Maybe Natural
-> ExceptT ErrorTally Identity Natural
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ErrorTally -> ExceptT ErrorTally Identity Natural
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_CannotDecryptCount) Natural -> ExceptT ErrorTally Identity Natural
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Natural -> ExceptT ErrorTally Identity Natural)
-> Maybe Natural -> ExceptT ErrorTally Identity Natural
forall a b. (a -> b) -> a -> b
$
		DecryptionFactor crypto c
-> Map (DecryptionFactor crypto c) Natural -> Maybe Natural
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup DecryptionFactor crypto c
x Map (DecryptionFactor crypto c) Natural
logMap
	[[Natural]]
tally_countByChoiceByQuest <- (DecryptionFactor crypto c -> ExceptT ErrorTally Identity Natural
log (DecryptionFactor crypto c -> ExceptT ErrorTally Identity Natural)
-> [DecryptionFactor crypto c]
-> ExceptT ErrorTally Identity [Natural]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
`mapM`)([DecryptionFactor crypto c]
 -> ExceptT ErrorTally Identity [Natural])
-> [[DecryptionFactor crypto c]]
-> ExceptT ErrorTally Identity [[Natural]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
`mapM`[[DecryptionFactor crypto c]]
dec
	Tally crypto v c -> Except ErrorTally (Tally crypto v c)
forall (m :: * -> *) a. Monad m => a -> m a
return Tally :: forall crypto v c.
Natural
-> EncryptedTally crypto v c
-> [DecryptionShare crypto v c]
-> [[Natural]]
-> Tally crypto v c
Tally{Natural
[[Natural]]
EncryptedTally crypto v c
[DecryptionShare crypto v c]
tally_countByChoiceByQuest :: [[Natural]]
tally_decShareByTrustee :: [DecryptionShare crypto v c]
tally_countMax :: Natural
tally_encByChoiceByQuest :: EncryptedTally crypto v c
tally_countByChoiceByQuest :: [[Natural]]
tally_decShareByTrustee :: [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: EncryptedTally crypto v c
tally_countMax :: Natural
..}

verifyTally ::
 CryptoParams crypto c =>
 Tally crypto v c ->
 DecryptionShareCombinator crypto v c ->
 Except ErrorTally ()
verifyTally :: Tally crypto v c
-> DecryptionShareCombinator crypto v c
-> ExceptT ErrorTally Identity ()
verifyTally Tally{Natural
[[Natural]]
EncryptedTally crypto v c
[DecryptionShare crypto v c]
tally_countByChoiceByQuest :: [[Natural]]
tally_decShareByTrustee :: [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: EncryptedTally crypto v c
tally_countMax :: Natural
tally_countByChoiceByQuest :: forall crypto v c. Tally crypto v c -> [[Natural]]
tally_decShareByTrustee :: forall crypto v c. Tally crypto v c -> [DecryptionShare crypto v c]
tally_encByChoiceByQuest :: forall crypto v c. Tally crypto v c -> EncryptedTally crypto v c
tally_countMax :: forall crypto v c. Tally crypto v c -> Natural
..} DecryptionShareCombinator crypto v c
decShareCombinator = do
	[[DecryptionFactor crypto c]]
decFactorByChoiceByQuest <- DecryptionShareCombinator crypto v c
decShareCombinator EncryptedTally crypto v c
tally_encByChoiceByQuest [DecryptionShare crypto v c]
tally_decShareByTrustee
	ExceptT ErrorTally Identity ()
-> ([Encryption crypto v c]
    -> [DecryptionFactor crypto c]
    -> [Natural]
    -> ExceptT ErrorTally Identity ())
-> EncryptedTally crypto v c
-> [[DecryptionFactor crypto c]]
-> [[Natural]]
-> ExceptT ErrorTally Identity ()
forall (f :: * -> *) a b c d.
Applicative f =>
f () -> (a -> b -> c -> f d) -> [a] -> [b] -> [c] -> f ()
isoZipWith3M_ (ErrorTally -> ExceptT ErrorTally Identity ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfQuestions)
	 (ExceptT ErrorTally Identity ()
-> (Encryption crypto v c
    -> DecryptionFactor crypto c
    -> Natural
    -> ExceptT ErrorTally Identity ())
-> [Encryption crypto v c]
-> [DecryptionFactor crypto c]
-> [Natural]
-> ExceptT ErrorTally Identity ()
forall (f :: * -> *) a b c d.
Applicative f =>
f () -> (a -> b -> c -> f d) -> [a] -> [b] -> [c] -> f ()
isoZipWith3M_ (ErrorTally -> ExceptT ErrorTally Identity ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfChoices)
		 (\Encryption{DecryptionFactor crypto c
encryption_vault :: DecryptionFactor crypto c
encryption_nonce :: DecryptionFactor crypto c
encryption_vault :: forall crypto k (v :: k) c. Encryption crypto v c -> G crypto c
encryption_nonce :: forall crypto k (v :: k) c. Encryption crypto v c -> G crypto c
..} DecryptionFactor crypto c
decFactor Natural
count -> do
			let groupGenPowCount :: DecryptionFactor crypto c
groupGenPowCount = DecryptionFactor crypto c
encryption_vault DecryptionFactor crypto c
-> DecryptionFactor crypto c -> DecryptionFactor crypto c
forall a. EuclideanRing a => a -> a -> a
/ DecryptionFactor crypto c
decFactor
			Bool
-> ExceptT ErrorTally Identity () -> ExceptT ErrorTally Identity ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (DecryptionFactor crypto c
groupGenPowCount DecryptionFactor crypto c -> DecryptionFactor crypto c -> Bool
forall a. Eq a => a -> a -> Bool
== DecryptionFactor crypto c
forall crypto c. CryptoParams crypto c => G crypto c
groupGen DecryptionFactor crypto c
-> E crypto c -> DecryptionFactor crypto c
forall crypto c.
(Reifies c crypto, Semiring (G crypto c)) =>
G crypto c -> E crypto c -> G crypto c
^ Natural -> E crypto c
forall a. FromNatural a => Natural -> a
fromNatural Natural
count) (ExceptT ErrorTally Identity () -> ExceptT ErrorTally Identity ())
-> ExceptT ErrorTally Identity () -> ExceptT ErrorTally Identity ()
forall a b. (a -> b) -> a -> b
$
				ErrorTally -> ExceptT ErrorTally Identity ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_WrongProof))
	 EncryptedTally crypto v c
tally_encByChoiceByQuest
	 [[DecryptionFactor crypto c]]
decFactorByChoiceByQuest
	 [[Natural]]
tally_countByChoiceByQuest

-- ** Type 'DecryptionShare'
-- | A decryption share is a 'DecryptionFactor' and a decryption 'Proof', by choice by 'Question'.
-- Computed by a trustee in 'proveDecryptionShare'.
newtype DecryptionShare crypto v c = DecryptionShare
 { DecryptionShare crypto v c
-> [[(DecryptionFactor crypto c, Proof crypto v c)]]
unDecryptionShare :: [[(DecryptionFactor crypto c, Proof crypto v c)]] }
 deriving ((forall x.
 DecryptionShare crypto v c -> Rep (DecryptionShare crypto v c) x)
-> (forall x.
    Rep (DecryptionShare crypto v c) x -> DecryptionShare crypto v c)
-> Generic (DecryptionShare crypto v c)
forall x.
Rep (DecryptionShare crypto v c) x -> DecryptionShare crypto v c
forall x.
DecryptionShare crypto v c -> Rep (DecryptionShare crypto v c) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall crypto v c x.
Rep (DecryptionShare crypto v c) x -> DecryptionShare crypto v c
forall crypto v c x.
DecryptionShare crypto v c -> Rep (DecryptionShare crypto v c) x
$cto :: forall crypto v c x.
Rep (DecryptionShare crypto v c) x -> DecryptionShare crypto v c
$cfrom :: forall crypto v c x.
DecryptionShare crypto v c -> Rep (DecryptionShare crypto v c) x
Generic)
deriving instance Eq (G crypto c) => Eq (DecryptionShare crypto v c)
deriving instance Show (G crypto c) => Show (DecryptionShare crypto v c)
deriving newtype instance NFData (G crypto c) => NFData (DecryptionShare crypto v c)
instance
 ( Reifies v Version
 , ToJSON (G crypto c)
 ) => ToJSON (DecryptionShare crypto v c) where
	toJSON :: DecryptionShare crypto v c -> Value
toJSON (DecryptionShare [[(G crypto c, Proof crypto v c)]]
decByChoiceByQuest) =
		[Pair] -> Value
JSON.object
		 [ Text
"decryption_factors" Text -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=
			[[Value]] -> Value
forall a. ToJSON a => [a] -> Value
toJSONList (((G crypto c -> Value
forall a. ToJSON a => a -> Value
toJSON (G crypto c -> Value)
-> ((G crypto c, Proof crypto v c) -> G crypto c)
-> (G crypto c, Proof crypto v c)
-> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (G crypto c, Proof crypto v c) -> G crypto c
forall a b. (a, b) -> a
fst) ((G crypto c, Proof crypto v c) -> Value)
-> [(G crypto c, Proof crypto v c)] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) ([(G crypto c, Proof crypto v c)] -> [Value])
-> [[(G crypto c, Proof crypto v c)]] -> [[Value]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [[(G crypto c, Proof crypto v c)]]
decByChoiceByQuest)
		 , Text
"decryption_proofs" Text -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.=
			[[Value]] -> Value
forall a. ToJSON a => [a] -> Value
toJSONList (((Proof crypto v c -> Value
forall a. ToJSON a => a -> Value
toJSON (Proof crypto v c -> Value)
-> ((G crypto c, Proof crypto v c) -> Proof crypto v c)
-> (G crypto c, Proof crypto v c)
-> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (G crypto c, Proof crypto v c) -> Proof crypto v c
forall a b. (a, b) -> b
snd) ((G crypto c, Proof crypto v c) -> Value)
-> [(G crypto c, Proof crypto v c)] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) ([(G crypto c, Proof crypto v c)] -> [Value])
-> [[(G crypto c, Proof crypto v c)]] -> [[Value]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [[(G crypto c, Proof crypto v c)]]
decByChoiceByQuest)
		 ]
	toEncoding :: DecryptionShare crypto v c -> Encoding
toEncoding (DecryptionShare [[(G crypto c, Proof crypto v c)]]
decByChoiceByQuest) =
		Series -> Encoding
JSON.pairs (Series -> Encoding) -> Series -> Encoding
forall a b. (a -> b) -> a -> b
$
			Text -> Encoding -> Series
JSON.pair Text
"decryption_factors"
			 (([(G crypto c, Proof crypto v c)] -> Encoding)
-> [[(G crypto c, Proof crypto v c)]] -> Encoding
forall a. (a -> Encoding) -> [a] -> Encoding
JSON.list (((G crypto c, Proof crypto v c) -> Encoding)
-> [(G crypto c, Proof crypto v c)] -> Encoding
forall a. (a -> Encoding) -> [a] -> Encoding
JSON.list (G crypto c -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding (G crypto c -> Encoding)
-> ((G crypto c, Proof crypto v c) -> G crypto c)
-> (G crypto c, Proof crypto v c)
-> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (G crypto c, Proof crypto v c) -> G crypto c
forall a b. (a, b) -> a
fst)) [[(G crypto c, Proof crypto v c)]]
decByChoiceByQuest) Series -> Series -> Series
forall a. Semigroup a => a -> a -> a
<>
			Text -> Encoding -> Series
JSON.pair Text
"decryption_proofs"
			 (([(G crypto c, Proof crypto v c)] -> Encoding)
-> [[(G crypto c, Proof crypto v c)]] -> Encoding
forall a. (a -> Encoding) -> [a] -> Encoding
JSON.list (((G crypto c, Proof crypto v c) -> Encoding)
-> [(G crypto c, Proof crypto v c)] -> Encoding
forall a. (a -> Encoding) -> [a] -> Encoding
JSON.list (Proof crypto v c -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding (Proof crypto v c -> Encoding)
-> ((G crypto c, Proof crypto v c) -> Proof crypto v c)
-> (G crypto c, Proof crypto v c)
-> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (G crypto c, Proof crypto v c) -> Proof crypto v c
forall a b. (a, b) -> b
snd)) [[(G crypto c, Proof crypto v c)]]
decByChoiceByQuest)
instance
 ( Reifies v Version
 , CryptoParams crypto c
 ) => FromJSON (DecryptionShare crypto v c) where
	parseJSON :: Value -> Parser (DecryptionShare crypto v c)
parseJSON = String
-> (Object -> Parser (DecryptionShare crypto v c))
-> Value
-> Parser (DecryptionShare crypto v c)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
JSON.withObject String
"DecryptionShare" ((Object -> Parser (DecryptionShare crypto v c))
 -> Value -> Parser (DecryptionShare crypto v c))
-> (Object -> Parser (DecryptionShare crypto v c))
-> Value
-> Parser (DecryptionShare crypto v c)
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
		[[DecryptionFactor crypto c]]
decFactors <- Object
o Object -> Text -> Parser [[DecryptionFactor crypto c]]
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"decryption_factors"
		[[Proof crypto v c]]
decProofs  <- Object
o Object -> Text -> Parser [[Proof crypto v c]]
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"decryption_proofs"
		let err :: String -> Parser ()
err String
msg = String -> Value -> Parser ()
forall a. String -> Value -> Parser a
JSON.typeMismatch (String
"DecryptionShare: "String -> ShowS
forall a. Semigroup a => a -> a -> a
<>String
msg) (Object -> Value
JSON.Object Object
o)
		[[(DecryptionFactor crypto c, Proof crypto v c)]]
-> DecryptionShare crypto v c
forall crypto v c.
[[(DecryptionFactor crypto c, Proof crypto v c)]]
-> DecryptionShare crypto v c
DecryptionShare
		 ([[(DecryptionFactor crypto c, Proof crypto v c)]]
 -> DecryptionShare crypto v c)
-> Parser [[(DecryptionFactor crypto c, Proof crypto v c)]]
-> Parser (DecryptionShare crypto v c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ()
-> ([DecryptionFactor crypto c]
    -> [Proof crypto v c]
    -> Parser [(DecryptionFactor crypto c, Proof crypto v c)])
-> [[DecryptionFactor crypto c]]
-> [[Proof crypto v c]]
-> Parser [[(DecryptionFactor crypto c, Proof crypto v c)]]
forall (f :: * -> *) a b c.
Applicative f =>
f () -> (a -> b -> f c) -> [a] -> [b] -> f [c]
isoZipWithM (String -> Parser ()
err String
"inconsistent number of questions")
			 (Parser ()
-> (DecryptionFactor crypto c
    -> Proof crypto v c
    -> Parser (DecryptionFactor crypto c, Proof crypto v c))
-> [DecryptionFactor crypto c]
-> [Proof crypto v c]
-> Parser [(DecryptionFactor crypto c, Proof crypto v c)]
forall (f :: * -> *) a b c.
Applicative f =>
f () -> (a -> b -> f c) -> [a] -> [b] -> f [c]
isoZipWithM (String -> Parser ()
err String
"inconsistent number of choices")
				 (\DecryptionFactor crypto c
a Proof crypto v c
b -> (DecryptionFactor crypto c, Proof crypto v c)
-> Parser (DecryptionFactor crypto c, Proof crypto v c)
forall (m :: * -> *) a. Monad m => a -> m a
return (DecryptionFactor crypto c
a, Proof crypto v c
b)))
		 [[DecryptionFactor crypto c]]
decFactors [[Proof crypto v c]]
decProofs

-- *** Type 'DecryptionFactor'
-- | @'encryption_nonce' '^'trusteeSecKey@
type DecryptionFactor = G

-- @('proveDecryptionShare' encByChoiceByQuest trusteeSecKey)@
proveDecryptionShare ::
 Reifies v Version =>
 CryptoParams crypto c =>
 Key crypto =>
 Monad m => RandomGen r =>
 EncryptedTally crypto v c -> SecretKey crypto c -> S.StateT r m (DecryptionShare crypto v c)
proveDecryptionShare :: EncryptedTally crypto v c
-> SecretKey crypto c -> StateT r m (DecryptionShare crypto v c)
proveDecryptionShare EncryptedTally crypto v c
encByChoiceByQuest SecretKey crypto c
trusteeSecKey =
	([[(DecryptionFactor crypto c, Proof crypto v c)]]
-> DecryptionShare crypto v c
forall crypto v c.
[[(DecryptionFactor crypto c, Proof crypto v c)]]
-> DecryptionShare crypto v c
DecryptionShare ([[(DecryptionFactor crypto c, Proof crypto v c)]]
 -> DecryptionShare crypto v c)
-> StateT r m [[(DecryptionFactor crypto c, Proof crypto v c)]]
-> StateT r m (DecryptionShare crypto v c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (StateT r m [[(DecryptionFactor crypto c, Proof crypto v c)]]
 -> StateT r m (DecryptionShare crypto v c))
-> StateT r m [[(DecryptionFactor crypto c, Proof crypto v c)]]
-> StateT r m (DecryptionShare crypto v c)
forall a b. (a -> b) -> a -> b
$
	(SecretKey crypto c
-> Encryption crypto v c
-> StateT r m (DecryptionFactor crypto c, Proof crypto v c)
forall v crypto c (m :: * -> *) r.
(Reifies v Version, CryptoParams crypto c, Key crypto, Monad m,
 RandomGen r) =>
SecretKey crypto c
-> Encryption crypto v c
-> StateT r m (DecryptionFactor crypto c, Proof crypto v c)
proveDecryptionFactor SecretKey crypto c
trusteeSecKey (Encryption crypto v c
 -> StateT r m (DecryptionFactor crypto c, Proof crypto v c))
-> [Encryption crypto v c]
-> StateT r m [(DecryptionFactor crypto c, Proof crypto v c)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
`mapM`) ([Encryption crypto v c]
 -> StateT r m [(DecryptionFactor crypto c, Proof crypto v c)])
-> EncryptedTally crypto v c
-> StateT r m [[(DecryptionFactor crypto c, Proof crypto v c)]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
`mapM` EncryptedTally crypto v c
encByChoiceByQuest

proveDecryptionFactor ::
 Reifies v Version => 
 CryptoParams crypto c =>
 Key crypto =>
 Monad m => RandomGen r =>
 SecretKey crypto c -> Encryption crypto v c -> S.StateT r m (DecryptionFactor crypto c, Proof crypto v c)
proveDecryptionFactor :: SecretKey crypto c
-> Encryption crypto v c
-> StateT r m (DecryptionFactor crypto c, Proof crypto v c)
proveDecryptionFactor SecretKey crypto c
trusteeSecKey Encryption{DecryptionFactor crypto c
encryption_vault :: DecryptionFactor crypto c
encryption_nonce :: DecryptionFactor crypto c
encryption_vault :: forall crypto k (v :: k) c. Encryption crypto v c -> G crypto c
encryption_nonce :: forall crypto k (v :: k) c. Encryption crypto v c -> G crypto c
..} = do
	Proof crypto v c
proof <- SecretKey crypto c
-> [DecryptionFactor crypto c]
-> Oracle [] crypto c
-> StateT r m (Proof crypto v c)
forall k crypto (v :: k) c (list :: * -> *) (m :: * -> *) r.
(Reifies v Version, CryptoParams crypto c, Monad m, RandomGen r,
 Functor list) =>
E crypto c
-> list (G crypto c)
-> Oracle list crypto c
-> StateT r m (Proof crypto v c)
prove SecretKey crypto c
trusteeSecKey [DecryptionFactor crypto c
forall crypto c. CryptoParams crypto c => G crypto c
groupGen, DecryptionFactor crypto c
encryption_nonce] (ByteString -> Oracle [] crypto c
forall crypto c.
CryptoParams crypto c =>
ByteString -> [G crypto c] -> E crypto c
hash ByteString
zkp)
	(DecryptionFactor crypto c, Proof crypto v c)
-> StateT r m (DecryptionFactor crypto c, Proof crypto v c)
forall (m :: * -> *) a. Monad m => a -> m a
return (DecryptionFactor crypto c
encryption_nonceDecryptionFactor crypto c
-> SecretKey crypto c -> DecryptionFactor crypto c
forall crypto c.
(Reifies c crypto, Semiring (G crypto c)) =>
G crypto c -> E crypto c -> G crypto c
^SecretKey crypto c
trusteeSecKey, Proof crypto v c
proof)
	where zkp :: ByteString
zkp = DecryptionFactor crypto c -> ByteString
forall crypto c.
CryptoParams crypto c =>
PublicKey crypto c -> ByteString
decryptionShareStatement (SecretKey crypto c -> DecryptionFactor crypto c
forall crypto c.
(Key crypto, Reifies c crypto) =>
SecretKey crypto c -> PublicKey crypto c
publicKey SecretKey crypto c
trusteeSecKey)

decryptionShareStatement :: CryptoParams crypto c => PublicKey crypto c -> BS.ByteString
decryptionShareStatement :: PublicKey crypto c -> ByteString
decryptionShareStatement PublicKey crypto c
pubKey =
	ByteString
"decrypt|"ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<>PublicKey crypto c -> ByteString
forall n. ToNatural n => n -> ByteString
bytesNat PublicKey crypto c
pubKeyByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<>ByteString
"|"

-- *** Type 'ErrorTally'
data ErrorTally
 =   ErrorTally_NumberOfQuestions
     -- ^ The number of 'Question's is not the one expected.
 |   ErrorTally_NumberOfChoices
     -- ^ The number of choices is not the one expected.
 |   ErrorTally_NumberOfTrustees
     -- ^ The number of trustees is not the one expected.
 |   ErrorTally_WrongProof
     -- ^ The 'Proof' of a 'DecryptionFactor' is wrong.
 |   ErrorTally_CannotDecryptCount
     -- ^ Raised by 'proveTally' when the discrete logarithm of @'groupGen' '^'count@
     -- cannot be computed, likely because 'tally_countMax' is wrong,
     -- or because the 'EncryptedTally' or 'DecryptionShare's have not been verified.
 deriving (ErrorTally -> ErrorTally -> Bool
(ErrorTally -> ErrorTally -> Bool)
-> (ErrorTally -> ErrorTally -> Bool) -> Eq ErrorTally
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ErrorTally -> ErrorTally -> Bool
$c/= :: ErrorTally -> ErrorTally -> Bool
== :: ErrorTally -> ErrorTally -> Bool
$c== :: ErrorTally -> ErrorTally -> Bool
Eq,Int -> ErrorTally -> ShowS
[ErrorTally] -> ShowS
ErrorTally -> String
(Int -> ErrorTally -> ShowS)
-> (ErrorTally -> String)
-> ([ErrorTally] -> ShowS)
-> Show ErrorTally
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ErrorTally] -> ShowS
$cshowList :: [ErrorTally] -> ShowS
show :: ErrorTally -> String
$cshow :: ErrorTally -> String
showsPrec :: Int -> ErrorTally -> ShowS
$cshowsPrec :: Int -> ErrorTally -> ShowS
Show,(forall x. ErrorTally -> Rep ErrorTally x)
-> (forall x. Rep ErrorTally x -> ErrorTally) -> Generic ErrorTally
forall x. Rep ErrorTally x -> ErrorTally
forall x. ErrorTally -> Rep ErrorTally x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ErrorTally x -> ErrorTally
$cfrom :: forall x. ErrorTally -> Rep ErrorTally x
Generic,ErrorTally -> ()
(ErrorTally -> ()) -> NFData ErrorTally
forall a. (a -> ()) -> NFData a
rnf :: ErrorTally -> ()
$crnf :: ErrorTally -> ()
NFData)

-- | @('verifyDecryptionShare' encTally trusteePubKey trusteeDecShare)@
-- checks that 'trusteeDecShare'
-- (supposedly submitted by a trustee whose 'PublicKey' is 'trusteePubKey')
-- is valid with respect to the 'EncryptedTally' 'encTally'.
verifyDecryptionShare ::
 Reifies v Version =>
 CryptoParams crypto c =>
 Monad m =>
 EncryptedTally crypto v c -> PublicKey crypto c -> DecryptionShare crypto v c ->
 ExceptT ErrorTally m ()
verifyDecryptionShare :: EncryptedTally crypto v c
-> PublicKey crypto c
-> DecryptionShare crypto v c
-> ExceptT ErrorTally m ()
verifyDecryptionShare EncryptedTally crypto v c
encByChoiceByQuest PublicKey crypto c
trusteePubKey (DecryptionShare [[(PublicKey crypto c, Proof crypto v c)]]
decShare) =
	let zkp :: ByteString
zkp = PublicKey crypto c -> ByteString
forall crypto c.
CryptoParams crypto c =>
PublicKey crypto c -> ByteString
decryptionShareStatement PublicKey crypto c
trusteePubKey in
	ExceptT ErrorTally m ()
-> ([Encryption crypto v c]
    -> [(PublicKey crypto c, Proof crypto v c)]
    -> ExceptT ErrorTally m ())
-> EncryptedTally crypto v c
-> [[(PublicKey crypto c, Proof crypto v c)]]
-> ExceptT ErrorTally m ()
forall (f :: * -> *) a b c.
Applicative f =>
f () -> (a -> b -> f c) -> [a] -> [b] -> f ()
isoZipWithM_ (ErrorTally -> ExceptT ErrorTally m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfQuestions)
	 (ExceptT ErrorTally m ()
-> (Encryption crypto v c
    -> (PublicKey crypto c, Proof crypto v c)
    -> ExceptT ErrorTally m ())
-> [Encryption crypto v c]
-> [(PublicKey crypto c, Proof crypto v c)]
-> ExceptT ErrorTally m ()
forall (f :: * -> *) a b c.
Applicative f =>
f () -> (a -> b -> f c) -> [a] -> [b] -> f ()
isoZipWithM_ (ErrorTally -> ExceptT ErrorTally m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfChoices) ((Encryption crypto v c
  -> (PublicKey crypto c, Proof crypto v c)
  -> ExceptT ErrorTally m ())
 -> [Encryption crypto v c]
 -> [(PublicKey crypto c, Proof crypto v c)]
 -> ExceptT ErrorTally m ())
-> (Encryption crypto v c
    -> (PublicKey crypto c, Proof crypto v c)
    -> ExceptT ErrorTally m ())
-> [Encryption crypto v c]
-> [(PublicKey crypto c, Proof crypto v c)]
-> ExceptT ErrorTally m ()
forall a b. (a -> b) -> a -> b
$
	 \Encryption{PublicKey crypto c
encryption_vault :: PublicKey crypto c
encryption_nonce :: PublicKey crypto c
encryption_vault :: forall crypto k (v :: k) c. Encryption crypto v c -> G crypto c
encryption_nonce :: forall crypto k (v :: k) c. Encryption crypto v c -> G crypto c
..} (PublicKey crypto c
decFactor, Proof crypto v c
proof) ->
		Bool -> ExceptT ErrorTally m () -> ExceptT ErrorTally m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Proof crypto v c -> Challenge crypto c
forall crypto k (v :: k) c. Proof crypto v c -> Challenge crypto c
proof_challenge Proof crypto v c
proof Challenge crypto c -> Challenge crypto c -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> [PublicKey crypto c] -> Challenge crypto c
forall crypto c.
CryptoParams crypto c =>
ByteString -> [G crypto c] -> E crypto c
hash ByteString
zkp
		 [ Proof crypto v c
-> PublicKey crypto c -> PublicKey crypto c -> PublicKey crypto c
forall k crypto (v :: k) c.
(Reifies v Version, CryptoParams crypto c) =>
Proof crypto v c -> G crypto c -> G crypto c -> G crypto c
commit Proof crypto v c
proof PublicKey crypto c
forall crypto c. CryptoParams crypto c => G crypto c
groupGen PublicKey crypto c
trusteePubKey
		 , Proof crypto v c
-> PublicKey crypto c -> PublicKey crypto c -> PublicKey crypto c
forall k crypto (v :: k) c.
(Reifies v Version, CryptoParams crypto c) =>
Proof crypto v c -> G crypto c -> G crypto c -> G crypto c
commit Proof crypto v c
proof PublicKey crypto c
encryption_nonce PublicKey crypto c
decFactor
		 ]) (ExceptT ErrorTally m () -> ExceptT ErrorTally m ())
-> ExceptT ErrorTally m () -> ExceptT ErrorTally m ()
forall a b. (a -> b) -> a -> b
$ ErrorTally -> ExceptT ErrorTally m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_WrongProof)
	 EncryptedTally crypto v c
encByChoiceByQuest
	 [[(PublicKey crypto c, Proof crypto v c)]]
decShare

verifyDecryptionShareByTrustee ::
 Reifies v Version =>
 CryptoParams crypto c =>
 Monad m =>
 EncryptedTally crypto v c -> [PublicKey crypto c] -> [DecryptionShare crypto v c] ->
 ExceptT ErrorTally m ()
verifyDecryptionShareByTrustee :: EncryptedTally crypto v c
-> [PublicKey crypto c]
-> [DecryptionShare crypto v c]
-> ExceptT ErrorTally m ()
verifyDecryptionShareByTrustee EncryptedTally crypto v c
encTally =
	ExceptT ErrorTally m ()
-> (PublicKey crypto c
    -> DecryptionShare crypto v c -> ExceptT ErrorTally m ())
-> [PublicKey crypto c]
-> [DecryptionShare crypto v c]
-> ExceptT ErrorTally m ()
forall (f :: * -> *) a b c.
Applicative f =>
f () -> (a -> b -> f c) -> [a] -> [b] -> f ()
isoZipWithM_ (ErrorTally -> ExceptT ErrorTally m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfTrustees)
	 (EncryptedTally crypto v c
-> PublicKey crypto c
-> DecryptionShare crypto v c
-> ExceptT ErrorTally m ()
forall v crypto c (m :: * -> *).
(Reifies v Version, CryptoParams crypto c, Monad m) =>
EncryptedTally crypto v c
-> PublicKey crypto c
-> DecryptionShare crypto v c
-> ExceptT ErrorTally m ()
verifyDecryptionShare EncryptedTally crypto v c
encTally)