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

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

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

-- * Type 'TrusteePublicKey'
data TrusteePublicKey crypto v c = TrusteePublicKey
 { TrusteePublicKey crypto v c -> PublicKey crypto c
trustee_PublicKey      :: !(PublicKey crypto c)
 , TrusteePublicKey crypto v c -> Proof crypto v c
trustee_SecretKeyProof :: !(Proof crypto v c)
	-- ^ NOTE: It is important to ensure
	-- that each trustee generates its key pair independently
	-- of the 'PublicKey's published by the other trustees.
	-- Otherwise, a dishonest trustee could publish as 'PublicKey'
	-- its genuine 'PublicKey' divided by the 'PublicKey's of the other trustees.
	-- This would then lead to the 'election_PublicKey'
	-- being equal to this dishonest trustee's 'PublicKey',
	-- which means that knowing its 'SecretKey' would be sufficient
	-- for decrypting messages encrypted to the 'election_PublicKey'.
	-- To avoid this attack, each trustee publishing a 'PublicKey'
	-- must 'prove' knowledge of the corresponding 'SecretKey'.
	-- Which is done in 'proveIndispensableTrusteePublicKey'
	-- and 'verifyIndispensableTrusteePublicKey'.
 } deriving ((forall x.
 TrusteePublicKey crypto v c -> Rep (TrusteePublicKey crypto v c) x)
-> (forall x.
    Rep (TrusteePublicKey crypto v c) x -> TrusteePublicKey crypto v c)
-> Generic (TrusteePublicKey crypto v c)
forall x.
Rep (TrusteePublicKey crypto v c) x -> TrusteePublicKey crypto v c
forall x.
TrusteePublicKey crypto v c -> Rep (TrusteePublicKey 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 (TrusteePublicKey crypto v c) x -> TrusteePublicKey crypto v c
forall crypto v c x.
TrusteePublicKey crypto v c -> Rep (TrusteePublicKey crypto v c) x
$cto :: forall crypto v c x.
Rep (TrusteePublicKey crypto v c) x -> TrusteePublicKey crypto v c
$cfrom :: forall crypto v c x.
TrusteePublicKey crypto v c -> Rep (TrusteePublicKey crypto v c) x
Generic)
deriving instance Eq (G crypto c) => Eq (TrusteePublicKey crypto v c)
deriving instance (Show (G crypto c), Show (PublicKey crypto c)) => Show (TrusteePublicKey crypto v c)
deriving instance NFData (G crypto c) => NFData (TrusteePublicKey crypto v c)
instance
 ( Reifies v Version
 , ToJSON (G crypto c)
 ) => ToJSON (TrusteePublicKey crypto v c) where
	toJSON :: TrusteePublicKey crypto v c -> Value
toJSON TrusteePublicKey{G crypto c
Proof crypto v c
trustee_SecretKeyProof :: Proof crypto v c
trustee_PublicKey :: G crypto c
trustee_SecretKeyProof :: forall crypto v c. TrusteePublicKey crypto v c -> Proof crypto v c
trustee_PublicKey :: forall crypto v c.
TrusteePublicKey crypto v c -> PublicKey crypto c
..} =
		[Pair] -> Value
JSON.object
		 [ Text
"pok"        Text -> Proof crypto v c -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Proof crypto v c
trustee_SecretKeyProof
		 , Text
"public_key" Text -> G crypto c -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= G crypto c
trustee_PublicKey
		 ]
	toEncoding :: TrusteePublicKey crypto v c -> Encoding
toEncoding TrusteePublicKey{G crypto c
Proof crypto v c
trustee_SecretKeyProof :: Proof crypto v c
trustee_PublicKey :: G crypto c
trustee_SecretKeyProof :: forall crypto v c. TrusteePublicKey crypto v c -> Proof crypto v c
trustee_PublicKey :: forall crypto v c.
TrusteePublicKey crypto v c -> PublicKey crypto c
..} =
		Series -> Encoding
JSON.pairs
		 (  Text
"pok"        Text -> Proof crypto v c -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Proof crypto v c
trustee_SecretKeyProof
		 Series -> Series -> Series
forall a. Semigroup a => a -> a -> a
<> Text
"public_key" Text -> G crypto c -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= G crypto c
trustee_PublicKey
		 )
instance
 ( Reifies v Version
 , CryptoParams crypto c
 ) => FromJSON (TrusteePublicKey crypto v c) where
	parseJSON :: Value -> Parser (TrusteePublicKey crypto v c)
parseJSON = String
-> (Object -> Parser (TrusteePublicKey crypto v c))
-> Value
-> Parser (TrusteePublicKey crypto v c)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
JSON.withObject String
"TrusteePublicKey" ((Object -> Parser (TrusteePublicKey crypto v c))
 -> Value -> Parser (TrusteePublicKey crypto v c))
-> (Object -> Parser (TrusteePublicKey crypto v c))
-> Value
-> Parser (TrusteePublicKey crypto v c)
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
		PublicKey crypto c
trustee_PublicKey <- Object
o Object -> Text -> Parser (PublicKey crypto c)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"public_key"
		Proof crypto v c
trustee_SecretKeyProof <- Object
o Object -> Text -> Parser (Proof crypto v c)
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"pok"
		TrusteePublicKey crypto v c -> Parser (TrusteePublicKey crypto v c)
forall (m :: * -> *) a. Monad m => a -> m a
return TrusteePublicKey :: forall crypto v c.
PublicKey crypto c
-> Proof crypto v c -> TrusteePublicKey crypto v c
TrusteePublicKey{PublicKey crypto c
Proof crypto v c
trustee_SecretKeyProof :: Proof crypto v c
trustee_PublicKey :: PublicKey crypto c
trustee_SecretKeyProof :: Proof crypto v c
trustee_PublicKey :: PublicKey crypto c
..}

-- ** Generating a 'TrusteePublicKey'

-- | @('proveIndispensableTrusteePublicKey' trustSecKey)@
-- returns the 'PublicKey' associated to 'trustSecKey'
-- and a 'Proof' of its knowledge.
proveIndispensableTrusteePublicKey ::
 Reifies v Version =>
 CryptoParams crypto c =>
 Key crypto =>
 Monad m => RandomGen r =>
 SecretKey crypto c -> S.StateT r m (TrusteePublicKey crypto v c)
proveIndispensableTrusteePublicKey :: SecretKey crypto c -> StateT r m (TrusteePublicKey crypto v c)
proveIndispensableTrusteePublicKey SecretKey crypto c
trustSecKey = do
	let trustee_PublicKey :: PublicKey crypto c
trustee_PublicKey = SecretKey crypto c -> PublicKey crypto c
forall crypto c.
(Key crypto, Reifies c crypto) =>
SecretKey crypto c -> PublicKey crypto c
publicKey SecretKey crypto c
trustSecKey
	Proof crypto v c
trustee_SecretKeyProof <-
		SecretKey crypto c
-> [PublicKey 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
trustSecKey [PublicKey crypto c
forall crypto c. CryptoParams crypto c => G crypto c
groupGen] (Oracle [] crypto c -> StateT r m (Proof crypto v c))
-> Oracle [] crypto c -> StateT r m (Proof crypto v c)
forall a b. (a -> b) -> a -> b
$
			ByteString -> Oracle [] crypto c
forall crypto c.
CryptoParams crypto c =>
ByteString -> [G crypto c] -> E crypto c
hash (PublicKey crypto c -> ByteString
forall crypto c.
CryptoParams crypto c =>
PublicKey crypto c -> ByteString
indispensableTrusteePublicKeyStatement PublicKey crypto c
trustee_PublicKey)
	TrusteePublicKey crypto v c
-> StateT r m (TrusteePublicKey crypto v c)
forall (m :: * -> *) a. Monad m => a -> m a
return TrusteePublicKey :: forall crypto v c.
PublicKey crypto c
-> Proof crypto v c -> TrusteePublicKey crypto v c
TrusteePublicKey{PublicKey crypto c
Proof crypto v c
trustee_SecretKeyProof :: Proof crypto v c
trustee_PublicKey :: PublicKey crypto c
trustee_SecretKeyProof :: Proof crypto v c
trustee_PublicKey :: PublicKey crypto c
..}

-- ** Checking a 'TrusteePublicKey' before incorporating it into the 'Election''s 'PublicKey'

-- | @('verifyIndispensableTrusteePublicKey' trustPubKey)@
-- returns 'True' iif. the given 'trustee_SecretKeyProof'
-- does 'prove' that the 'SecretKey' associated with
-- the given 'trustee_PublicKey' is known by the trustee.
verifyIndispensableTrusteePublicKey ::
 Reifies v Version =>
 CryptoParams crypto c =>
 Monad m =>
 TrusteePublicKey crypto v c ->
 ExceptT ErrorTrusteePublicKey m ()
verifyIndispensableTrusteePublicKey :: TrusteePublicKey crypto v c -> ExceptT ErrorTrusteePublicKey m ()
verifyIndispensableTrusteePublicKey TrusteePublicKey{PublicKey crypto c
Proof crypto v c
trustee_SecretKeyProof :: Proof crypto v c
trustee_PublicKey :: PublicKey crypto c
trustee_SecretKeyProof :: forall crypto v c. TrusteePublicKey crypto v c -> Proof crypto v c
trustee_PublicKey :: forall crypto v c.
TrusteePublicKey crypto v c -> PublicKey crypto c
..} =
	Bool
-> ExceptT ErrorTrusteePublicKey m ()
-> ExceptT ErrorTrusteePublicKey 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
trustee_SecretKeyProof 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
		 (PublicKey crypto c -> ByteString
forall crypto c.
CryptoParams crypto c =>
PublicKey crypto c -> ByteString
indispensableTrusteePublicKeyStatement PublicKey crypto c
trustee_PublicKey)
		 [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
trustee_SecretKeyProof PublicKey crypto c
forall crypto c. CryptoParams crypto c => G crypto c
groupGen PublicKey crypto c
trustee_PublicKey]
	 ) (ExceptT ErrorTrusteePublicKey m ()
 -> ExceptT ErrorTrusteePublicKey m ())
-> ExceptT ErrorTrusteePublicKey m ()
-> ExceptT ErrorTrusteePublicKey m ()
forall a b. (a -> b) -> a -> b
$
		ErrorTrusteePublicKey -> ExceptT ErrorTrusteePublicKey m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTrusteePublicKey
ErrorTrusteePublicKey_WrongProof

-- ** Type 'ErrorTrusteePublicKey'
data ErrorTrusteePublicKey
 =   ErrorTrusteePublicKey_WrongProof
     -- ^ The 'trustee_SecretKeyProof' is wrong.
 deriving (ErrorTrusteePublicKey -> ErrorTrusteePublicKey -> Bool
(ErrorTrusteePublicKey -> ErrorTrusteePublicKey -> Bool)
-> (ErrorTrusteePublicKey -> ErrorTrusteePublicKey -> Bool)
-> Eq ErrorTrusteePublicKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ErrorTrusteePublicKey -> ErrorTrusteePublicKey -> Bool
$c/= :: ErrorTrusteePublicKey -> ErrorTrusteePublicKey -> Bool
== :: ErrorTrusteePublicKey -> ErrorTrusteePublicKey -> Bool
$c== :: ErrorTrusteePublicKey -> ErrorTrusteePublicKey -> Bool
Eq,Int -> ErrorTrusteePublicKey -> ShowS
[ErrorTrusteePublicKey] -> ShowS
ErrorTrusteePublicKey -> String
(Int -> ErrorTrusteePublicKey -> ShowS)
-> (ErrorTrusteePublicKey -> String)
-> ([ErrorTrusteePublicKey] -> ShowS)
-> Show ErrorTrusteePublicKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ErrorTrusteePublicKey] -> ShowS
$cshowList :: [ErrorTrusteePublicKey] -> ShowS
show :: ErrorTrusteePublicKey -> String
$cshow :: ErrorTrusteePublicKey -> String
showsPrec :: Int -> ErrorTrusteePublicKey -> ShowS
$cshowsPrec :: Int -> ErrorTrusteePublicKey -> ShowS
Show)

