fix governor datum validation
This commit is contained in:
parent
e22bdc59fb
commit
d709a1fdd0
7 changed files with 289 additions and 218 deletions
|
|
@ -23,7 +23,7 @@ import Agora.Governor (
|
|||
Governor,
|
||||
GovernorDatum,
|
||||
PGovernorDatum,
|
||||
governorDatumValid,
|
||||
pisGovernorDatumValid,
|
||||
)
|
||||
import Agora.Governor.Scripts (
|
||||
authorityTokenSymbolFromGovernor,
|
||||
|
|
@ -215,7 +215,7 @@ mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov)
|
|||
|
||||
-- Ensure the output governor datum is what we want.
|
||||
pguardC "Unexpected governor datum" $ datumF.newDatum #== governorOutputDatum
|
||||
pguardC "New governor datum should be valid" $ governorDatumValid # governorOutputDatum
|
||||
pguardC "New governor datum should be valid" $ pisGovernorDatumValid # governorOutputDatum
|
||||
|
||||
return $ popaque $ pconstant ()
|
||||
where
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ module Agora.Governor (
|
|||
-- * Utilities
|
||||
pgetNextProposalId,
|
||||
getNextProposalId,
|
||||
governorDatumValid,
|
||||
pisGovernorDatumValid,
|
||||
) where
|
||||
|
||||
import Agora.Proposal (
|
||||
|
|
@ -28,12 +28,15 @@ import Agora.Proposal (
|
|||
PProposalThresholds (..),
|
||||
ProposalId (ProposalId),
|
||||
ProposalThresholds,
|
||||
pisProposalThresholdsValid,
|
||||
)
|
||||
import Agora.Proposal.Time (
|
||||
MaxTimeRangeWidth,
|
||||
PMaxTimeRangeWidth,
|
||||
PProposalTimingConfig,
|
||||
ProposalTimingConfig,
|
||||
pisMaxTimeRangeWidthValid,
|
||||
pisProposalTimeingConfigValid,
|
||||
)
|
||||
import Agora.SafeMoney (GTTag)
|
||||
import Data.Tagged (Tagged (..))
|
||||
|
|
@ -44,15 +47,13 @@ import Plutarch.DataRepr (
|
|||
PDataFields,
|
||||
PIsDataReprInstances (PIsDataReprInstances),
|
||||
)
|
||||
import Plutarch.Extra.Comonad (pextract)
|
||||
import Plutarch.Extra.IsData (
|
||||
DerivePConstantViaEnum (..),
|
||||
EnumIsData (..),
|
||||
)
|
||||
import Plutarch.Extra.Other (DerivePNewtype' (..))
|
||||
import Plutarch.Extra.TermCont (pletC, pletFieldsC, pmatchC)
|
||||
import Plutarch.Extra.TermCont (pletFieldsC)
|
||||
import Plutarch.Lift (PConstantDecl, PUnsafeLiftDecl (..))
|
||||
import Plutarch.SafeMoney (PDiscrete (..))
|
||||
import PlutusLedgerApi.V1 (TxOutRef)
|
||||
import PlutusLedgerApi.V1.Value (AssetClass (..))
|
||||
import PlutusTx qualified
|
||||
|
|
@ -239,25 +240,24 @@ getNextProposalId (ProposalId pid) = ProposalId $ pid + 1
|
|||
|
||||
@since 0.1.0
|
||||
-}
|
||||
governorDatumValid :: Term s (PGovernorDatum :--> PBool)
|
||||
governorDatumValid = phoistAcyclic $
|
||||
pisGovernorDatumValid :: Term s (PGovernorDatum :--> PBool)
|
||||
pisGovernorDatumValid = phoistAcyclic $
|
||||
plam $ \datum -> unTermCont $ do
|
||||
thresholds <-
|
||||
pletFieldsC @'["execute", "create", "vote"] $
|
||||
pfield @"proposalThresholds" # datum
|
||||
|
||||
PDiscrete execute' <- pmatchC thresholds.execute
|
||||
PDiscrete draft' <- pmatchC thresholds.create
|
||||
PDiscrete vote' <- pmatchC thresholds.vote
|
||||
|
||||
execute <- pletC $ pextract # execute'
|
||||
draft <- pletC $ pextract # draft'
|
||||
vote <- pletC $ pextract # vote'
|
||||
datumF <-
|
||||
pletFieldsC
|
||||
@'[ "proposalThresholds"
|
||||
, "proposalTimings"
|
||||
, "createProposalTimeRangeMaxWidth"
|
||||
]
|
||||
datum
|
||||
|
||||
pure $
|
||||
foldr1
|
||||
(#&&)
|
||||
[ ptraceIfFalse "Execute threshold is less than or equal to" $ 0 #<= execute
|
||||
, ptraceIfFalse "Draft threshold is less than or equal to " $ 0 #<= draft
|
||||
, ptraceIfFalse "Vote threshold is less than or equal to " $ 0 #<= vote
|
||||
[ ptraceIfFalse "thersholds valid" $
|
||||
pisProposalThresholdsValid # datumF.proposalThresholds
|
||||
, ptraceIfFalse "timings valid" $
|
||||
pisProposalTimeingConfigValid # datumF.proposalTimings
|
||||
, ptraceIfFalse "time range valid" $
|
||||
pisMaxTimeRangeWidthValid # datumF.createProposalTimeRangeMaxWidth
|
||||
]
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ import Agora.Governor (
|
|||
Governor (gstOutRef, gtClassRef, maximumCosigners),
|
||||
GovernorRedeemer (..),
|
||||
PGovernorDatum (PGovernorDatum),
|
||||
governorDatumValid,
|
||||
pgetNextProposalId,
|
||||
pisGovernorDatumValid,
|
||||
)
|
||||
import Agora.Proposal (
|
||||
PProposalDatum (..),
|
||||
|
|
@ -180,7 +180,9 @@ governorPolicy gov =
|
|||
let datumHash = pfield @"datumHash" # pfromData govOutput
|
||||
datum = mustFindDatum' @PGovernorDatum # datumHash # txInfoF.datums
|
||||
|
||||
pure $ popaque $ governorDatumValid # datum
|
||||
pguardC "Governor output datum valid" $ pisGovernorDatumValid # datum
|
||||
|
||||
pure $ popaque $ pconstant ()
|
||||
|
||||
{- | Validator for Governors.
|
||||
|
||||
|
|
@ -310,7 +312,8 @@ governorValidator gov =
|
|||
pfromData $
|
||||
mustBePJust # "Ouput governor state datum not found"
|
||||
#$ ptryFindDatum # outputGovernorStateDatumHash # txInfoF.datums
|
||||
pguardC "New datum is not valid" $ governorDatumValid # newGovernorDatum
|
||||
|
||||
pguardC "New datum is valid" $ pisGovernorDatumValid # newGovernorDatum
|
||||
|
||||
pure $
|
||||
pmatchEnumFromData redeemer' $ \case
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ module Agora.Proposal (
|
|||
pwinner',
|
||||
pneutralOption,
|
||||
pretractVotes,
|
||||
pisProposalThresholdsValid,
|
||||
) where
|
||||
|
||||
import Agora.Proposal.Time (PProposalStartingTime, PProposalTimingConfig, ProposalStartingTime, ProposalTimingConfig)
|
||||
|
|
@ -53,6 +54,8 @@ import Plutarch.Api.V1 (
|
|||
)
|
||||
import Plutarch.Api.V1.AssocMap qualified as PAssocMap
|
||||
import Plutarch.DataRepr (DerivePConstantViaData (..), PDataFields, PIsDataReprInstances (..))
|
||||
import Plutarch.Extra.Comonad (pextract)
|
||||
import Plutarch.Extra.Field (pletAllC)
|
||||
import Plutarch.Extra.IsData (
|
||||
DerivePConstantViaDataList (..),
|
||||
DerivePConstantViaEnum (..),
|
||||
|
|
@ -62,13 +65,13 @@ import Plutarch.Extra.IsData (
|
|||
import Plutarch.Extra.Map qualified as PM
|
||||
import Plutarch.Extra.Map.Unsorted qualified as PUM
|
||||
import Plutarch.Extra.Other (DerivePNewtype' (..))
|
||||
import Plutarch.Extra.TermCont (pguardC, pletC)
|
||||
import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC)
|
||||
import Plutarch.Lift (
|
||||
DerivePConstantViaNewtype (..),
|
||||
PConstantDecl,
|
||||
PUnsafeLiftDecl (..),
|
||||
)
|
||||
import Plutarch.SafeMoney (PDiscrete)
|
||||
import Plutarch.SafeMoney (PDiscrete (..))
|
||||
import Plutarch.Show (PShow (..))
|
||||
import PlutusLedgerApi.V1 (DatumHash, PubKeyHash, ValidatorHash)
|
||||
import PlutusLedgerApi.V1.Value (AssetClass)
|
||||
|
|
@ -568,27 +571,6 @@ deriving via
|
|||
instance
|
||||
PTryFrom PData (PAsData PProposalVotes)
|
||||
|
||||
{- | Retract votes given the option and the amount of votes.
|
||||
|
||||
@since 0.1.0
|
||||
-}
|
||||
pretractVotes :: Term s (PResultTag :--> PInteger :--> PProposalVotes :--> PProposalVotes)
|
||||
pretractVotes = phoistAcyclic $
|
||||
plam $ \rt count votes ->
|
||||
let voteMap :: Term _ (PMap 'Unsorted PResultTag PInteger)
|
||||
voteMap = pto votes
|
||||
in pcon $
|
||||
PProposalVotes $
|
||||
PM.pupdate
|
||||
# plam
|
||||
( \oldCount -> unTermCont $ do
|
||||
newCount <- pletC $ oldCount - count
|
||||
pguardC "Resulting vote count greater or equal to 0" $ 0 #<= newCount
|
||||
pure $ pcon $ PJust newCount
|
||||
)
|
||||
# rt
|
||||
# voteMap
|
||||
|
||||
-- | @since 0.1.0
|
||||
instance PUnsafeLiftDecl PProposalVotes where type PLifted PProposalVotes = ProposalVotes
|
||||
|
||||
|
|
@ -864,3 +846,49 @@ pneutralOption = phoistAcyclic $
|
|||
el' = pto el
|
||||
in pnull # el'
|
||||
in pfromData $ pfstBuiltin #$ mustBePJust # "No neutral option" #$ pfind # f # l
|
||||
|
||||
{- | Return true if the thresholds are valid.
|
||||
|
||||
@since 0.2.0
|
||||
-}
|
||||
pisProposalThresholdsValid :: forall (s :: S). Term s (PProposalThresholds :--> PBool)
|
||||
pisProposalThresholdsValid = phoistAcyclic $
|
||||
plam $ \thresholds -> unTermCont $ do
|
||||
thresholdsF <- pletAllC thresholds
|
||||
|
||||
PDiscrete execute' <- pmatchC thresholdsF.execute
|
||||
PDiscrete draft' <- pmatchC thresholdsF.create
|
||||
PDiscrete vote' <- pmatchC thresholdsF.vote
|
||||
|
||||
execute <- pletC $ pextract # execute'
|
||||
draft <- pletC $ pextract # draft'
|
||||
vote <- pletC $ pextract # vote'
|
||||
|
||||
pure $
|
||||
foldr1
|
||||
(#&&)
|
||||
[ ptraceIfFalse "Execute threshold is less than or equal to 0" $ 0 #<= execute
|
||||
, ptraceIfFalse "Draft threshold is less than or equal to 0" $ 0 #<= draft
|
||||
, ptraceIfFalse "Vote threshold is less than or equal to 0" $ 0 #<= vote
|
||||
]
|
||||
|
||||
{- | Retract votes given the option and the amount of votes.
|
||||
|
||||
@since 0.1.0
|
||||
-}
|
||||
pretractVotes :: Term s (PResultTag :--> PInteger :--> PProposalVotes :--> PProposalVotes)
|
||||
pretractVotes = phoistAcyclic $
|
||||
plam $ \rt count votes ->
|
||||
let voteMap :: Term _ (PMap 'Unsorted PResultTag PInteger)
|
||||
voteMap = pto votes
|
||||
in pcon $
|
||||
PProposalVotes $
|
||||
PM.pupdate
|
||||
# plam
|
||||
( \oldCount -> unTermCont $ do
|
||||
newCount <- pletC $ oldCount - count
|
||||
pguardC "Resulting vote count greater or equal to 0" $ 0 #<= newCount
|
||||
pure $ pcon $ PJust newCount
|
||||
)
|
||||
# rt
|
||||
# voteMap
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ module Agora.Proposal.Time (
|
|||
isVotingPeriod,
|
||||
isLockingPeriod,
|
||||
isExecutionPeriod,
|
||||
pisProposalTimeingConfigValid,
|
||||
pisMaxTimeRangeWidthValid,
|
||||
) where
|
||||
|
||||
import Agora.Plutarch.Orphans ()
|
||||
|
|
@ -44,6 +46,7 @@ import Plutarch.DataRepr (
|
|||
PDataFields,
|
||||
PIsDataReprInstances (..),
|
||||
)
|
||||
import Plutarch.Extra.Field (pletAllC)
|
||||
import Plutarch.Extra.TermCont (pguardC, pletFieldsC, pmatchC)
|
||||
import Plutarch.Lift (
|
||||
DerivePConstantViaNewtype (..),
|
||||
|
|
@ -273,6 +276,43 @@ deriving via
|
|||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
{- | Return true if the timing configuration is valid.
|
||||
|
||||
@since 0.2.0
|
||||
-}
|
||||
pisProposalTimeingConfigValid :: Term s (PProposalTimingConfig :--> PBool)
|
||||
pisProposalTimeingConfigValid = phoistAcyclic $
|
||||
plam $ \conf -> unTermCont $ do
|
||||
confF <- pletAllC conf
|
||||
|
||||
-- everything is greater or equal 0
|
||||
pure $
|
||||
ptraceIfFalse "ge 0" $
|
||||
foldr
|
||||
( \t ->
|
||||
(#&&)
|
||||
( pconstant 0
|
||||
#<= pfromData t
|
||||
)
|
||||
)
|
||||
(pconstant True)
|
||||
[ confF.draftTime
|
||||
, confF.votingTime
|
||||
, confF.lockingTime
|
||||
, confF.executingTime
|
||||
]
|
||||
|
||||
{- | Return true if the maximum time width is greater than 0.
|
||||
|
||||
@since 0.2.0
|
||||
-}
|
||||
pisMaxTimeRangeWidthValid :: Term s (PMaxTimeRangeWidth :--> PBool)
|
||||
pisMaxTimeRangeWidthValid =
|
||||
phoistAcyclic $
|
||||
plam $
|
||||
ptraceIfFalse "greater than 0"
|
||||
. (pconstant (MaxTimeRangeWidth 0) #<)
|
||||
|
||||
{- | Get the starting time of a proposal, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field.
|
||||
For every proposal, this is only meant to run once upon creation. Given time range should be
|
||||
tight enough, meaning that the width of the time range should be less than the maximum value.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue