diff --git a/agora/Agora/Governor/Scripts.hs b/agora/Agora/Governor/Scripts.hs index dacef86..c484ccf 100644 --- a/agora/Agora/Governor/Scripts.hs +++ b/agora/Agora/Governor/Scripts.hs @@ -53,6 +53,7 @@ import Agora.Proposal ( ProposalStatus (Draft, Locked), pemptyVotesFor, proposalDatumValid, + pwinner, ) import Agora.Proposal.Scripts ( proposalPolicy, @@ -77,7 +78,6 @@ import Agora.Utils ( mustFindDatum', pfindTxInByTxOutRef, pisDJust, - pisJust, pisUTXOSpent, psymbolValueOf, ptryFindDatum, @@ -605,27 +605,7 @@ governorValidator gov = -- TODO: anything else to check here? -- Find the highest votes and the corresponding tag. - let highestVoteFolder = - phoistAcyclic $ - plam - ( \pair last' -> - pif - (pisJust # last') - ( unTermCont $ do - PJust last <- tcmatch last' - let lastHighestVote = pfromData $ psndBuiltin # last - thisVote = pfromData $ psndBuiltin # pair - pure $ pif (lastHighestVote #< thisVote) (pcon $ PJust pair) last' - ) - (pcon $ PJust pair) - ) - - votesList = pto $ pto $ pfromData proposalInputDatumF.votes - - maybeWinner = - pfoldr # highestVoteFolder # pcon PNothing # votesList - - winner <- tclet $ mustBePJust # "No winning outcome" # maybeWinner + winner <- tclet $ mustBePJust # "No winning outcome" #$ pwinner # proposalInputDatumF.votes PDiscrete minimumVotes' <- pmatchC $ pfromData $ pfield @"execute" # proposalInputDatumF.thresholds let highestVote = pfromData $ psndBuiltin # winner diff --git a/agora/Agora/Proposal.hs b/agora/Agora/Proposal.hs index e79e360..ba17a25 100644 --- a/agora/Agora/Proposal.hs +++ b/agora/Agora/Proposal.hs @@ -31,6 +31,7 @@ module Agora.Proposal ( -- * Plutarch helpers proposalDatumValid, pemptyVotesFor, + pwinner, ) where import GHC.Generics qualified as GHC @@ -448,3 +449,37 @@ proposalDatumValid proposal = , ptraceIfFalse "Proposal has fewer cosigners than the limit" $ plength # (pfromData datum.cosigners) #<= pconstant proposal.maximumCosigners , ptraceIfFalse "Proposal votes and effects are compatible with each other" $ pkeysEqual # datum.effects # pto (pfromData datum.votes) ] + +{- | Find the winning outcome (and the corresponding vote count) given the votes. + + FIXME: What if two or more outcomes have the exact same vote count? +-} +pwinner :: + Term + s + ( PProposalVotes + :--> PMaybe (PBuiltinPair (PAsData PResultTag) (PAsData PInteger)) + ) +pwinner = phoistAcyclic $ + plam $ \votes -> + let l :: Term _ (PBuiltinList _) + l = pto $ pto votes + + f :: + Term + _ + ( PBuiltinPair (PAsData PResultTag) (PAsData PInteger) + :--> PMaybe (PBuiltinPair (PAsData PResultTag) (PAsData PInteger)) + :--> PMaybe (PBuiltinPair (PAsData PResultTag) (PAsData PInteger)) + ) + f = phoistAcyclic $ + plam $ \this maybeLast -> pmatch maybeLast $ \case + PNothing -> pcon $ PJust this + PJust last -> + let lastVotes = pfromData $ psndBuiltin # last + thisVotes = pfromData $ psndBuiltin # this + in pif + (lastVotes #< thisVotes) + (pcon $ PJust this) + maybeLast + in pfoldr # f # pcon PNothing # l