-- ** Hashing
indispensableTrusteePublicKeyStatement ::
 CryptoParams crypto c =>
 PublicKey crypto c -> BS.ByteString
indispensableTrusteePublicKeyStatement :: PublicKey crypto c -> ByteString
indispensableTrusteePublicKeyStatement PublicKey crypto c
trustPubKey =
	ByteString
"pok|"ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<>PublicKey crypto c -> ByteString
forall n. ToNatural n => n -> ByteString
bytesNat PublicKey crypto c
trustPubKeyByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<>ByteString
"|"

-- * 'Election''s 'PublicKey'

-- ** Generating an 'Election''s 'PublicKey' from multiple 'TrusteePublicKey's.

combineIndispensableTrusteePublicKeys ::
 CryptoParams crypto c =>
 [TrusteePublicKey crypto v c] -> PublicKey crypto c
combineIndispensableTrusteePublicKeys :: [TrusteePublicKey crypto v c] -> PublicKey crypto c
combineIndispensableTrusteePublicKeys =
	(TrusteePublicKey crypto v c
 -> PublicKey crypto c -> PublicKey crypto c)
-> PublicKey crypto c
-> [TrusteePublicKey crypto v c]
-> PublicKey crypto c
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr (\TrusteePublicKey{PublicKey crypto c
Proof crypto v c
trustee_SecretKeyProof :: Proof crypto v c
trustee_PublicKey :: PublicKey crypto c
trustee_SecretKeyProof :: forall crypto v c. TrusteePublicKey crypto v c -> Proof crypto v c
trustee_PublicKey :: forall crypto v c.
TrusteePublicKey crypto v c -> PublicKey crypto c
..} -> (PublicKey crypto c
trustee_PublicKey PublicKey crypto c -> PublicKey crypto c -> PublicKey crypto c
forall a. Semiring a => a -> a -> a
*)) PublicKey crypto c
forall a. Semiring a => a
one

