{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Test.Consensus.Committee.WFALS.Tests (tests) where
import Cardano.Ledger.BaseTypes
import Data.Function (on)
import Data.List (intercalate, sortOn)
import Data.List.NonEmpty (NonEmpty ((:|)))
import qualified Data.List.NonEmpty as NonEmpty
import Data.Map (Map)
import qualified Data.Map.Strict as Map
import Data.Proxy (Proxy (..))
import Ouroboros.Consensus.Committee.Class
( CryptoSupportsVotingCommittee (..)
, ensureUniqueVotesWithSameTarget
)
import Ouroboros.Consensus.Committee.Crypto
( CryptoSupportsVRF (..)
, ElectionId
, PrivateKey
, PublicKey
, VRFPoolContext (..)
, evalVRF
, mkVRFElectionInput
)
import Ouroboros.Consensus.Committee.LS (LocalSortitionNumSeats (..))
import qualified Ouroboros.Consensus.Committee.LS as LS
import Ouroboros.Consensus.Committee.Types
( LedgerStake (..)
, PoolId
, TargetCommitteeSize (..)
)
import Ouroboros.Consensus.Committee.WFA
( NonPersistentCommitteeSize (..)
, PersistentCommitteeSize (..)
, SeatIndex (..)
, mkExtWFAStakeDistr
)
import Ouroboros.Consensus.Committee.WFALS
( EligibilityWitness (..)
, Vote (..)
, VotingCommitteeInput (..)
, WFALS
, nonPersistentCommitteeSize
, persistentCommitteeSize
, totalNonPersistentStake
)
import Test.Consensus.Committee.TestCrypto (TestCrypto)
import qualified Test.Consensus.Committee.TestCrypto as TestCrypto
import Test.Consensus.Committee.Utils
( eqWithShowCmp
, genEpochNonce
, genPools
, mkBucket
, onError
, tabulateNumPools
, tabulatePoolStake
, unfairWFATiebreaker
)
import Test.QuickCheck
( Gen
, Property
, Testable (..)
, choose
, counterexample
, elements
, forAll
, forAllShow
, frequency
, tabulate
)
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.QuickCheck (testProperty)
import Test.Util.TestEnv (adjustQuickCheckTests)
tests :: TestTree
tests :: TestTree
tests =
String -> [TestTree] -> TestTree
testGroup
String
"Implementation tests using TestCrypto"
[ (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
String
"prop_checkShouldVote_verifyVote"
Property
prop_checkShouldVote_verifyVote
, (Int -> Int) -> TestTree -> TestTree
adjustQuickCheckTests (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
String
"prop_fakeVotesDontVerify"
Property
prop_fakeVotesDontVerify
, String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty
String
"prop_forgeCert_verifyCert"
Property
prop_forgeCert_verifyCert
]
prop_checkShouldVote_verifyVote :: Property
prop_checkShouldVote_verifyVote :: Property
prop_checkShouldVote_verifyVote =
Gen
(Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake))
-> (Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Int
-> Gen
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF))
-> Gen
(Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake))
forall privateKey publicKey.
Int
-> Gen (privateKey, publicKey)
-> Gen (Map PoolId (privateKey, publicKey, LedgerStake))
genPools Int
1000 Gen
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
TestCrypto.genKeyPair) ((Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property)
-> (Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools ->
Gen TargetCommitteeSize
-> (TargetCommitteeSize -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
-> Gen TargetCommitteeSize
genTargetCommitteeSize Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools) ((TargetCommitteeSize -> Property) -> Property)
-> (TargetCommitteeSize -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \TargetCommitteeSize
targetCommitteeSize ->
Gen (PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
-> ((PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
-> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
-> Gen (PoolId, PrivateKey TestCrypto, LedgerStake)
samplePool Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools) (((PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
-> Property)
-> Property)
-> ((PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
-> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \(PoolId
poolId, (PrivateKey SIGN, PrivateKey VRF)
poolPrivateKey, LedgerStake
poolStake) ->
Gen Nonce -> (Nonce -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Nonce
genEpochNonce ((Nonce -> Property) -> Property)
-> (Nonce -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Nonce
epochNonce ->
Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Word64
Gen (ElectionId TestCrypto)
TestCrypto.genElectionId ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
electionId ->
Gen ByteString -> (ByteString -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen ByteString
Gen (VoteCandidate TestCrypto)
TestCrypto.genVoteCandidate ((ByteString -> Property) -> Property)
-> (ByteString -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \ByteString
candidate -> do
let extWFAStakeDistr :: ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
extWFAStakeDistr =
WFATiebreaker
-> Map PoolId (LedgerStake, (PublicKey SIGN, PublicKey VRF))
-> Either
WFAError (ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
forall a.
WFATiebreaker
-> Map PoolId (LedgerStake, a)
-> Either WFAError (ExtWFAStakeDistr a)
mkExtWFAStakeDistr
WFATiebreaker
unfairWFATiebreaker
((((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> (LedgerStake, (PublicKey SIGN, PublicKey VRF)))
-> Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Map PoolId (LedgerStake, (PublicKey SIGN, PublicKey VRF))
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map (\((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pubKey, LedgerStake
stake) -> (LedgerStake
stake, (PublicKey SIGN, PublicKey VRF)
pubKey)) Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools)
Either WFAError (ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
-> (WFAError -> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
-> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
forall err a. Either err a -> (err -> a) -> a
`onError` \WFAError
err ->
String -> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
forall a. HasCallStack => String -> a
error (String
"mkExtWFAStakeDistr failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> WFAError -> String
forall a. Show a => a -> String
show WFAError
err)
let committee :: VotingCommittee TestCrypto WFALS
committee =
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
VotingCommitteeInput crypto committee
-> Either
(VotingCommitteeError crypto committee)
(VotingCommittee crypto committee)
mkVotingCommittee @TestCrypto @WFALS
( Nonce
-> TargetCommitteeSize
-> ExtWFAStakeDistr (PublicKey TestCrypto)
-> VotingCommitteeInput TestCrypto WFALS
forall crypto.
Nonce
-> TargetCommitteeSize
-> ExtWFAStakeDistr (PublicKey crypto)
-> VotingCommitteeInput crypto WFALS
WFALSVotingCommitteeInput
Nonce
epochNonce
TargetCommitteeSize
targetCommitteeSize
ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
ExtWFAStakeDistr (PublicKey TestCrypto)
extWFAStakeDistr
)
Either
(VotingCommitteeError TestCrypto WFALS)
(VotingCommittee TestCrypto WFALS)
-> (VotingCommitteeError TestCrypto WFALS
-> VotingCommittee TestCrypto WFALS)
-> VotingCommittee TestCrypto WFALS
forall err a. Either err a -> (err -> a) -> a
`onError` \VotingCommitteeError TestCrypto WFALS
err ->
String -> VotingCommittee TestCrypto WFALS
forall a. HasCallStack => String -> a
error (String
"mkVotingCommittee failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VotingCommitteeError TestCrypto WFALS -> String
forall a. Show a => a -> String
show VotingCommitteeError TestCrypto WFALS
err)
let shouldVote :: Maybe (EligibilityWitness TestCrypto WFALS)
shouldVote =
VotingCommittee TestCrypto WFALS
-> PoolId
-> PrivateKey TestCrypto
-> ElectionId TestCrypto
-> Either
(VotingCommitteeError TestCrypto WFALS)
(Maybe (EligibilityWitness TestCrypto WFALS))
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
VotingCommittee crypto committee
-> PoolId
-> PrivateKey crypto
-> ElectionId crypto
-> Either
(VotingCommitteeError crypto committee)
(Maybe (EligibilityWitness crypto committee))
checkShouldVote
VotingCommittee TestCrypto WFALS
committee
PoolId
poolId
(PrivateKey SIGN, PrivateKey VRF)
PrivateKey TestCrypto
poolPrivateKey
Word64
ElectionId TestCrypto
electionId
Either
(VotingCommitteeError TestCrypto WFALS)
(Maybe (EligibilityWitness TestCrypto WFALS))
-> (VotingCommitteeError TestCrypto WFALS
-> Maybe (EligibilityWitness TestCrypto WFALS))
-> Maybe (EligibilityWitness TestCrypto WFALS)
forall err a. Either err a -> (err -> a) -> a
`onError` \VotingCommitteeError TestCrypto WFALS
err ->
String -> Maybe (EligibilityWitness TestCrypto WFALS)
forall a. HasCallStack => String -> a
error (String
"checkShouldVote failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VotingCommitteeError TestCrypto WFALS -> String
forall a. Show a => a -> String
show VotingCommitteeError TestCrypto WFALS
err)
Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property -> Property
forall privateKey publicKey.
Map PoolId (privateKey, publicKey, LedgerStake)
-> Property -> Property
tabulateNumPools Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools
(Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TargetCommitteeSize -> Property -> Property
tabulateTargetCommitteeSize TargetCommitteeSize
targetCommitteeSize
(Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LedgerStake -> Property -> Property
tabulatePoolStake LedgerStake
poolStake
(Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (EligibilityWitness TestCrypto WFALS) -> Property -> Property
tabulateShouldVote Maybe (EligibilityWitness TestCrypto WFALS)
shouldVote
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ case Maybe (EligibilityWitness TestCrypto WFALS)
shouldVote of
Just EligibilityWitness TestCrypto WFALS
witness -> do
let vote :: Vote TestCrypto WFALS
vote =
EligibilityWitness TestCrypto WFALS
-> PrivateKey TestCrypto
-> ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> Vote TestCrypto WFALS
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
EligibilityWitness crypto committee
-> PrivateKey crypto
-> ElectionId crypto
-> VoteCandidate crypto
-> Vote crypto committee
forgeVote
EligibilityWitness TestCrypto WFALS
witness
(PrivateKey SIGN, PrivateKey VRF)
PrivateKey TestCrypto
poolPrivateKey
Word64
ElectionId TestCrypto
electionId
ByteString
VoteCandidate TestCrypto
candidate
case VotingCommittee TestCrypto WFALS
-> Vote TestCrypto WFALS
-> Either
(VotingCommitteeError TestCrypto WFALS)
(EligibilityWitness TestCrypto WFALS)
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
VotingCommittee crypto committee
-> Vote crypto committee
-> Either
(VotingCommitteeError crypto committee)
(EligibilityWitness crypto committee)
verifyVote VotingCommittee TestCrypto WFALS
committee Vote TestCrypto WFALS
vote of
Left VotingCommitteeError TestCrypto WFALS
err ->
String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
(String
"vote verification failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VotingCommitteeError TestCrypto WFALS -> String
forall a. Show a => a -> String
show VotingCommitteeError TestCrypto WFALS
err)
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
Right EligibilityWitness TestCrypto WFALS
witness' ->
String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
String
"vote verification mismatch"
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ (EligibilityWitness TestCrypto WFALS -> String)
-> (EligibilityWitness TestCrypto WFALS
-> EligibilityWitness TestCrypto WFALS -> Bool)
-> EligibilityWitness TestCrypto WFALS
-> EligibilityWitness TestCrypto WFALS
-> Property
forall a. (a -> String) -> (a -> a -> Bool) -> a -> a -> Property
eqWithShowCmp
EligibilityWitness TestCrypto WFALS -> String
showWitness
EligibilityWitness TestCrypto WFALS
-> EligibilityWitness TestCrypto WFALS -> Bool
cmpWitness
EligibilityWitness TestCrypto WFALS
witness
EligibilityWitness TestCrypto WFALS
witness'
Maybe (EligibilityWitness TestCrypto WFALS)
Nothing ->
Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True
prop_fakeVotesDontVerify :: Property
prop_fakeVotesDontVerify :: Property
prop_fakeVotesDontVerify =
Gen
(Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake))
-> (Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Int
-> Gen
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF))
-> Gen
(Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake))
forall privateKey publicKey.
Int
-> Gen (privateKey, publicKey)
-> Gen (Map PoolId (privateKey, publicKey, LedgerStake))
genPools Int
1000 Gen
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
TestCrypto.genKeyPair) ((Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property)
-> (Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools ->
Gen TargetCommitteeSize
-> (TargetCommitteeSize -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
-> Gen TargetCommitteeSize
genTargetCommitteeSize Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools) ((TargetCommitteeSize -> Property) -> Property)
-> (TargetCommitteeSize -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \TargetCommitteeSize
targetCommitteeSize -> do
Gen (PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
-> ((PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
-> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
-> Gen (PoolId, PrivateKey TestCrypto, LedgerStake)
samplePool Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools) (((PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
-> Property)
-> Property)
-> ((PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
-> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \(PoolId
_, (PrivateKey SIGN, PrivateKey VRF)
poolPrivateKey, LedgerStake
poolStake) ->
Gen Nonce -> (Nonce -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Nonce
genEpochNonce ((Nonce -> Property) -> Property)
-> (Nonce -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Nonce
epochNonce ->
Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Word64
Gen (ElectionId TestCrypto)
TestCrypto.genElectionId ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
electionId ->
Gen ByteString -> (ByteString -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen ByteString
Gen (VoteCandidate TestCrypto)
TestCrypto.genVoteCandidate ((ByteString -> Property) -> Property)
-> (ByteString -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \ByteString
candidate -> do
let extWFAStakeDistr :: ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
extWFAStakeDistr =
WFATiebreaker
-> Map PoolId (LedgerStake, (PublicKey SIGN, PublicKey VRF))
-> Either
WFAError (ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
forall a.
WFATiebreaker
-> Map PoolId (LedgerStake, a)
-> Either WFAError (ExtWFAStakeDistr a)
mkExtWFAStakeDistr
WFATiebreaker
unfairWFATiebreaker
((((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> (LedgerStake, (PublicKey SIGN, PublicKey VRF)))
-> Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Map PoolId (LedgerStake, (PublicKey SIGN, PublicKey VRF))
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map (\((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pubKey, LedgerStake
stake) -> (LedgerStake
stake, (PublicKey SIGN, PublicKey VRF)
pubKey)) Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools)
Either WFAError (ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
-> (WFAError -> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
-> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
forall err a. Either err a -> (err -> a) -> a
`onError` \WFAError
err ->
String -> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
forall a. HasCallStack => String -> a
error (String
"mkExtWFAStakeDistr failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> WFAError -> String
forall a. Show a => a -> String
show WFAError
err)
let committee :: VotingCommittee TestCrypto WFALS
committee =
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
VotingCommitteeInput crypto committee
-> Either
(VotingCommitteeError crypto committee)
(VotingCommittee crypto committee)
mkVotingCommittee @TestCrypto @WFALS
( Nonce
-> TargetCommitteeSize
-> ExtWFAStakeDistr (PublicKey TestCrypto)
-> VotingCommitteeInput TestCrypto WFALS
forall crypto.
Nonce
-> TargetCommitteeSize
-> ExtWFAStakeDistr (PublicKey crypto)
-> VotingCommitteeInput crypto WFALS
WFALSVotingCommitteeInput
Nonce
epochNonce
TargetCommitteeSize
targetCommitteeSize
ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
ExtWFAStakeDistr (PublicKey TestCrypto)
extWFAStakeDistr
)
Either
(VotingCommitteeError TestCrypto WFALS)
(VotingCommittee TestCrypto WFALS)
-> (VotingCommitteeError TestCrypto WFALS
-> VotingCommittee TestCrypto WFALS)
-> VotingCommittee TestCrypto WFALS
forall err a. Either err a -> (err -> a) -> a
`onError` \VotingCommitteeError TestCrypto WFALS
err ->
String -> VotingCommittee TestCrypto WFALS
forall a. HasCallStack => String -> a
error (String
"mkVotingCommittee failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VotingCommitteeError TestCrypto WFALS -> String
forall a. Show a => a -> String
show VotingCommitteeError TestCrypto WFALS
err)
Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
-> ((FakeEligibilityWitnessType,
EligibilityWitness TestCrypto WFALS)
-> String)
-> ((FakeEligibilityWitnessType,
EligibilityWitness TestCrypto WFALS)
-> Property)
-> Property
forall prop a.
Testable prop =>
Gen a -> (a -> String) -> (a -> prop) -> Property
forAllShow
( VotingCommittee TestCrypto WFALS
-> PrivateKey TestCrypto
-> LedgerStake
-> Nonce
-> ElectionId TestCrypto
-> Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
genFakeEligibilityWitness
VotingCommittee TestCrypto WFALS
committee
(PrivateKey SIGN, PrivateKey VRF)
PrivateKey TestCrypto
poolPrivateKey
LedgerStake
poolStake
Nonce
epochNonce
Word64
ElectionId TestCrypto
electionId
)
(EligibilityWitness TestCrypto WFALS -> String
showWitness (EligibilityWitness TestCrypto WFALS -> String)
-> ((FakeEligibilityWitnessType,
EligibilityWitness TestCrypto WFALS)
-> EligibilityWitness TestCrypto WFALS)
-> (FakeEligibilityWitnessType,
EligibilityWitness TestCrypto WFALS)
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
-> EligibilityWitness TestCrypto WFALS
forall a b. (a, b) -> b
snd)
(((FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
-> Property)
-> Property)
-> ((FakeEligibilityWitnessType,
EligibilityWitness TestCrypto WFALS)
-> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \(FakeEligibilityWitnessType
fakeWitnessType, EligibilityWitness TestCrypto WFALS
fakeWitness) -> do
let fakeVote :: Vote TestCrypto WFALS
fakeVote =
EligibilityWitness TestCrypto WFALS
-> PrivateKey TestCrypto
-> ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> Vote TestCrypto WFALS
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
EligibilityWitness crypto committee
-> PrivateKey crypto
-> ElectionId crypto
-> VoteCandidate crypto
-> Vote crypto committee
forgeVote
EligibilityWitness TestCrypto WFALS
fakeWitness
(PrivateKey SIGN, PrivateKey VRF)
PrivateKey TestCrypto
poolPrivateKey
Word64
ElectionId TestCrypto
electionId
ByteString
VoteCandidate TestCrypto
candidate
Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property -> Property
forall privateKey publicKey.
Map PoolId (privateKey, publicKey, LedgerStake)
-> Property -> Property
tabulateNumPools Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools
(Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TargetCommitteeSize -> Property -> Property
tabulateTargetCommitteeSize TargetCommitteeSize
targetCommitteeSize
(Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FakeEligibilityWitnessType -> Property -> Property
tabulateFakePersistentWitnessType FakeEligibilityWitnessType
fakeWitnessType
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ do
case VotingCommittee TestCrypto WFALS
-> Vote TestCrypto WFALS
-> Either
(VotingCommitteeError TestCrypto WFALS)
(EligibilityWitness TestCrypto WFALS)
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
VotingCommittee crypto committee
-> Vote crypto committee
-> Either
(VotingCommitteeError crypto committee)
(EligibilityWitness crypto committee)
verifyVote VotingCommittee TestCrypto WFALS
committee Vote TestCrypto WFALS
fakeVote of
Left VotingCommitteeError TestCrypto WFALS
_ ->
Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True
Right EligibilityWitness TestCrypto WFALS
_ ->
String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
( [String] -> String
unlines
[ String
"vote verification succeeded but should have failed:"
, String
"fake witness type: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> FakeEligibilityWitnessType -> String
forall a. Show a => a -> String
show FakeEligibilityWitnessType
fakeWitnessType
]
)
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
prop_forgeCert_verifyCert :: Property
prop_forgeCert_verifyCert :: Property
prop_forgeCert_verifyCert =
Gen
(Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake))
-> (Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Int
-> Gen
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF))
-> Gen
(Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake))
forall privateKey publicKey.
Int
-> Gen (privateKey, publicKey)
-> Gen (Map PoolId (privateKey, publicKey, LedgerStake))
genPools Int
1000 Gen
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF))
Gen (PrivateKey TestCrypto, PublicKey TestCrypto)
TestCrypto.genKeyPair) ((Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property)
-> (Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property)
-> Property
forall a b. (a -> b) -> a -> b
$ \Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools ->
Gen TargetCommitteeSize
-> (TargetCommitteeSize -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll (Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
-> Gen TargetCommitteeSize
genTargetCommitteeSize Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools) ((TargetCommitteeSize -> Property) -> Property)
-> (TargetCommitteeSize -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \TargetCommitteeSize
targetCommitteeSize ->
Gen Nonce -> (Nonce -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Nonce
genEpochNonce ((Nonce -> Property) -> Property)
-> (Nonce -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Nonce
epochNonce ->
Gen Word64 -> (Word64 -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen Word64
Gen (ElectionId TestCrypto)
TestCrypto.genElectionId ((Word64 -> Property) -> Property)
-> (Word64 -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Word64
electionId ->
Gen ByteString -> (ByteString -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll Gen ByteString
Gen (VoteCandidate TestCrypto)
TestCrypto.genVoteCandidate ((ByteString -> Property) -> Property)
-> (ByteString -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \ByteString
candidate -> do
let extWFAStakeDistr :: ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
extWFAStakeDistr =
WFATiebreaker
-> Map PoolId (LedgerStake, (PublicKey SIGN, PublicKey VRF))
-> Either
WFAError (ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
forall a.
WFATiebreaker
-> Map PoolId (LedgerStake, a)
-> Either WFAError (ExtWFAStakeDistr a)
mkExtWFAStakeDistr
WFATiebreaker
unfairWFATiebreaker
((((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> (LedgerStake, (PublicKey SIGN, PublicKey VRF)))
-> Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Map PoolId (LedgerStake, (PublicKey SIGN, PublicKey VRF))
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map (\((PrivateKey SIGN, PrivateKey VRF)
_, (PublicKey SIGN, PublicKey VRF)
pubKey, LedgerStake
stake) -> (LedgerStake
stake, (PublicKey SIGN, PublicKey VRF)
pubKey)) Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools)
Either WFAError (ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
-> (WFAError -> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF))
-> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
forall err a. Either err a -> (err -> a) -> a
`onError` \WFAError
err ->
String -> ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
forall a. HasCallStack => String -> a
error (String
"mkExtWFAStakeDistr failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> WFAError -> String
forall a. Show a => a -> String
show WFAError
err)
let committee :: VotingCommittee TestCrypto WFALS
committee =
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
VotingCommitteeInput crypto committee
-> Either
(VotingCommitteeError crypto committee)
(VotingCommittee crypto committee)
mkVotingCommittee @TestCrypto @WFALS
( Nonce
-> TargetCommitteeSize
-> ExtWFAStakeDistr (PublicKey TestCrypto)
-> VotingCommitteeInput TestCrypto WFALS
forall crypto.
Nonce
-> TargetCommitteeSize
-> ExtWFAStakeDistr (PublicKey crypto)
-> VotingCommitteeInput crypto WFALS
WFALSVotingCommitteeInput
Nonce
epochNonce
TargetCommitteeSize
targetCommitteeSize
ExtWFAStakeDistr (PublicKey SIGN, PublicKey VRF)
ExtWFAStakeDistr (PublicKey TestCrypto)
extWFAStakeDistr
)
Either
(VotingCommitteeError TestCrypto WFALS)
(VotingCommittee TestCrypto WFALS)
-> (VotingCommitteeError TestCrypto WFALS
-> VotingCommittee TestCrypto WFALS)
-> VotingCommittee TestCrypto WFALS
forall err a. Either err a -> (err -> a) -> a
`onError` \VotingCommitteeError TestCrypto WFALS
err ->
String -> VotingCommittee TestCrypto WFALS
forall a. HasCallStack => String -> a
error (String
"mkVotingCommittee failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VotingCommitteeError TestCrypto WFALS -> String
forall a. Show a => a -> String
show VotingCommitteeError TestCrypto WFALS
err)
let ([Vote TestCrypto WFALS]
votes, [EligibilityWitness TestCrypto WFALS]
originalWitnesses) =
[(Vote TestCrypto WFALS, EligibilityWitness TestCrypto WFALS)]
-> ([Vote TestCrypto WFALS], [EligibilityWitness TestCrypto WFALS])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(Vote TestCrypto WFALS, EligibilityWitness TestCrypto WFALS)]
-> ([Vote TestCrypto WFALS],
[EligibilityWitness TestCrypto WFALS]))
-> [(Vote TestCrypto WFALS, EligibilityWitness TestCrypto WFALS)]
-> ([Vote TestCrypto WFALS], [EligibilityWitness TestCrypto WFALS])
forall a b. (a -> b) -> a -> b
$
[ ( EligibilityWitness TestCrypto WFALS
-> PrivateKey TestCrypto
-> ElectionId TestCrypto
-> VoteCandidate TestCrypto
-> Vote TestCrypto WFALS
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
EligibilityWitness crypto committee
-> PrivateKey crypto
-> ElectionId crypto
-> VoteCandidate crypto
-> Vote crypto committee
forgeVote EligibilityWitness TestCrypto WFALS
witness (PrivateKey SIGN, PrivateKey VRF)
PrivateKey TestCrypto
privateKey Word64
ElectionId TestCrypto
electionId ByteString
VoteCandidate TestCrypto
candidate
, EligibilityWitness TestCrypto WFALS
witness
)
| (PoolId
poolId, ((PrivateKey SIGN, PrivateKey VRF)
privateKey, (PublicKey SIGN, PublicKey VRF)
_, LedgerStake
_)) <- Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> [(PoolId,
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake))]
forall k a. Map k a -> [(k, a)]
Map.toList Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools
, Just EligibilityWitness TestCrypto WFALS
witness <-
[ VotingCommittee TestCrypto WFALS
-> PoolId
-> PrivateKey TestCrypto
-> ElectionId TestCrypto
-> Either
(VotingCommitteeError TestCrypto WFALS)
(Maybe (EligibilityWitness TestCrypto WFALS))
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
VotingCommittee crypto committee
-> PoolId
-> PrivateKey crypto
-> ElectionId crypto
-> Either
(VotingCommitteeError crypto committee)
(Maybe (EligibilityWitness crypto committee))
checkShouldVote
VotingCommittee TestCrypto WFALS
committee
PoolId
poolId
(PrivateKey SIGN, PrivateKey VRF)
PrivateKey TestCrypto
privateKey
Word64
ElectionId TestCrypto
electionId
Either
(VotingCommitteeError TestCrypto WFALS)
(Maybe (EligibilityWitness TestCrypto WFALS))
-> (VotingCommitteeError TestCrypto WFALS
-> Maybe (EligibilityWitness TestCrypto WFALS))
-> Maybe (EligibilityWitness TestCrypto WFALS)
forall err a. Either err a -> (err -> a) -> a
`onError` \VotingCommitteeError TestCrypto WFALS
err ->
String -> Maybe (EligibilityWitness TestCrypto WFALS)
forall a. HasCallStack => String -> a
error (String
"checkShouldVote failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VotingCommitteeError TestCrypto WFALS -> String
forall a. Show a => a -> String
show VotingCommitteeError TestCrypto WFALS
err)
]
]
Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Property -> Property
forall privateKey publicKey.
Map PoolId (privateKey, publicKey, LedgerStake)
-> Property -> Property
tabulateNumPools Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
pools
(Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Property -> Property
tabulateNumVotes ([Vote TestCrypto WFALS] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Vote TestCrypto WFALS]
votes)
(Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TargetCommitteeSize -> Property -> Property
tabulateTargetCommitteeSize TargetCommitteeSize
targetCommitteeSize
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ case [Vote TestCrypto WFALS]
votes of
[] ->
Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True
Vote TestCrypto WFALS
firstVote : [Vote TestCrypto WFALS]
nextVotes -> do
let uniqueVotesWithSameTarget :: UniqueVotesWithSameTarget TestCrypto WFALS
uniqueVotesWithSameTarget =
(Vote TestCrypto WFALS
-> (ElectionId TestCrypto, VoteCandidate TestCrypto))
-> (Vote TestCrypto WFALS -> Vote TestCrypto WFALS -> Ordering)
-> NE [Vote TestCrypto WFALS]
-> Either
(UniqueVotesWithSameTargetError (Vote TestCrypto WFALS))
(UniqueVotesWithSameTarget TestCrypto WFALS)
forall crypto committee.
(Eq (ElectionId crypto), Eq (VoteCandidate crypto)) =>
(Vote crypto committee
-> (ElectionId crypto, VoteCandidate crypto))
-> (Vote crypto committee -> Vote crypto committee -> Ordering)
-> NE [Vote crypto committee]
-> Either
(UniqueVotesWithSameTargetError (Vote crypto committee))
(UniqueVotesWithSameTarget crypto committee)
ensureUniqueVotesWithSameTarget
( \case
WFALSPersistentVote SeatIndex
_ ElectionId TestCrypto
eid VoteCandidate TestCrypto
cand VoteSignature TestCrypto
_ -> (ElectionId TestCrypto
eid, VoteCandidate TestCrypto
cand)
WFALSNonPersistentVote SeatIndex
_ ElectionId TestCrypto
eid VoteCandidate TestCrypto
cand VRFOutput TestCrypto
_ VoteSignature TestCrypto
_ -> (ElectionId TestCrypto
eid, VoteCandidate TestCrypto
cand)
)
( SeatIndex -> SeatIndex -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (SeatIndex -> SeatIndex -> Ordering)
-> (Vote TestCrypto WFALS -> SeatIndex)
-> Vote TestCrypto WFALS
-> Vote TestCrypto WFALS
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` \case
WFALSPersistentVote SeatIndex
seatIndex ElectionId TestCrypto
_ VoteCandidate TestCrypto
_ VoteSignature TestCrypto
_ -> SeatIndex
seatIndex
WFALSNonPersistentVote SeatIndex
seatIndex ElectionId TestCrypto
_ VoteCandidate TestCrypto
_ VRFOutput TestCrypto
_ VoteSignature TestCrypto
_ -> SeatIndex
seatIndex
)
(Vote TestCrypto WFALS
firstVote Vote TestCrypto WFALS
-> [Vote TestCrypto WFALS] -> NonEmpty (Vote TestCrypto WFALS)
forall a. a -> [a] -> NonEmpty a
:| [Vote TestCrypto WFALS]
nextVotes)
Either
(UniqueVotesWithSameTargetError (Vote TestCrypto WFALS))
(UniqueVotesWithSameTarget TestCrypto WFALS)
-> (UniqueVotesWithSameTargetError (Vote TestCrypto WFALS)
-> UniqueVotesWithSameTarget TestCrypto WFALS)
-> UniqueVotesWithSameTarget TestCrypto WFALS
forall err a. Either err a -> (err -> a) -> a
`onError` \UniqueVotesWithSameTargetError (Vote TestCrypto WFALS)
_ ->
String -> UniqueVotesWithSameTarget TestCrypto WFALS
forall a. HasCallStack => String -> a
error String
"votes don't have the same target!"
let cert :: Cert TestCrypto WFALS
cert =
UniqueVotesWithSameTarget TestCrypto WFALS
-> Either
(VotingCommitteeError TestCrypto WFALS) (Cert TestCrypto WFALS)
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
UniqueVotesWithSameTarget crypto committee
-> Either
(VotingCommitteeError crypto committee) (Cert crypto committee)
forgeCert UniqueVotesWithSameTarget TestCrypto WFALS
uniqueVotesWithSameTarget
Either
(VotingCommitteeError TestCrypto WFALS) (Cert TestCrypto WFALS)
-> (VotingCommitteeError TestCrypto WFALS -> Cert TestCrypto WFALS)
-> Cert TestCrypto WFALS
forall err a. Either err a -> (err -> a) -> a
`onError` \VotingCommitteeError TestCrypto WFALS
err ->
String -> Cert TestCrypto WFALS
forall a. HasCallStack => String -> a
error (String
"forgeCert failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VotingCommitteeError TestCrypto WFALS -> String
forall a. Show a => a -> String
show VotingCommitteeError TestCrypto WFALS
err)
case VotingCommittee TestCrypto WFALS
-> Cert TestCrypto WFALS
-> Either
(VotingCommitteeError TestCrypto WFALS)
(NE [EligibilityWitness TestCrypto WFALS])
forall crypto committee.
CryptoSupportsVotingCommittee crypto committee =>
VotingCommittee crypto committee
-> Cert crypto committee
-> Either
(VotingCommitteeError crypto committee)
(NE [EligibilityWitness crypto committee])
verifyCert VotingCommittee TestCrypto WFALS
committee Cert TestCrypto WFALS
cert of
Left VotingCommitteeError TestCrypto WFALS
err ->
String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
(String
"certificate verification failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VotingCommitteeError TestCrypto WFALS -> String
forall a. Show a => a -> String
show VotingCommitteeError TestCrypto WFALS
err)
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
False
Right NE [EligibilityWitness TestCrypto WFALS]
witnesses -> do
let witnessesFromCert :: [EligibilityWitness TestCrypto WFALS]
witnessesFromCert = NonEmpty (EligibilityWitness TestCrypto WFALS)
-> [EligibilityWitness TestCrypto WFALS]
forall a. NonEmpty a -> [a]
NonEmpty.toList NonEmpty (EligibilityWitness TestCrypto WFALS)
NE [EligibilityWitness TestCrypto WFALS]
witnesses
String -> Bool -> Property
forall prop. Testable prop => String -> prop -> Property
counterexample
( [String] -> String
unlines
[ String
"witnesses mismatch!"
, String
"expected these " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([EligibilityWitness TestCrypto WFALS] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [EligibilityWitness TestCrypto WFALS]
originalWitnesses) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" witnesses:"
, String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" ((EligibilityWitness TestCrypto WFALS -> String)
-> [EligibilityWitness TestCrypto WFALS] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap EligibilityWitness TestCrypto WFALS -> String
showWitness [EligibilityWitness TestCrypto WFALS]
originalWitnesses)
, String
"but got these " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([EligibilityWitness TestCrypto WFALS] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [EligibilityWitness TestCrypto WFALS]
witnessesFromCert) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" witnesses:"
, String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" ((EligibilityWitness TestCrypto WFALS -> String)
-> [EligibilityWitness TestCrypto WFALS] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap EligibilityWitness TestCrypto WFALS -> String
showWitness [EligibilityWitness TestCrypto WFALS]
witnessesFromCert)
]
)
(Bool -> Property) -> Bool -> Property
forall a b. (a -> b) -> a -> b
$ [EligibilityWitness TestCrypto WFALS]
-> [EligibilityWitness TestCrypto WFALS] -> Bool
cmpWitnesses [EligibilityWitness TestCrypto WFALS]
originalWitnesses [EligibilityWitness TestCrypto WFALS]
witnessesFromCert
samplePool ::
Map PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake) ->
Gen (PoolId, PrivateKey TestCrypto, LedgerStake)
samplePool :: Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
-> Gen (PoolId, PrivateKey TestCrypto, LedgerStake)
samplePool Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools =
[(PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)]
-> Gen (PoolId, (PrivateKey SIGN, PrivateKey VRF), LedgerStake)
forall a. HasCallStack => [a] -> Gen a
elements
[ (PoolId
poolId, (PrivateKey SIGN, PrivateKey VRF)
privateKey, LedgerStake
ledgerStake)
| (PoolId
poolId, ((PrivateKey SIGN, PrivateKey VRF)
privateKey, (PublicKey SIGN, PublicKey VRF)
_, LedgerStake
ledgerStake)) <- Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> [(PoolId,
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake))]
forall k a. Map k a -> [(k, a)]
Map.toList Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools
]
genTargetCommitteeSize ::
Map PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake) ->
Gen TargetCommitteeSize
genTargetCommitteeSize :: Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
-> Gen TargetCommitteeSize
genTargetCommitteeSize Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools = do
let hasPositiveStake :: (a, b, LedgerStake) -> Bool
hasPositiveStake (a
_, b
_, LedgerStake Rational
stake) =
Rational
stake Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> Rational
0
let poolsWithPositiveStake :: Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
poolsWithPositiveStake =
(((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Bool)
-> Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
forall a k. (a -> Bool) -> Map k a -> Map k a
Map.filter ((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Bool
forall {a} {b}. (a, b, LedgerStake) -> Bool
hasPositiveStake Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
Map
PoolId (PrivateKey TestCrypto, PublicKey TestCrypto, LedgerStake)
pools
numPools <-
(Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
-> Int
forall k a. Map k a -> Int
Map.size Map
PoolId
((PrivateKey SIGN, PrivateKey VRF),
(PublicKey SIGN, PublicKey VRF), LedgerStake)
poolsWithPositiveStake)
pure $ TargetCommitteeSize (fromIntegral numPools)
data FakeEligibilityWitnessType
= NotAPersistentMember
| NotANonPersistentMember
| NonPersistentMemberWithZeroSeats
deriving Int -> FakeEligibilityWitnessType -> String -> String
[FakeEligibilityWitnessType] -> String -> String
FakeEligibilityWitnessType -> String
(Int -> FakeEligibilityWitnessType -> String -> String)
-> (FakeEligibilityWitnessType -> String)
-> ([FakeEligibilityWitnessType] -> String -> String)
-> Show FakeEligibilityWitnessType
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> FakeEligibilityWitnessType -> String -> String
showsPrec :: Int -> FakeEligibilityWitnessType -> String -> String
$cshow :: FakeEligibilityWitnessType -> String
show :: FakeEligibilityWitnessType -> String
$cshowList :: [FakeEligibilityWitnessType] -> String -> String
showList :: [FakeEligibilityWitnessType] -> String -> String
Show
genFakeEligibilityWitness ::
VotingCommittee TestCrypto WFALS ->
PrivateKey TestCrypto ->
LedgerStake ->
Nonce ->
ElectionId TestCrypto ->
Gen (FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
genFakeEligibilityWitness :: VotingCommittee TestCrypto WFALS
-> PrivateKey TestCrypto
-> LedgerStake
-> Nonce
-> ElectionId TestCrypto
-> Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
genFakeEligibilityWitness
VotingCommittee TestCrypto WFALS
committee
PrivateKey TestCrypto
poolPrivateKey
LedgerStake
poolStake
Nonce
epochNonce
ElectionId TestCrypto
electionId = do
[(Int,
Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS))]
-> Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
forall a. HasCallStack => [(Int, Gen a)] -> Gen a
frequency
[
( if Word64
numNonPersistentSeats Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
0 then Int
1 else Int
0
, Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
genFakePersistentMemberWitness
)
,
( if Word64
numPersistentSeats Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
0 then Int
1 else Int
0
, Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
genFakeNonPersistentMemberWitness
)
]
where
numPersistentSeats :: Word64
numPersistentSeats =
PersistentCommitteeSize -> Word64
unPersistentCommitteeSize (VotingCommittee TestCrypto WFALS -> PersistentCommitteeSize
forall crypto.
VotingCommittee crypto WFALS -> PersistentCommitteeSize
persistentCommitteeSize VotingCommittee TestCrypto WFALS
committee)
numNonPersistentSeats :: Word64
numNonPersistentSeats =
NonPersistentCommitteeSize -> Word64
unNonPersistentCommitteeSize (VotingCommittee TestCrypto WFALS -> NonPersistentCommitteeSize
forall crypto.
VotingCommittee crypto WFALS -> NonPersistentCommitteeSize
nonPersistentCommitteeSize VotingCommittee TestCrypto WFALS
committee)
persistentRange :: (Word64, Word64)
persistentRange =
(Word64
0, Word64
numPersistentSeats Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1)
nonPersistentRange :: (Word64, Word64)
nonPersistentRange =
(Word64
numPersistentSeats, Word64
numPersistentSeats Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
numNonPersistentSeats Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1)
genFakePersistentMemberWitness :: Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
genFakePersistentMemberWitness = do
seatIndex <- Word64 -> SeatIndex
SeatIndex (Word64 -> SeatIndex) -> Gen Word64 -> Gen SeatIndex
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word64, Word64) -> Gen Word64
forall a. Random a => (a, a) -> Gen a
choose (Word64, Word64)
nonPersistentRange
pure
( NotAPersistentMember
, WFALSPersistentMember
seatIndex
poolStake
)
genFakeNonPersistentMemberWitness :: Gen
(FakeEligibilityWitnessType, EligibilityWitness TestCrypto WFALS)
genFakeNonPersistentMemberWitness = do
let vrfOutput :: VRFOutput TestCrypto
vrfOutput =
forall crypto.
CryptoSupportsVRF crypto =>
VRFPoolContext crypto
-> VRFElectionInput crypto -> Either String (VRFOutput crypto)
evalVRF @TestCrypto
(VRFSigningKey TestCrypto -> VRFPoolContext TestCrypto
forall crypto. VRFSigningKey crypto -> VRFPoolContext crypto
VRFSignContext (Proxy TestCrypto
-> PrivateKey TestCrypto -> VRFSigningKey TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Proxy crypto -> PrivateKey crypto -> VRFSigningKey crypto
getVRFSigningKey (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @TestCrypto) PrivateKey TestCrypto
poolPrivateKey))
(Nonce -> ElectionId TestCrypto -> VRFElectionInput TestCrypto
forall crypto.
CryptoSupportsVRF crypto =>
Nonce -> ElectionId crypto -> VRFElectionInput crypto
mkVRFElectionInput Nonce
epochNonce ElectionId TestCrypto
electionId)
Either String (VRFOutput TestCrypto)
-> (String -> VRFOutput TestCrypto) -> VRFOutput TestCrypto
forall err a. Either err a -> (err -> a) -> a
`onError` \String
err ->
String -> VRFOutput TestCrypto
forall a. HasCallStack => String -> a
error (String
"evalVRF failed: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
forall a. Show a => a -> String
show String
err)
let numSeats :: LocalSortitionNumSeats
numSeats =
NonPersistentCommitteeSize
-> TotalNonPersistentStake
-> LedgerStake
-> NormalizedVRFOutput
-> LocalSortitionNumSeats
LS.localSortitionNumSeats
(VotingCommittee TestCrypto WFALS -> NonPersistentCommitteeSize
forall crypto.
VotingCommittee crypto WFALS -> NonPersistentCommitteeSize
nonPersistentCommitteeSize VotingCommittee TestCrypto WFALS
committee)
(VotingCommittee TestCrypto WFALS -> TotalNonPersistentStake
forall crypto.
VotingCommittee crypto WFALS -> TotalNonPersistentStake
totalNonPersistentStake VotingCommittee TestCrypto WFALS
committee)
LedgerStake
poolStake
(VRFOutput TestCrypto -> NormalizedVRFOutput
forall crypto.
CryptoSupportsVRF crypto =>
VRFOutput crypto -> NormalizedVRFOutput
normalizeVRFOutput VRFOutput TestCrypto
vrfOutput)
case LocalSortitionNumSeats -> Maybe (NonZero LocalSortitionNumSeats)
forall a. HasZero a => a -> Maybe (NonZero a)
nonZero LocalSortitionNumSeats
numSeats of
Just NonZero LocalSortitionNumSeats
nonZeroNumSeats -> do
seatIndex <- Word64 -> SeatIndex
SeatIndex (Word64 -> SeatIndex) -> Gen Word64 -> Gen SeatIndex
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word64, Word64) -> Gen Word64
forall a. Random a => (a, a) -> Gen a
choose (Word64, Word64)
persistentRange
pure
( NotANonPersistentMember
, WFALSNonPersistentMember
seatIndex
poolStake
vrfOutput
nonZeroNumSeats
)
Maybe (NonZero LocalSortitionNumSeats)
Nothing -> do
seatIndex <- Word64 -> SeatIndex
SeatIndex (Word64 -> SeatIndex) -> Gen Word64 -> Gen SeatIndex
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word64, Word64) -> Gen Word64
forall a. Random a => (a, a) -> Gen a
choose (Word64, Word64)
nonPersistentRange
pure
( NonPersistentMemberWithZeroSeats
, WFALSNonPersistentMember
seatIndex
poolStake
vrfOutput
(unsafeNonZero numSeats)
)
showWitness ::
EligibilityWitness TestCrypto WFALS ->
String
showWitness :: EligibilityWitness TestCrypto WFALS -> String
showWitness EligibilityWitness TestCrypto WFALS
witness =
case EligibilityWitness TestCrypto WFALS
witness of
WFALSPersistentMember SeatIndex
seatIndex LedgerStake
_ ->
String
"PersistentMember(SeatIndex=" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> SeatIndex -> String
forall a. Show a => a -> String
show SeatIndex
seatIndex String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
WFALSNonPersistentMember SeatIndex
seatIndex LedgerStake
_ VRFOutput TestCrypto
vrfOutput NonZero LocalSortitionNumSeats
numSeats ->
String
"NonPersistentMember(SeatIndex="
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> SeatIndex -> String
forall a. Show a => a -> String
show SeatIndex
seatIndex
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
", VRFOutput="
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> VRFOutput TestCrypto -> String
forall a. Show a => a -> String
show VRFOutput TestCrypto
vrfOutput
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
", NumSeats="
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Word64 -> String
forall a. Show a => a -> String
show (LocalSortitionNumSeats -> Word64
unLocalSortitionNumSeats (NonZero LocalSortitionNumSeats -> LocalSortitionNumSeats
forall a. NonZero a -> a
unNonZero NonZero LocalSortitionNumSeats
numSeats))
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
cmpWitness ::
EligibilityWitness TestCrypto WFALS ->
EligibilityWitness TestCrypto WFALS ->
Bool
cmpWitness :: EligibilityWitness TestCrypto WFALS
-> EligibilityWitness TestCrypto WFALS -> Bool
cmpWitness EligibilityWitness TestCrypto WFALS
w1 EligibilityWitness TestCrypto WFALS
w2 =
case (EligibilityWitness TestCrypto WFALS
w1, EligibilityWitness TestCrypto WFALS
w2) of
( WFALSPersistentMember SeatIndex
seatIndex1 LedgerStake
_
, WFALSPersistentMember SeatIndex
seatIndex2 LedgerStake
_
) ->
SeatIndex
seatIndex1 SeatIndex -> SeatIndex -> Bool
forall a. Eq a => a -> a -> Bool
== SeatIndex
seatIndex2
( WFALSNonPersistentMember SeatIndex
seatIndex1 LedgerStake
_ VRFOutput TestCrypto
vrfOutput1 NonZero LocalSortitionNumSeats
numSeats1
, WFALSNonPersistentMember SeatIndex
seatIndex2 LedgerStake
_ VRFOutput TestCrypto
vrfOutput2 NonZero LocalSortitionNumSeats
numSeats2
) ->
SeatIndex
seatIndex1 SeatIndex -> SeatIndex -> Bool
forall a. Eq a => a -> a -> Bool
== SeatIndex
seatIndex2
Bool -> Bool -> Bool
&& VRFOutput TestCrypto
vrfOutput1 VRFOutput TestCrypto -> VRFOutput TestCrypto -> Bool
forall a. Eq a => a -> a -> Bool
== VRFOutput TestCrypto
vrfOutput2
Bool -> Bool -> Bool
&& NonZero LocalSortitionNumSeats
numSeats1 NonZero LocalSortitionNumSeats
-> NonZero LocalSortitionNumSeats -> Bool
forall a. Eq a => a -> a -> Bool
== NonZero LocalSortitionNumSeats
numSeats2
(EligibilityWitness TestCrypto WFALS,
EligibilityWitness TestCrypto WFALS)
_ ->
Bool
False
cmpWitnesses ::
[EligibilityWitness TestCrypto WFALS] ->
[EligibilityWitness TestCrypto WFALS] ->
Bool
cmpWitnesses :: [EligibilityWitness TestCrypto WFALS]
-> [EligibilityWitness TestCrypto WFALS] -> Bool
cmpWitnesses [EligibilityWitness TestCrypto WFALS]
ws1 [EligibilityWitness TestCrypto WFALS]
ws2 =
[EligibilityWitness TestCrypto WFALS] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [EligibilityWitness TestCrypto WFALS]
ws1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [EligibilityWitness TestCrypto WFALS] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [EligibilityWitness TestCrypto WFALS]
ws2
Bool -> Bool -> Bool
&& ((EligibilityWitness TestCrypto WFALS,
EligibilityWitness TestCrypto WFALS)
-> Bool)
-> [(EligibilityWitness TestCrypto WFALS,
EligibilityWitness TestCrypto WFALS)]
-> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all
((EligibilityWitness TestCrypto WFALS
-> EligibilityWitness TestCrypto WFALS -> Bool)
-> (EligibilityWitness TestCrypto WFALS,
EligibilityWitness TestCrypto WFALS)
-> Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry EligibilityWitness TestCrypto WFALS
-> EligibilityWitness TestCrypto WFALS -> Bool
cmpWitness)
([EligibilityWitness TestCrypto WFALS]
-> [EligibilityWitness TestCrypto WFALS]
-> [(EligibilityWitness TestCrypto WFALS,
EligibilityWitness TestCrypto WFALS)]
forall a b. [a] -> [b] -> [(a, b)]
zip ([EligibilityWitness TestCrypto WFALS]
-> [EligibilityWitness TestCrypto WFALS]
forall {crypto}.
[EligibilityWitness crypto WFALS]
-> [EligibilityWitness crypto WFALS]
sortBySeatIndex [EligibilityWitness TestCrypto WFALS]
ws1) ([EligibilityWitness TestCrypto WFALS]
-> [EligibilityWitness TestCrypto WFALS]
forall {crypto}.
[EligibilityWitness crypto WFALS]
-> [EligibilityWitness crypto WFALS]
sortBySeatIndex [EligibilityWitness TestCrypto WFALS]
ws2))
where
sortBySeatIndex :: [EligibilityWitness crypto WFALS]
-> [EligibilityWitness crypto WFALS]
sortBySeatIndex =
(EligibilityWitness crypto WFALS -> SeatIndex)
-> [EligibilityWitness crypto WFALS]
-> [EligibilityWitness crypto WFALS]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn ((EligibilityWitness crypto WFALS -> SeatIndex)
-> [EligibilityWitness crypto WFALS]
-> [EligibilityWitness crypto WFALS])
-> (EligibilityWitness crypto WFALS -> SeatIndex)
-> [EligibilityWitness crypto WFALS]
-> [EligibilityWitness crypto WFALS]
forall a b. (a -> b) -> a -> b
$ \case
WFALSPersistentMember SeatIndex
seatIndex LedgerStake
_ -> SeatIndex
seatIndex
WFALSNonPersistentMember SeatIndex
seatIndex LedgerStake
_ VRFOutput crypto
_ NonZero LocalSortitionNumSeats
_ -> SeatIndex
seatIndex
tabulateTargetCommitteeSize ::
TargetCommitteeSize ->
Property ->
Property
tabulateTargetCommitteeSize :: TargetCommitteeSize -> Property -> Property
tabulateTargetCommitteeSize (TargetCommitteeSize Word64
size) =
String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate
String
"Target committee size"
[Integer -> Integer -> String
mkBucket Integer
100 (Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
size)]
tabulateShouldVote ::
Maybe (EligibilityWitness TestCrypto WFALS) ->
Property ->
Property
tabulateShouldVote :: Maybe (EligibilityWitness TestCrypto WFALS) -> Property -> Property
tabulateShouldVote Maybe (EligibilityWitness TestCrypto WFALS)
shouldVote =
String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate
String
"Should vote"
[ case Maybe (EligibilityWitness TestCrypto WFALS)
shouldVote of
Maybe (EligibilityWitness TestCrypto WFALS)
Nothing ->
String
"NoVote"
Just (WFALSPersistentMember SeatIndex
_ LedgerStake
_) ->
String
"PersistentVote"
Just (WFALSNonPersistentMember SeatIndex
_ LedgerStake
_ VRFOutput TestCrypto
_ NonZero LocalSortitionNumSeats
numSeats) ->
String
"NonPersistentVote(NumSeats="
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Word64 -> String
forall a. Show a => a -> String
show (LocalSortitionNumSeats -> Word64
unLocalSortitionNumSeats (NonZero LocalSortitionNumSeats -> LocalSortitionNumSeats
forall a. NonZero a -> a
unNonZero NonZero LocalSortitionNumSeats
numSeats))
String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
]
tabulateFakePersistentWitnessType ::
FakeEligibilityWitnessType ->
Property ->
Property
tabulateFakePersistentWitnessType :: FakeEligibilityWitnessType -> Property -> Property
tabulateFakePersistentWitnessType FakeEligibilityWitnessType
fakeWitnessType =
String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate
String
"Fake witness type"
[FakeEligibilityWitnessType -> String
forall a. Show a => a -> String
show FakeEligibilityWitnessType
fakeWitnessType]
tabulateNumVotes ::
Int ->
Property ->
Property
tabulateNumVotes :: Int -> Property -> Property
tabulateNumVotes Int
numVotes =
String -> [String] -> Property -> Property
forall prop.
Testable prop =>
String -> [String] -> prop -> Property
tabulate
String
"Number of votes"
[Integer -> Integer -> String
mkBucket Integer
100 (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
numVotes)]