{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Ouroboros.Consensus.Committee.Class
(
CryptoSupportsVotingCommittee (..)
, VotesWithSameTarget
, getElectionIdFromVotes
, getVoteCandidateFromVotes
, getRawVotes
, VotesWithSameTargetError (..)
, ensureSameTarget
) where
import Data.Containers.NonEmpty (HasNonEmpty (..))
import Data.Either (partitionEithers)
import Data.Kind (Type)
import Data.List.NonEmpty (NonEmpty (..))
import Ouroboros.Consensus.Committee.Crypto
( CryptoSupportsVoteSigning
, ElectionId
, PrivateKey
, VoteCandidate
)
import Ouroboros.Consensus.Committee.Types (PoolId, VoteWeight)
class
CryptoSupportsVoteSigning crypto =>
CryptoSupportsVotingCommittee crypto committee
where
data VotingCommittee crypto committee :: Type
data VotingCommitteeInput crypto committee :: Type
data VotingCommitteeError crypto committee :: Type
data EligibilityWitness crypto committee :: Type
data Vote crypto committee :: Type
data Cert crypto committee :: Type
mkVotingCommittee ::
VotingCommitteeInput crypto committee ->
Either
(VotingCommitteeError crypto committee)
(VotingCommittee crypto committee)
checkShouldVote ::
VotingCommittee crypto committee ->
PoolId ->
PrivateKey crypto ->
ElectionId crypto ->
Either
(VotingCommitteeError crypto committee)
(Maybe (EligibilityWitness crypto committee))
forgeVote ::
EligibilityWitness crypto committee ->
PrivateKey crypto ->
ElectionId crypto ->
VoteCandidate crypto ->
Vote crypto committee
verifyVote ::
VotingCommittee crypto committee ->
Vote crypto committee ->
Either
(VotingCommitteeError crypto committee)
(EligibilityWitness crypto committee)
eligiblePartyVoteWeight ::
VotingCommittee crypto committee ->
EligibilityWitness crypto committee ->
VoteWeight
forgeCert ::
VotesWithSameTarget crypto committee ->
Cert crypto committee
verifyCert ::
VotingCommittee crypto committee ->
Cert crypto committee ->
Either
(VotingCommitteeError crypto committee)
(NE [EligibilityWitness crypto committee])
data VotesWithSameTarget crypto committee
= VotesWithSameTarget
(ElectionId crypto)
(VoteCandidate crypto)
(NE [Vote crypto committee])
getElectionIdFromVotes ::
VotesWithSameTarget crypto committee ->
ElectionId crypto
getElectionIdFromVotes :: forall crypto committee.
VotesWithSameTarget crypto committee -> ElectionId crypto
getElectionIdFromVotes (VotesWithSameTarget ElectionId crypto
electionId VoteCandidate crypto
_ NE [Vote crypto committee]
_) =
ElectionId crypto
electionId
getVoteCandidateFromVotes ::
VotesWithSameTarget crypto committee ->
VoteCandidate crypto
getVoteCandidateFromVotes :: forall crypto committee.
VotesWithSameTarget crypto committee -> VoteCandidate crypto
getVoteCandidateFromVotes (VotesWithSameTarget ElectionId crypto
_ VoteCandidate crypto
candidate NE [Vote crypto committee]
_) =
VoteCandidate crypto
candidate
getRawVotes ::
VotesWithSameTarget crypto committee ->
NE [Vote crypto committee]
getRawVotes :: forall crypto committee.
VotesWithSameTarget crypto committee -> NE [Vote crypto committee]
getRawVotes (VotesWithSameTarget ElectionId crypto
_ VoteCandidate crypto
_ NE [Vote crypto committee]
votes) =
NE [Vote crypto committee]
votes
data VotesWithSameTargetError crypto committee
= EmptyVotes
| TargetMismatch
(NE [Vote crypto committee])
(NE [Vote crypto committee])
ensureSameTarget ::
( Eq (ElectionId crypto)
, Eq (VoteCandidate crypto)
) =>
(Vote crypto committee -> (ElectionId crypto, VoteCandidate crypto)) ->
[Vote crypto committee] ->
Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee)
ensureSameTarget :: forall crypto committee.
(Eq (ElectionId crypto), Eq (VoteCandidate crypto)) =>
(Vote crypto committee
-> (ElectionId crypto, VoteCandidate crypto))
-> [Vote crypto committee]
-> Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee)
ensureSameTarget Vote crypto committee -> (ElectionId crypto, VoteCandidate crypto)
getTarget = \case
[] ->
VotesWithSameTargetError crypto committee
-> Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee)
forall a b. a -> Either a b
Left VotesWithSameTargetError crypto committee
forall crypto committee. VotesWithSameTargetError crypto committee
EmptyVotes
(Vote crypto committee
firstVote : [Vote crypto committee]
nextVotes) -> do
case [Either (Vote crypto committee) (Vote crypto committee)]
-> ([Vote crypto committee], [Vote crypto committee])
forall a b. [Either a b] -> ([a], [b])
partitionEithers ((Vote crypto committee
-> Either (Vote crypto committee) (Vote crypto committee))
-> [Vote crypto committee]
-> [Either (Vote crypto committee) (Vote crypto committee)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Vote crypto committee
-> Either (Vote crypto committee) (Vote crypto committee)
matchesTarget [Vote crypto committee]
nextVotes) of
([], [Vote crypto committee]
matchingVotes) ->
VotesWithSameTarget crypto committee
-> Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee)
forall a b. b -> Either a b
Right (VotesWithSameTarget crypto committee
-> Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee))
-> VotesWithSameTarget crypto committee
-> Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee)
forall a b. (a -> b) -> a -> b
$
ElectionId crypto
-> VoteCandidate crypto
-> NE [Vote crypto committee]
-> VotesWithSameTarget crypto committee
forall crypto committee.
ElectionId crypto
-> VoteCandidate crypto
-> NE [Vote crypto committee]
-> VotesWithSameTarget crypto committee
VotesWithSameTarget
ElectionId crypto
electionId
VoteCandidate crypto
candidate
(Vote crypto committee
firstVote Vote crypto committee
-> [Vote crypto committee] -> NonEmpty (Vote crypto committee)
forall a. a -> [a] -> NonEmpty a
:| [Vote crypto committee]
matchingVotes)
(Vote crypto committee
firstMismatchingVote : [Vote crypto committee]
nextMismatchingVotes, [Vote crypto committee]
matchingVotes) ->
VotesWithSameTargetError crypto committee
-> Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee)
forall a b. a -> Either a b
Left (VotesWithSameTargetError crypto committee
-> Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee))
-> VotesWithSameTargetError crypto committee
-> Either
(VotesWithSameTargetError crypto committee)
(VotesWithSameTarget crypto committee)
forall a b. (a -> b) -> a -> b
$
NE [Vote crypto committee]
-> NE [Vote crypto committee]
-> VotesWithSameTargetError crypto committee
forall crypto committee.
NE [Vote crypto committee]
-> NE [Vote crypto committee]
-> VotesWithSameTargetError crypto committee
TargetMismatch
(Vote crypto committee
firstVote Vote crypto committee
-> [Vote crypto committee] -> NonEmpty (Vote crypto committee)
forall a. a -> [a] -> NonEmpty a
:| [Vote crypto committee]
matchingVotes)
(Vote crypto committee
firstMismatchingVote Vote crypto committee
-> [Vote crypto committee] -> NonEmpty (Vote crypto committee)
forall a. a -> [a] -> NonEmpty a
:| [Vote crypto committee]
nextMismatchingVotes)
where
target :: (ElectionId crypto, VoteCandidate crypto)
target@(ElectionId crypto
electionId, VoteCandidate crypto
candidate) =
Vote crypto committee -> (ElectionId crypto, VoteCandidate crypto)
getTarget Vote crypto committee
firstVote
matchesTarget :: Vote crypto committee
-> Either (Vote crypto committee) (Vote crypto committee)
matchesTarget Vote crypto committee
v'
| Vote crypto committee -> (ElectionId crypto, VoteCandidate crypto)
getTarget Vote crypto committee
v' (ElectionId crypto, VoteCandidate crypto)
-> (ElectionId crypto, VoteCandidate crypto) -> Bool
forall a. Eq a => a -> a -> Bool
/= (ElectionId crypto, VoteCandidate crypto)
target = Vote crypto committee
-> Either (Vote crypto committee) (Vote crypto committee)
forall a b. a -> Either a b
Left Vote crypto committee
v'
| Bool
otherwise = Vote crypto committee
-> Either (Vote crypto committee) (Vote crypto committee)
forall a b. b -> Either a b
Right Vote crypto committee
v'