-- ** Checking the trustee's 'DecryptionShare's before decrypting an 'EncryptedTally'.

verifyIndispensableDecryptionShareByTrustee ::
 Reifies v Version =>
 CryptoParams crypto c =>
 Monad m =>
 EncryptedTally crypto v c -> [PublicKey crypto c] -> [DecryptionShare crypto v c] ->
 ExceptT ErrorTally m ()
verifyIndispensableDecryptionShareByTrustee :: EncryptedTally crypto v c
-> [PublicKey crypto c]
-> [DecryptionShare crypto v c]
-> ExceptT ErrorTally m ()
verifyIndispensableDecryptionShareByTrustee EncryptedTally crypto v c
encByChoiceByQuest =
	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 -> ExceptT ErrorTally m ())
-> ErrorTally -> ExceptT ErrorTally m ()
forall a b. (a -> b) -> a -> b
$ 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
encByChoiceByQuest)

-- ** Decrypting an 'EncryptedTally' from multiple 'TrusteePublicKey's.

-- | @('combineDecryptionShares' pubKeyByTrustee decShareByTrustee)@
-- returns the 'DecryptionFactor's by choice by 'Question'
combineIndispensableDecryptionShares ::
 Reifies v Version =>
 CryptoParams crypto c =>
 [PublicKey crypto c] -> DecryptionShareCombinator crypto v c
