make use of LPE's time module

This commit is contained in:
Hongrui Fang 2022-09-06 21:45:30 +08:00 committed by 方泓睿
parent 1f71f30e52
commit e5dc29f98b
No known key found for this signature in database
GPG key ID: F10AB2CCE24113DD
3 changed files with 64 additions and 82 deletions

View file

@ -36,7 +36,7 @@ import Agora.Proposal (
pneutralOption, pneutralOption,
pwinner, pwinner,
) )
import Agora.Proposal.Time (createProposalStartingTime) import Agora.Proposal.Time (validateProposalStartingTime)
import Agora.Scripts ( import Agora.Scripts (
AgoraScripts, AgoraScripts,
authorityTokenSymbol, authorityTokenSymbol,
@ -74,7 +74,7 @@ import Plutarch.Extra.AssetClass (passetClass, passetClassValueOf)
import Plutarch.Extra.Field (pletAllC) import Plutarch.Extra.Field (pletAllC)
import Plutarch.Extra.List (pfirstJust) import Plutarch.Extra.List (pfirstJust)
import Plutarch.Extra.Map (ptryLookup) import Plutarch.Extra.Map (ptryLookup)
import Plutarch.Extra.Maybe (passertPJust, pfromJust, pmaybeData, pnothing) import Plutarch.Extra.Maybe (passertPJust, pmaybeData, pnothing)
import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=)) import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=))
import Plutarch.Extra.ScriptContext ( import Plutarch.Extra.ScriptContext (
pfindOutputsToAddress, pfindOutputsToAddress,
@ -367,12 +367,7 @@ governorValidator as =
proposalOutputDatum <- pletAllC $ pto $ pfromData proposalOutputDatum' proposalOutputDatum <- pletAllC $ pto $ pfromData proposalOutputDatum'
let expectedStartingTime = let expectedCosigners = psingleton @PBuiltinList # stakeInputDatumF.owner
pfromJust #$ createProposalStartingTime
# oldGovernorDatumF.createProposalTimeRangeMaxWidth
# txInfoF.validRange
expectedCosigners = psingleton @PBuiltinList # stakeInputDatumF.owner
pguardC "Proposal datum correct" $ pguardC "Proposal datum correct" $
foldl1 foldl1
@ -389,8 +384,11 @@ governorValidator as =
proposalOutputDatum.status #== pconstantData Draft proposalOutputDatum.status #== pconstantData Draft
, ptraceIfFalse "cosigners correct" $ , ptraceIfFalse "cosigners correct" $
plistEquals # pfromData proposalOutputDatum.cosigners # expectedCosigners plistEquals # pfromData proposalOutputDatum.cosigners # expectedCosigners
, ptraceIfFalse "starting time correct" $ , ptraceIfFalse "starting time valid" $
proposalOutputDatum.startingTime #== expectedStartingTime validateProposalStartingTime
# oldGovernorDatumF.createProposalTimeRangeMaxWidth
# txInfoF.validRange
# proposalOutputDatum.startingTime
, ptraceIfFalse "copy over configurations" $ , ptraceIfFalse "copy over configurations" $
proposalOutputDatum.thresholds #== oldGovernorDatumF.proposalThresholds proposalOutputDatum.thresholds #== oldGovernorDatumF.proposalThresholds
#&& proposalOutputDatum.timingConfig #== oldGovernorDatumF.proposalTimings #&& proposalOutputDatum.timingConfig #== oldGovernorDatumF.proposalTimings

View file

@ -14,13 +14,13 @@ module Agora.Proposal.Time (
MaxTimeRangeWidth (..), MaxTimeRangeWidth (..),
-- * Plutarch-land -- * Plutarch-land
PProposalTime (..), PProposalTime,
PProposalTimingConfig (..), PProposalTimingConfig (..),
PProposalStartingTime (..), PProposalStartingTime (..),
PMaxTimeRangeWidth (..), PMaxTimeRangeWidth (..),
-- * Compute periods given config and starting time. -- * Compute periods given config and starting time.
createProposalStartingTime, validateProposalStartingTime,
currentProposalTime, currentProposalTime,
isDraftPeriod, isDraftPeriod,
isVotingPeriod, isVotingPeriod,
@ -30,6 +30,7 @@ module Agora.Proposal.Time (
pisMaxTimeRangeWidthValid, pisMaxTimeRangeWidthValid,
) where ) where
import Agora.Utils (pcurrentTimeDuration)
import Control.Composition ((.*)) import Control.Composition ((.*))
import Plutarch.Api.V1 ( import Plutarch.Api.V1 (
PExtended (PFinite), PExtended (PFinite),
@ -44,10 +45,14 @@ import Plutarch.DataRepr (
PDataFields, PDataFields,
) )
import Plutarch.Extra.Applicative (PApply (pliftA2)) import Plutarch.Extra.Applicative (PApply (pliftA2))
import Plutarch.Extra.Bind ((#>>=))
import Plutarch.Extra.Field (pletAll, pletAllC) import Plutarch.Extra.Field (pletAll, pletAllC)
import Plutarch.Extra.Maybe (pjust, pnothing) import Plutarch.Extra.Maybe (pjust, pmaybe, pnothing)
import Plutarch.Extra.TermCont (pmatchC) import Plutarch.Extra.TermCont (pmatchC)
import Plutarch.Extra.Time (
PCurrentTime (PCurrentTime),
pisCurrentTimeWithin,
pisWithinCurrentTime,
)
import Plutarch.Lift ( import Plutarch.Lift (
DerivePConstantViaNewtype (DerivePConstantViaNewtype), DerivePConstantViaNewtype (DerivePConstantViaNewtype),
PConstantDecl, PConstantDecl,
@ -160,23 +165,7 @@ newtype MaxTimeRangeWidth = MaxTimeRangeWidth {getMaxWidth :: POSIXTime}
@since 0.1.0 @since 0.1.0
-} -}
data PProposalTime (s :: S) = PProposalTime type PProposalTime = PCurrentTime
{ lowerBound :: Term s PPOSIXTime
, upperBound :: Term s PPOSIXTime
}
deriving stock
( -- | @since 0.1.0
Generic
)
deriving anyclass
( -- | @since 0.1.0
PlutusType
, -- | @since 0.1.0
PEq
)
instance DerivePlutusType PProposalTime where
type DPTStrat _ = PlutusTypeScott
-- | Plutarch-level version of 'ProposalStartingTime'. -- | Plutarch-level version of 'ProposalStartingTime'.
newtype PProposalStartingTime (s :: S) = PProposalStartingTime (Term s PPOSIXTime) newtype PProposalStartingTime (s :: S) = PProposalStartingTime (Term s PPOSIXTime)
@ -327,38 +316,41 @@ pisMaxTimeRangeWidthValid =
ptraceIfFalse "greater than 0" ptraceIfFalse "greater than 0"
. (pconstant (MaxTimeRangeWidth 0) #<) . (pconstant (MaxTimeRangeWidth 0) #<)
{- | Get the starting time of a proposal, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field. {- | Validate 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 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. tight enough, meaning that the width of the time range should be less than the maximum value.
@since 0.1.0 @since 1.0.0
-} -}
createProposalStartingTime :: validateProposalStartingTime ::
forall (s :: S). forall (s :: S).
Term Term
s s
( PMaxTimeRangeWidth ( PMaxTimeRangeWidth
:--> PPOSIXTimeRange :--> PPOSIXTimeRange
:--> PMaybe PProposalStartingTime :--> PProposalStartingTime
:--> PBool
) )
createProposalStartingTime = phoistAcyclic $ validateProposalStartingTime = phoistAcyclic $
plam $ \(pto -> maxDuration) iv -> plam $ \(pto -> maxDuration) iv (pto -> st) ->
let ct = currentProposalTime # iv pmaybe
# ptrace
f :: Term _ (PProposalTime :--> PMaybe PProposalStartingTime) "validateProposalStartingTime: unable to get current time"
f = plam $ (pconstant False)
flip pmatch $ \(PProposalTime lb ub) -> # plam
let duration = ub - lb ( \ct ->
let duration = pcurrentTimeDuration # ct
startingTime = pdiv # (lb + ub) # 2 isTightEnough =
in pif ptraceIfFalse
(duration #<= maxDuration) "createProposalStartingTime: given time range should be tight enough"
(pjust #$ pcon $ PProposalStartingTime startingTime) $ duration #<= maxDuration
( ptrace isInCurrentTimeRange =
"createProposalStartingTime: given time range should be tight enough" ptraceIfFalse
pnothing "createProposalStartingTime: starting time should be in current time range"
) $ pisWithinCurrentTime # st # ct
in ct #>>= f in isTightEnough #&& isInCurrentTimeRange
)
# (currentProposalTime # iv)
{- | Get the current proposal time, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field. {- | Get the current proposal time, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field.
@ -389,32 +381,9 @@ currentProposalTime = phoistAcyclic $
lowerBound = getBound # lb lowerBound = getBound # lb
upperBound = getBound # ub upperBound = getBound # ub
mkTime = phoistAcyclic $ plam $ pcon .* PProposalTime mkTime = phoistAcyclic $ plam $ pcon .* PCurrentTime
pure $ pliftA2 # mkTime # lowerBound # upperBound pure $ pliftA2 # mkTime # lowerBound # upperBound
{- | Check if 'PProposalTime' is within two 'PPOSIXTime'. Inclusive.
@since 0.1.0
-}
proposalTimeWithin ::
forall (s :: S).
Term
s
( PPOSIXTime
:--> PPOSIXTime
:--> PProposalTime
:--> PBool
)
proposalTimeWithin = phoistAcyclic $
plam $ \l h proposalTime' -> unTermCont $ do
PProposalTime ut lt <- pmatchC proposalTime'
pure $
foldr1
(#&&)
[ l #<= lt
, ut #<= h
]
{- | True if the 'PProposalTime' is in the draft period. {- | True if the 'PProposalTime' is in the draft period.
@since 0.1.0 @since 0.1.0
@ -430,7 +399,7 @@ isDraftPeriod ::
) )
isDraftPeriod = phoistAcyclic $ isDraftPeriod = phoistAcyclic $
plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) -> plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) ->
proposalTimeWithin # s # (s + (pfield @"draftTime" # config)) pisCurrentTimeWithin # s # (s + (pfield @"draftTime" # config))
{- | True if the 'PProposalTime' is in the voting period. {- | True if the 'PProposalTime' is in the voting period.
@ -448,7 +417,7 @@ isVotingPeriod ::
isVotingPeriod = phoistAcyclic $ isVotingPeriod = phoistAcyclic $
plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) -> plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) ->
pletFields @'["draftTime", "votingTime"] config $ \f -> pletFields @'["draftTime", "votingTime"] config $ \f ->
proposalTimeWithin # s # (s + f.draftTime + f.votingTime) pisCurrentTimeWithin # s # (s + f.draftTime + f.votingTime)
{- | True if the 'PProposalTime' is in the locking period. {- | True if the 'PProposalTime' is in the locking period.
@ -466,7 +435,7 @@ isLockingPeriod ::
isLockingPeriod = phoistAcyclic $ isLockingPeriod = phoistAcyclic $
plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) -> plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) ->
pletFields @'["draftTime", "votingTime", "lockingTime"] config $ \f -> pletFields @'["draftTime", "votingTime", "lockingTime"] config $ \f ->
proposalTimeWithin # s # (s + f.draftTime + f.votingTime + f.lockingTime) pisCurrentTimeWithin # s # (s + f.draftTime + f.votingTime + f.lockingTime)
{- | True if the 'PProposalTime' is in the execution period. {- | True if the 'PProposalTime' is in the execution period.
@ -484,5 +453,5 @@ isExecutionPeriod ::
isExecutionPeriod = phoistAcyclic $ isExecutionPeriod = phoistAcyclic $
plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) -> plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) ->
pletFields @'["draftTime", "votingTime", "lockingTime", "executingTime"] config $ \f -> pletFields @'["draftTime", "votingTime", "lockingTime", "executingTime"] config $ \f ->
proposalTimeWithin # s pisCurrentTimeWithin # s
# (s + f.draftTime + f.votingTime + f.lockingTime + f.executingTime) # (s + f.draftTime + f.votingTime + f.lockingTime + f.executingTime)

View file

@ -21,11 +21,13 @@ module Agora.Utils (
plistEqualsBy, plistEqualsBy,
pstringIntercalate, pstringIntercalate,
punwords, punwords,
pcurrentTimeDuration,
) where ) where
import Plutarch.Api.V1 (PTokenName, PValidatorHash) import Plutarch.Api.V1 (PPOSIXTime, PTokenName, PValidatorHash)
import Plutarch.Api.V2 (PScriptHash) import Plutarch.Api.V2 (PScriptHash)
import Plutarch.Extra.TermCont (pmatchC) import Plutarch.Extra.TermCont (pmatchC)
import Plutarch.Extra.Time (PCurrentTime (PCurrentTime))
import Plutarch.List (puncons) import Plutarch.List (puncons)
import Plutarch.Unsafe (punsafeCoerce) import Plutarch.Unsafe (punsafeCoerce)
import PlutusLedgerApi.V2 ( import PlutusLedgerApi.V2 (
@ -175,3 +177,16 @@ punwords ::
[Term s PString] -> [Term s PString] ->
Term s PString Term s PString
punwords = pstringIntercalate " " punwords = pstringIntercalate " "
-- | @since 1.0.0
pcurrentTimeDuration ::
forall (s :: S).
Term
s
( PCurrentTime
:--> PPOSIXTime
)
pcurrentTimeDuration = phoistAcyclic $
plam $
flip pmatch $
\(PCurrentTime lb ub) -> ub - lb