@@ -50,6 +50,7 @@ data PerasRoundVoteState blk
5050 }
5151 | PerasRoundVoteStateQuorumReachedAlready
5252 { prvsRoundNo :: ! PerasRoundNo
53+ , prvsExcessVotes :: ! Word64
5354 , prvsLoserStates :: ! (Map (Point blk ) (PerasTargetVoteState blk 'Loser))
5455 , prvsWinnerState :: ! (PerasTargetVoteState blk 'Winner)
5556 }
@@ -64,8 +65,8 @@ prvsMaybeCert :: PerasRoundVoteState blk -> Maybe (ValidatedPerasCert blk)
6465prvsMaybeCert = \ case
6566 PerasRoundVoteStateQuorumNotReached {} ->
6667 Nothing
67- PerasRoundVoteStateQuorumReachedAlready _ _ winner ->
68- let (PerasTargetVoteWinner _ _ cert) = winner
68+ PerasRoundVoteStateQuorumReachedAlready _ _ _ winner ->
69+ let (PerasTargetVoteWinner _ cert) = winner
6970 in Just cert
7071
7172-- | Create a fresh round vote state for the given round number
@@ -138,31 +139,43 @@ updatePerasRoundVoteState vote cfg roundState = do
138139 pure $
139140 PerasRoundVoteStateQuorumReachedAlready
140141 { prvsRoundNo = prvsRoundNo roundState
142+ , prvsExcessVotes = 0
141143 , prvsLoserStates = loserStates
142144 , prvsWinnerState = winnerState
143145 }
144146
145147 -- Quorum already reached
146148 state@ PerasRoundVoteStateQuorumReachedAlready {prvsLoserStates, prvsWinnerState} -> do
147- let votePoint = getPerasVoteBlock vote
148- winnerPoint = getPerasVoteBlock prvsWinnerState
149- existingOrFreshLoserVoteState =
150- fromMaybe (freshLoserVoteState (getPerasVoteTarget vote))
151-
152- updateMaybeLoser mState =
153- updateLoserVoteState cfg vote (existingOrFreshLoserVoteState mState)
154- `onErr` \ err ->
155- RoundVoteStateLoserAboveQuorum prvsWinnerState err
149+ let votePoint =
150+ getPerasVoteBlock vote
151+ winnerPoint =
152+ getPerasVoteBlock prvsWinnerState
156153
157154 if votePoint == winnerPoint
158- then
155+ -- The vote ratifies the winner => update winner state
156+ then do
157+ let winnerState' = updateWinnerVoteState vote prvsWinnerState
159158 pure $
160- state{prvsWinnerState = updateWinnerVoteState vote prvsWinnerState}
159+ state
160+ { prvsExcessVotes = prvsExcessVotes state + 1
161+ , prvsWinnerState = winnerState'
162+ }
163+
164+ -- The vote is for a loser => update loser state
161165 else do
162- prvsLoserStates' <-
163- Map. alterF (fmap Just . updateMaybeLoser) votePoint prvsLoserStates
166+ let existingOrFreshLoserVoteState =
167+ fromMaybe (freshLoserVoteState (getPerasVoteTarget vote))
168+ updateMaybeLoserVoteState mState =
169+ fmap Just $
170+ updateLoserVoteState cfg vote (existingOrFreshLoserVoteState mState)
171+ `onErr` \ err ->
172+ RoundVoteStateLoserAboveQuorum prvsWinnerState err
173+ prvsLoserStates' <- Map. alterF updateMaybeLoserVoteState votePoint prvsLoserStates
164174 pure $
165- state{prvsLoserStates = prvsLoserStates'}
175+ state
176+ { prvsExcessVotes = prvsExcessVotes state + 1
177+ , prvsLoserStates = prvsLoserStates'
178+ }
166179
167180-- | Updates the round vote states map with the given vote.
168181--
@@ -243,9 +256,11 @@ pattern VoteDidntGenerateNewCert <-
243256voteGeneratedCert :: PerasRoundVoteState blk -> Maybe (ValidatedPerasCert blk )
244257voteGeneratedCert = \ case
245258 PerasRoundVoteStateQuorumReachedAlready
246- { prvsWinnerState = PerasTargetVoteWinner _ 0 cert
259+ { prvsExcessVotes = 0
260+ , prvsWinnerState = PerasTargetVoteWinner _ cert
247261 } -> Just cert
248- _ -> Nothing
262+ _ ->
263+ Nothing
249264
250265{- ------------------------------------------------------------------------------
251266 Peras target vote tally
@@ -340,9 +355,6 @@ data PerasTargetVoteState blk (status :: PerasTargetVoteStatus) where
340355 PerasTargetVoteState blk 'Loser
341356 PerasTargetVoteWinner ::
342357 ! (PerasTargetVoteTally blk ) ->
343- -- | Number of extra votes received since the target was elected winner and
344- -- the cert was forged.
345- ! Word64 ->
346358 ! (ValidatedPerasCert blk ) ->
347359 PerasTargetVoteState blk 'Winner
348360
@@ -380,8 +392,8 @@ instance
380392 noThunks ctx tally
381393 noThunks ctx (PerasTargetVoteLoser tally) =
382394 noThunks ctx tally
383- noThunks ctx (PerasTargetVoteWinner tally w cert) =
384- noThunks ctx (tally, w, cert)
395+ noThunks ctx (PerasTargetVoteWinner tally cert) =
396+ noThunks ctx (tally, cert)
385397
386398instance HasPerasVoteTarget (PerasTargetVoteState blk status ) blk where
387399 getPerasVoteTarget = getPerasVoteTarget . ptvsVoteTally
@@ -397,7 +409,7 @@ ptvsVoteTally :: PerasTargetVoteState blk status -> PerasTargetVoteTally blk
397409ptvsVoteTally = \ case
398410 PerasTargetVoteCandidate tally -> tally
399411 PerasTargetVoteLoser tally -> tally
400- PerasTargetVoteWinner tally _ _ -> tally
412+ PerasTargetVoteWinner tally _ -> tally
401413
402414freshCandidateVoteState :: PerasVoteTarget blk -> PerasTargetVoteState blk 'Candidate
403415freshCandidateVoteState target =
@@ -443,7 +455,7 @@ updateCandidateVoteState cfg vote oldState = do
443455 in if stakeAboveThreshold cfg (ptvtTotalStake newVoteTally)
444456 then do
445457 cert <- forgePerasCert cfg (ptvtTarget newVoteTally) voteList
446- pure $ BecameWinner (PerasTargetVoteWinner newVoteTally 0 cert)
458+ pure $ BecameWinner (PerasTargetVoteWinner newVoteTally cert)
447459 else
448460 pure $ RemainedCandidate (PerasTargetVoteCandidate newVoteTally)
449461
@@ -475,8 +487,8 @@ updateWinnerVoteState ::
475487 PerasTargetVoteState blk 'Winner
476488updateWinnerVoteState vote oldState =
477489 let newVoteTally = updateTargetVoteTally vote (ptvsVoteTally oldState)
478- (PerasTargetVoteWinner _ extraCertCount cert) = oldState
479- in PerasTargetVoteWinner newVoteTally (extraCertCount + 1 ) cert
490+ (PerasTargetVoteWinner _ cert) = oldState
491+ in PerasTargetVoteWinner newVoteTally cert
480492
481493{- ------------------------------------------------------------------------------
482494 Helpers
0 commit comments