combineIndispensableDecryptionShares :: [PublicKey crypto c] -> DecryptionShareCombinator crypto v c
combineIndispensableDecryptionShares
 [PublicKey crypto c]
pubKeyByTrustee
 EncryptedTally crypto v c
encByChoiceByQuest
 [DecryptionShare crypto v c]
decByChoiceByQuestByTrustee = do
	EncryptedTally crypto v c
-> [PublicKey crypto c]
-> [DecryptionShare crypto v c]
-> ExceptT ErrorTally Identity ()
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 ()
verifyIndispensableDecryptionShareByTrustee
	 EncryptedTally crypto v c
encByChoiceByQuest
	 [PublicKey crypto c]
pubKeyByTrustee
	 [DecryptionShare crypto v c]
decByChoiceByQuestByTrustee
	(DecryptionShare [[(PublicKey crypto c, Proof crypto v c)]]
dec0,[DecryptionShare crypto v c]
decs) <-
		ExceptT
  ErrorTally
  Identity
  (DecryptionShare crypto v c, [DecryptionShare crypto v c])
-> ((DecryptionShare crypto v c, [DecryptionShare crypto v c])
    -> ExceptT
         ErrorTally
         Identity
         (DecryptionShare crypto v c, [DecryptionShare crypto v c]))
-> Maybe (DecryptionShare crypto v c, [DecryptionShare crypto v c])
-> ExceptT
     ErrorTally
     Identity
     (DecryptionShare crypto v c, [DecryptionShare crypto v c])
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ErrorTally
-> ExceptT
     ErrorTally
     Identity
     (DecryptionShare crypto v c, [DecryptionShare crypto v c])
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfTrustees) (DecryptionShare crypto v c, [DecryptionShare crypto v c])
-> ExceptT
     ErrorTally
     Identity
     (DecryptionShare crypto v c, [DecryptionShare crypto v c])
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (DecryptionShare crypto v c, [DecryptionShare crypto v c])
 -> ExceptT
      ErrorTally
      Identity
      (DecryptionShare crypto v c, [DecryptionShare crypto v c]))
-> Maybe (DecryptionShare crypto v c, [DecryptionShare crypto v c])
-> ExceptT
     ErrorTally
     Identity
     (DecryptionShare crypto v c, [DecryptionShare crypto v c])
forall a b. (a -> b) -> a -> b
$
		[DecryptionShare crypto v c]
-> Maybe (DecryptionShare crypto v c, [DecryptionShare crypto v c])
forall a. [a] -> Maybe (a, [a])
List.uncons [DecryptionShare crypto v c]
decByChoiceByQuestByTrustee
	([[PublicKey crypto c]]
 -> [[(PublicKey crypto c, Proof crypto v c)]]
 -> Except ErrorTally [[PublicKey crypto c]])
-> [[PublicKey crypto c]]
-> [[[(PublicKey crypto c, Proof crypto v c)]]]
-> Except ErrorTally [[PublicKey crypto c]]
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (ExceptT ErrorTally Identity ()
-> ([PublicKey crypto c]
    -> [(PublicKey crypto c, Proof crypto v c)]
    -> ExceptT ErrorTally Identity [PublicKey crypto c])
-> [[PublicKey crypto c]]
-> [[(PublicKey crypto c, Proof crypto v c)]]
-> Except ErrorTally [[PublicKey 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 [PublicKey crypto c]
-> ([PublicKey crypto c]
    -> ExceptT ErrorTally Identity [PublicKey crypto c])
-> Maybe [PublicKey crypto c]
-> ExceptT ErrorTally Identity [PublicKey crypto c]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ErrorTally -> ExceptT ErrorTally Identity [PublicKey crypto c]
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE ErrorTally
ErrorTally_NumberOfChoices) [PublicKey crypto c]
-> ExceptT ErrorTally Identity [PublicKey crypto c]
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe [PublicKey crypto c]
 -> ExceptT ErrorTally Identity [PublicKey crypto c])
-> ([PublicKey crypto c]
    -> [(PublicKey crypto c, Proof crypto v c)]
    -> Maybe [PublicKey crypto c])
-> [PublicKey crypto c]
-> [(PublicKey crypto c, Proof crypto v c)]
-> ExceptT ErrorTally Identity [PublicKey crypto c]
forall c d a b. (c -> d) -> (a -> b -> c) -> a -> b -> d
`o2`
		(PublicKey crypto c
 -> (PublicKey crypto c, Proof crypto v c) -> PublicKey crypto c)
-> [PublicKey crypto c]
-> [(PublicKey crypto c, Proof crypto v c)]
-> Maybe [PublicKey crypto c]
forall a b c. (a -> b -> c) -> [a] -> [b] -> Maybe [c]
isoZipWith (\PublicKey crypto c
a (PublicKey crypto c
decFactor, Proof crypto v c
_proof) -> PublicKey crypto c
a PublicKey crypto c -> PublicKey crypto c -> PublicKey crypto c
forall a. Semiring a => a -> a -> a
* PublicKey crypto c
decFactor)))
	 (((PublicKey crypto c, Proof crypto v c) -> PublicKey crypto c
forall a b. (a, b) -> a
fst ((PublicKey crypto c, Proof crypto v c) -> PublicKey crypto c)
-> [(PublicKey crypto c, Proof crypto v c)] -> [PublicKey crypto c]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) ([(PublicKey crypto c, Proof crypto v c)] -> [PublicKey crypto c])
-> [[(PublicKey crypto c, Proof crypto v c)]]
-> [[PublicKey crypto c]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [[(PublicKey crypto c, Proof crypto v c)]]
dec0) (DecryptionShare crypto v c
-> [[(PublicKey crypto c, Proof crypto v c)]]
forall crypto v c.
DecryptionShare crypto v c
-> [[(DecryptionFactor crypto c, Proof crypto v c)]]
unDecryptionShare (DecryptionShare crypto v c
 -> [[(PublicKey crypto c, Proof crypto v c)]])
-> [DecryptionShare crypto v c]
-> [[[(PublicKey crypto c, Proof crypto v c)]]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [DecryptionShare crypto v c]
decs)