apply Emily's suggestions
This commit is contained in:
parent
9c8d04dbc6
commit
f00cc62476
3 changed files with 334 additions and 328 deletions
|
|
@ -42,6 +42,7 @@ import Agora.Utils (
|
|||
import Plutarch.Api.V1 (
|
||||
PDatumHash,
|
||||
PMintingPolicy,
|
||||
PPubKeyHash,
|
||||
PScriptContext (PScriptContext),
|
||||
PScriptPurpose (PMinting, PSpending),
|
||||
PTxInfo (PTxInfo),
|
||||
|
|
@ -305,198 +306,272 @@ proposalValidator proposal =
|
|||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
let acceptMultipleStakes = pmatch proposalRedeemer $ \case
|
||||
PCosign _ -> pconstant True
|
||||
PAdvanceProposal _ ->
|
||||
currentStatus #== pconstant Draft
|
||||
_ -> pconstant False
|
||||
withMultipleStakes' ::
|
||||
Term
|
||||
_
|
||||
( ( PInteger
|
||||
:--> PBuiltinList (PAsData PPubKeyHash)
|
||||
:--> PUnit
|
||||
)
|
||||
:--> PUnit
|
||||
) <-
|
||||
pletC $
|
||||
plam $ \validationLogic -> unTermCont $ do
|
||||
-- The following code ensures that all the stake datums are not
|
||||
-- changed.
|
||||
--
|
||||
-- TODO: This is quite inefficient (O(nlogn)) but for now we don't
|
||||
-- have a nice way to check this. In plutus v2 we'll have map of
|
||||
-- (Script -> Redeemer) in ScriptContext, which should be the
|
||||
-- straight up solution.
|
||||
let sortDatumHashes = phoistAcyclic $ pmsortBy # pltAsData
|
||||
|
||||
sortedStakeInputDatumHashes =
|
||||
sortDatumHashes # stakeInputDatumHashes
|
||||
|
||||
sortedStakeOutputDatumHashes =
|
||||
sortDatumHashes # stakeOutputDatumHashes
|
||||
|
||||
pguardC "All stake datum are unchanged" $
|
||||
plistEquals
|
||||
# sortedStakeInputDatumHashes
|
||||
# sortedStakeOutputDatumHashes
|
||||
|
||||
PPair totalStakedAmount stakeOwners <-
|
||||
pmatchC $
|
||||
pfoldl
|
||||
# plam
|
||||
( \l dh -> unTermCont $ do
|
||||
let stake =
|
||||
pfromData $
|
||||
pfromJust
|
||||
#$ ptryFindDatum
|
||||
@(PAsData PStakeDatum)
|
||||
# pfromData dh
|
||||
# txInfoF.datums
|
||||
|
||||
stakeF <- pletFieldsC @'["stakedAmount", "owner"] stake
|
||||
|
||||
PPair amount owners <- pmatchC l
|
||||
|
||||
let newAmount = amount + punsafeCoerce (pfromData stakeF.stakedAmount)
|
||||
updatedOwners = pcons # stakeF.owner # owners
|
||||
|
||||
pure $ pcon $ PPair newAmount updatedOwners
|
||||
)
|
||||
# pcon (PPair (0 :: Term _ PInteger) (pnil @PBuiltinList))
|
||||
# stakeInputDatumHashes
|
||||
|
||||
sortedStakeOwners <- pletC $ pmsortBy # pltAsData # stakeOwners
|
||||
|
||||
pure $ validationLogic # totalStakedAmount # sortedStakeOwners
|
||||
|
||||
withSingleStake' ::
|
||||
Term
|
||||
_
|
||||
( ( PStakeDatum :--> PStakeDatum :--> PBool :--> PUnit
|
||||
)
|
||||
:--> PUnit
|
||||
) <- pletC $
|
||||
plam $ \validationLogic -> unTermCont $ do
|
||||
pguardC "Can only deal with one stake" $
|
||||
stakeInputNum #== 1
|
||||
|
||||
stakeInputHash <- pletC $ pfromData $ phead # stakeInputDatumHashes
|
||||
stakeOutputHash <- pletC $ pfromData $ phead # stakeOutputDatumHashes
|
||||
|
||||
stakeIn :: Term _ PStakeDatum <-
|
||||
pletC $
|
||||
pfromData $
|
||||
pfromJust #$ ptryFindDatum # stakeInputHash # txInfoF.datums
|
||||
|
||||
stakeOut :: Term _ PStakeDatum <-
|
||||
pletC $
|
||||
pfromData $
|
||||
pfromJust #$ ptryFindDatum # stakeOutputHash # txInfoF.datums
|
||||
|
||||
stakeUnchanged <- pletC $ stakeInputHash #== stakeOutputHash
|
||||
|
||||
pure $ validationLogic # stakeIn # stakeOut # stakeUnchanged
|
||||
|
||||
let withMultipleStakes val =
|
||||
withMultipleStakes' #$ plam $
|
||||
\totalStakedAmount
|
||||
sortedStakeOwner ->
|
||||
unTermCont $
|
||||
val totalStakedAmount sortedStakeOwner
|
||||
|
||||
withSingleStake val =
|
||||
withSingleStake' #$ plam $ \stakeIn stakeOut stakeUnchange -> unTermCont $ do
|
||||
stakeInF <- pletFieldsC @'["stakedAmount", "lockedBy", "owner"] stakeIn
|
||||
|
||||
val stakeInF stakeOut stakeUnchange
|
||||
|
||||
pure $
|
||||
popaque $
|
||||
pif
|
||||
acceptMultipleStakes
|
||||
( unTermCont $ do
|
||||
-- The following code ensures that all the stake datums are not
|
||||
-- changed.
|
||||
--
|
||||
-- TODO: This is quite inefficient (O(nlogn)) but for now we don't
|
||||
-- have a nice way to check this. In plutus v2 we'll have map of
|
||||
-- (Script -> Redeemer) in ScriptContext, which should be the
|
||||
-- straight up solution.
|
||||
let sortDatumHashes = phoistAcyclic $ pmsortBy # pltAsData
|
||||
pmatch proposalRedeemer $ \case
|
||||
PCosign r -> withMultipleStakes $ \_ sortedStakeOwners -> do
|
||||
pguardC "Should be in draft state" $
|
||||
currentStatus #== pconstant Draft
|
||||
|
||||
sortedStakeInputDatumHashes =
|
||||
sortDatumHashes # stakeInputDatumHashes
|
||||
newSigs <- pletC $ pfield @"newCosigners" # r
|
||||
|
||||
sortedStakeOutputDatumHashes =
|
||||
sortDatumHashes # stakeOutputDatumHashes
|
||||
pguardC "Signed by all new cosigners" $
|
||||
pall # signedBy # newSigs
|
||||
|
||||
pguardC "All stake datum are unchanged" $
|
||||
plistEquals
|
||||
# sortedStakeInputDatumHashes
|
||||
# sortedStakeOutputDatumHashes
|
||||
updatedSigs <-
|
||||
pletC $
|
||||
pmergeBy # pltAsData
|
||||
# newSigs
|
||||
# proposalF.cosigners
|
||||
|
||||
PPair totalStakedAmount stakeOwners <-
|
||||
pmatchC $
|
||||
pfoldl
|
||||
# plam
|
||||
( \l dh -> unTermCont $ do
|
||||
let stake =
|
||||
pfromData $
|
||||
pfromJust
|
||||
#$ ptryFindDatum
|
||||
@(PAsData PStakeDatum)
|
||||
# pfromData dh
|
||||
# txInfoF.datums
|
||||
pguardC "Cosigners are unique" $
|
||||
pisUniq' # updatedSigs
|
||||
|
||||
stakeF <- pletFieldsC @'["stakedAmount", "owner"] stake
|
||||
pguardC "All new cosigners are witnessed by their Stake datums" $
|
||||
plistEquals # sortedStakeOwners # newSigs
|
||||
|
||||
PPair amount owners <- pmatchC l
|
||||
let expectedDatum =
|
||||
mkRecordConstr
|
||||
PProposalDatum
|
||||
( #proposalId .= proposalF.proposalId
|
||||
.& #effects .= proposalF.effects
|
||||
.& #status .= proposalF.status
|
||||
.& #cosigners .= pdata updatedSigs
|
||||
.& #thresholds .= proposalF.thresholds
|
||||
.& #votes .= proposalF.votes
|
||||
.& #timingConfig .= proposalF.timingConfig
|
||||
.& #startingTime .= proposalF.startingTime
|
||||
)
|
||||
|
||||
let newAmount = amount + punsafeCoerce (pfromData stakeF.stakedAmount)
|
||||
updatedOwners = pcons # stakeF.owner # owners
|
||||
pguardC "Signatures are correctly added to cosignature list" $
|
||||
proposalOut #== expectedDatum
|
||||
|
||||
pure $ pcon $ PPair newAmount updatedOwners
|
||||
)
|
||||
# pcon (PPair (0 :: Term _ PInteger) (pnil @PBuiltinList))
|
||||
# stakeInputDatumHashes
|
||||
pure $ pconstant ()
|
||||
|
||||
sortedStakeOwners <- pletC $ pmsortBy # pltAsData # stakeOwners
|
||||
----------------------------------------------------------------------
|
||||
|
||||
redeemer <- pmatchC proposalRedeemer
|
||||
PVote r -> withSingleStake $ \stakeInF stakeOut _ -> do
|
||||
pguardC "Input proposal must be in VotingReady state" $
|
||||
currentStatus #== pconstant VotingReady
|
||||
|
||||
case redeemer of
|
||||
PCosign r -> do
|
||||
pguardC "Should be in draft state" $
|
||||
currentStatus #== pconstant Draft
|
||||
pguardC "Proposal time should be wthin the voting period" $
|
||||
isVotingPeriod # proposalF.timingConfig
|
||||
# proposalF.startingTime
|
||||
# currentTime
|
||||
|
||||
newSigs <- pletC $ pfield @"newCosigners" # r
|
||||
-- Ensure the transaction is voting to a valid 'ResultTag'(outcome).
|
||||
PProposalVotes voteMap <- pmatchC proposalF.votes
|
||||
voteFor <- pletC $ pfromData $ pfield @"resultTag" # r
|
||||
|
||||
pguardC "Signed by all new cosigners" $
|
||||
pall # signedBy # newSigs
|
||||
pguardC "Vote option should be valid" $
|
||||
pisJust #$ plookup # voteFor # voteMap
|
||||
|
||||
updatedSigs <-
|
||||
pletC $
|
||||
pmergeBy # pltAsData
|
||||
# newSigs
|
||||
# proposalF.cosigners
|
||||
-- Ensure that no lock with the current proposal id has been put on the stake.
|
||||
pguardC "Same stake shouldn't vote on the same proposal twice" $
|
||||
pnot #$ pany
|
||||
# plam
|
||||
( \((pfield @"proposalTag" #) . pfromData -> pid) ->
|
||||
pid #== proposalF.proposalId
|
||||
)
|
||||
# pfromData stakeInF.lockedBy
|
||||
|
||||
pguardC "Cosigners are unique" $
|
||||
pisUniq' # updatedSigs
|
||||
|
||||
pguardC "All new cosigners are witnessed by their Stake datums" $
|
||||
plistEquals # sortedStakeOwners # newSigs
|
||||
|
||||
let expectedDatum =
|
||||
mkRecordConstr
|
||||
PProposalDatum
|
||||
( #proposalId .= proposalF.proposalId
|
||||
.& #effects .= proposalF.effects
|
||||
.& #status .= proposalF.status
|
||||
.& #cosigners .= pdata updatedSigs
|
||||
.& #thresholds .= proposalF.thresholds
|
||||
.& #votes .= proposalF.votes
|
||||
.& #timingConfig .= proposalF.timingConfig
|
||||
.& #startingTime .= proposalF.startingTime
|
||||
let -- The amount of new votes should be the 'stakedAmount'.
|
||||
-- Update the vote counter of the proposal, and leave other stuff as is.
|
||||
expectedNewVotes = pmatch (pfromData proposalF.votes) $ \(PProposalVotes m) ->
|
||||
pcon $
|
||||
PProposalVotes $
|
||||
pupdate
|
||||
# plam
|
||||
( \votes -> unTermCont $ do
|
||||
PDiscrete v <- pmatchC stakeInF.stakedAmount
|
||||
pure $ pcon $ PJust $ votes + (pextract # v)
|
||||
)
|
||||
# voteFor
|
||||
# m
|
||||
expectedProposalOut =
|
||||
mkRecordConstr
|
||||
PProposalDatum
|
||||
( #proposalId .= proposalF.proposalId
|
||||
.& #effects .= proposalF.effects
|
||||
.& #status .= proposalF.status
|
||||
.& #cosigners .= proposalF.cosigners
|
||||
.& #thresholds .= proposalF.thresholds
|
||||
.& #votes .= pdata expectedNewVotes
|
||||
.& #timingConfig .= proposalF.timingConfig
|
||||
.& #startingTime .= proposalF.startingTime
|
||||
)
|
||||
|
||||
pguardC "Signatures are correctly added to cosignature list" $
|
||||
proposalOut #== expectedDatum
|
||||
pguardC "Output proposal should be valid" $ proposalOut #== expectedProposalOut
|
||||
|
||||
pure $ pconstant ()
|
||||
-- We validate the output stake datum here as well: We need the vote option
|
||||
-- to create a valid 'ProposalLock', however the vote option is encoded
|
||||
-- in the proposal redeemer, which is invisible for the stake validator.
|
||||
|
||||
------------------------------------------------------------------
|
||||
let newProposalLock =
|
||||
mkRecordConstr
|
||||
PProposalLock
|
||||
( #vote .= pdata voteFor
|
||||
.& #proposalTag .= proposalF.proposalId
|
||||
)
|
||||
-- Prepend the new lock to existing locks
|
||||
expectedProposalLocks =
|
||||
pcons
|
||||
# pdata newProposalLock
|
||||
# pfromData stakeInF.lockedBy
|
||||
expectedStakeOut =
|
||||
mkRecordConstr
|
||||
PStakeDatum
|
||||
( #stakedAmount .= stakeInF.stakedAmount
|
||||
.& #owner .= stakeInF.owner
|
||||
.& #lockedBy .= pdata expectedProposalLocks
|
||||
)
|
||||
|
||||
PAdvanceProposal _ -> do
|
||||
inDraftPeriod <-
|
||||
pletC $
|
||||
isDraftPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime
|
||||
pguardC "Output stake should be locked by the proposal" $ expectedStakeOut #== stakeOut
|
||||
|
||||
pure $
|
||||
pif
|
||||
inDraftPeriod
|
||||
( unTermCont $ do
|
||||
pguardC "More cosigns than minimum amount" $
|
||||
punsafeCoerce (pfromData thresholdsF.vote) #< totalStakedAmount
|
||||
pure $ pconstant ()
|
||||
|
||||
pguardC "All new cosigners are witnessed by their Stake datums" $
|
||||
plistEquals # sortedStakeOwners # proposalF.cosigners
|
||||
----------------------------------------------------------------------
|
||||
|
||||
-- 'Draft' -> 'VotingReady'
|
||||
pguardC "Proposal status set to VotingReady" $
|
||||
proposalOutStatus #== pconstant VotingReady
|
||||
PUnlock r -> withSingleStake $ \stakeInF stakeOut _ -> do
|
||||
-- At draft stage, the votes should be empty.
|
||||
pguardC "Shouldn't retract votes from a draft proposal" $
|
||||
pnot #$ currentStatus #== pconstant Draft
|
||||
|
||||
pure $ pconstant ()
|
||||
)
|
||||
( unTermCont $ do
|
||||
pguardC "Advance to failed state" $ proposalOutStatus #== pconstant Finished
|
||||
-- This is the vote option we're retracting from.
|
||||
retractFrom <- pletC $ pfield @"resultTag" # r
|
||||
|
||||
pure $ pconstant ()
|
||||
)
|
||||
-- Determine if the input stake is actually locked by this proposal.
|
||||
stakeUsage <- pletC $ pgetStakeUsage # stakeInF.lockedBy # proposalF.proposalId
|
||||
|
||||
------------------------------------------------------------------
|
||||
pguardC "Stake input relevant" $
|
||||
pmatch stakeUsage $ \case
|
||||
PDidNothing ->
|
||||
ptraceIfFalse "Stake should be relevant" $
|
||||
pconstant False
|
||||
PCreated ->
|
||||
ptraceIfFalse "Removing creator's locks means status is Finished" $
|
||||
currentStatus #== pconstant Finished
|
||||
PVotedFor rt ->
|
||||
ptraceIfFalse "Result tag should match the one given in the redeemer" $
|
||||
rt #== retractFrom
|
||||
|
||||
_ -> pure $ pconstant ()
|
||||
)
|
||||
( unTermCont $ do
|
||||
pguardC "Can only deal with one stake" $
|
||||
stakeInputNum #== 1
|
||||
-- The count of removing votes is equal to the 'stakeAmount' of input stake.
|
||||
retractCount <-
|
||||
pletC $
|
||||
pmatch stakeInF.stakedAmount $ \(PDiscrete v) -> pextract # v
|
||||
|
||||
let stakeInputHash = pfromData $ phead # stakeInputDatumHashes
|
||||
stakeOutputHash = pfromData $ phead # stakeOutputDatumHashes
|
||||
-- The votes can only change when the proposal still allows voting.
|
||||
let shouldUpdateVotes =
|
||||
currentStatus #== pconstant VotingReady
|
||||
#&& pnot # (pcon PCreated #== stakeUsage)
|
||||
|
||||
stakeIn :: Term _ PStakeDatum <-
|
||||
pletC $
|
||||
pfromData $
|
||||
pfromJust #$ ptryFindDatum # stakeInputHash # txInfoF.datums
|
||||
stakeInF <- pletFieldsC @'["stakedAmount", "lockedBy", "owner"] stakeIn
|
||||
pguardC "Proposal output correct" $
|
||||
pif
|
||||
shouldUpdateVotes
|
||||
( let -- Remove votes and leave other parts of the proposal as it.
|
||||
expectedVotes = pretractVotes # retractFrom # retractCount # proposalF.votes
|
||||
|
||||
stakeOut :: Term _ PStakeDatum <-
|
||||
pletC $
|
||||
pfromData $
|
||||
pfromJust #$ ptryFindDatum # stakeOutputHash # txInfoF.datums
|
||||
|
||||
redeemer <- pmatchC proposalRedeemer
|
||||
|
||||
case redeemer of
|
||||
PVote r -> do
|
||||
pguardC "Input proposal must be in VotingReady state" $
|
||||
currentStatus #== pconstant VotingReady
|
||||
|
||||
pguardC "Proposal time should be wthin the voting period" $
|
||||
isVotingPeriod # proposalF.timingConfig
|
||||
# proposalF.startingTime
|
||||
# currentTime
|
||||
|
||||
-- Ensure the transaction is voting to a valid 'ResultTag'(outcome).
|
||||
PProposalVotes voteMap <- pmatchC proposalF.votes
|
||||
voteFor <- pletC $ pfromData $ pfield @"resultTag" # r
|
||||
|
||||
pguardC "Vote option should be valid" $
|
||||
pisJust #$ plookup # voteFor # voteMap
|
||||
|
||||
-- Ensure that no lock with the current proposal id has been put on the stake.
|
||||
pguardC "Same stake shouldn't vote on the same proposal twice" $
|
||||
pnot #$ pany
|
||||
# plam
|
||||
( \((pfield @"proposalTag" #) . pfromData -> pid) ->
|
||||
pid #== proposalF.proposalId
|
||||
)
|
||||
# pfromData stakeInF.lockedBy
|
||||
|
||||
let -- The amount of new votes should be the 'stakedAmount'.
|
||||
-- Update the vote counter of the proposal, and leave other stuff as is.
|
||||
expectedNewVotes = pmatch (pfromData proposalF.votes) $ \(PProposalVotes m) ->
|
||||
pcon $
|
||||
PProposalVotes $
|
||||
pupdate
|
||||
# plam
|
||||
( \votes -> unTermCont $ do
|
||||
PDiscrete v <- pmatchC stakeInF.stakedAmount
|
||||
pure $ pcon $ PJust $ votes + (pextract # v)
|
||||
)
|
||||
# voteFor
|
||||
# m
|
||||
expectedProposalOut =
|
||||
mkRecordConstr
|
||||
PProposalDatum
|
||||
|
|
@ -505,122 +580,60 @@ proposalValidator proposal =
|
|||
.& #status .= proposalF.status
|
||||
.& #cosigners .= proposalF.cosigners
|
||||
.& #thresholds .= proposalF.thresholds
|
||||
.& #votes .= pdata expectedNewVotes
|
||||
.& #votes .= pdata expectedVotes
|
||||
.& #timingConfig .= proposalF.timingConfig
|
||||
.& #startingTime .= proposalF.startingTime
|
||||
)
|
||||
in ptraceIfFalse "Update votes" $
|
||||
expectedProposalOut #== proposalOut
|
||||
)
|
||||
-- No change to the proposal is allowed.
|
||||
$ ptraceIfFalse "Proposal unchanged" proposalUnchanged
|
||||
|
||||
pguardC "Output proposal should be valid" $ proposalOut #== expectedProposalOut
|
||||
-- At last, we ensure that all locks belong to this proposal will be removed.
|
||||
stakeOutputLocks <- pletC $ pfield @"lockedBy" # stakeOut
|
||||
|
||||
-- We validate the output stake datum here as well: We need the vote option
|
||||
-- to create a valid 'ProposalLock', however the vote option is encoded
|
||||
-- in the proposal redeemer, which is invisible for the stake validator.
|
||||
let templateStakeOut =
|
||||
mkRecordConstr
|
||||
PStakeDatum
|
||||
( #stakedAmount .= stakeInF.stakedAmount
|
||||
.& #owner .= stakeInF.owner
|
||||
.& #lockedBy .= stakeOutputLocks
|
||||
)
|
||||
|
||||
let newProposalLock =
|
||||
mkRecordConstr
|
||||
PProposalLock
|
||||
( #vote .= pdata voteFor
|
||||
.& #proposalTag .= proposalF.proposalId
|
||||
)
|
||||
-- Prepend the new lock to existing locks
|
||||
expectedProposalLocks =
|
||||
pcons
|
||||
# pdata newProposalLock
|
||||
# pfromData stakeInF.lockedBy
|
||||
expectedStakeOut =
|
||||
mkRecordConstr
|
||||
PStakeDatum
|
||||
( #stakedAmount .= stakeInF.stakedAmount
|
||||
.& #owner .= stakeInF.owner
|
||||
.& #lockedBy .= pdata expectedProposalLocks
|
||||
)
|
||||
pguardC "Only locks updated in the output stake" $
|
||||
templateStakeOut #== stakeOut
|
||||
|
||||
pguardC "Output stake should be locked by the proposal" $ expectedStakeOut #== stakeOut
|
||||
pguardC "All relevant locks removed from the stake" $
|
||||
pgetStakeUsage # pfromData stakeOutputLocks
|
||||
# proposalF.proposalId #== pcon PDidNothing
|
||||
|
||||
pure $ pconstant ()
|
||||
pure $ pconstant ()
|
||||
|
||||
------------------------------------------------------------------
|
||||
PUnlock r -> do
|
||||
-- At draft stage, the votes should be empty.
|
||||
pguardC "Shouldn't retract votes from a draft proposal" $
|
||||
pnot #$ currentStatus #== pconstant Draft
|
||||
----------------------------------------------------------------------
|
||||
|
||||
-- This is the vote option we're retracting from.
|
||||
retractFrom <- pletC $ pfield @"resultTag" # r
|
||||
PAdvanceProposal _ ->
|
||||
let fromDraft = withMultipleStakes $ \totalStakedAmount sortedStakeOwners ->
|
||||
pmatchC (isDraftPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime) >>= \case
|
||||
PTrue -> do
|
||||
pguardC "More cosigns than minimum amount" $
|
||||
punsafeCoerce (pfromData thresholdsF.vote) #< totalStakedAmount
|
||||
|
||||
-- Determine if the input stake is actually locked by this proposal.
|
||||
stakeUsage <- pletC $ pgetStakeUsage # stakeInF.lockedBy # proposalF.proposalId
|
||||
pguardC "All new cosigners are witnessed by their Stake datums" $
|
||||
plistEquals # sortedStakeOwners # proposalF.cosigners
|
||||
|
||||
pguardC "Stake input relevant" $
|
||||
pmatch stakeUsage $ \case
|
||||
PDidNothing ->
|
||||
ptraceIfFalse "Stake should be relevant" $
|
||||
pconstant False
|
||||
PCreated ->
|
||||
ptraceIfFalse "Removing creator's locks means status is Finished" $
|
||||
currentStatus #== pconstant Finished
|
||||
PVotedFor rt ->
|
||||
ptraceIfFalse "Result tag should match the one given in the redeemer" $
|
||||
rt #== retractFrom
|
||||
-- 'Draft' -> 'VotingReady'
|
||||
pguardC "Proposal status set to VotingReady" $
|
||||
proposalOutStatus #== pconstant VotingReady
|
||||
|
||||
-- The count of removing votes is equal to the 'stakeAmount' of input stake.
|
||||
retractCount <-
|
||||
pletC $
|
||||
pmatch stakeInF.stakedAmount $ \(PDiscrete v) -> pextract # v
|
||||
pure $ pconstant ()
|
||||
PFalse -> do
|
||||
pguardC "Advance to failed state" $ proposalOutStatus #== pconstant Finished
|
||||
|
||||
-- The votes can only change when the proposal still allows voting.
|
||||
let shouldUpdateVotes =
|
||||
currentStatus #== pconstant VotingReady
|
||||
#&& pnot # (pcon PCreated #== stakeUsage)
|
||||
pure $ pconstant ()
|
||||
|
||||
pguardC "Proposal output correct" $
|
||||
pif
|
||||
shouldUpdateVotes
|
||||
( let -- Remove votes and leave other parts of the proposal as it.
|
||||
expectedVotes = pretractVotes # retractFrom # retractCount # proposalF.votes
|
||||
|
||||
expectedProposalOut =
|
||||
mkRecordConstr
|
||||
PProposalDatum
|
||||
( #proposalId .= proposalF.proposalId
|
||||
.& #effects .= proposalF.effects
|
||||
.& #status .= proposalF.status
|
||||
.& #cosigners .= proposalF.cosigners
|
||||
.& #thresholds .= proposalF.thresholds
|
||||
.& #votes .= pdata expectedVotes
|
||||
.& #timingConfig .= proposalF.timingConfig
|
||||
.& #startingTime .= proposalF.startingTime
|
||||
)
|
||||
in ptraceIfFalse "Update votes" $
|
||||
expectedProposalOut #== proposalOut
|
||||
)
|
||||
-- No change to the proposal is allowed.
|
||||
$ ptraceIfFalse "Proposal unchanged" proposalUnchanged
|
||||
|
||||
-- At last, we ensure that all locks belong to this proposal will be removed.
|
||||
stakeOutputLocks <- pletC $ pfield @"lockedBy" # stakeOut
|
||||
|
||||
let templateStakeOut =
|
||||
mkRecordConstr
|
||||
PStakeDatum
|
||||
( #stakedAmount .= stakeInF.stakedAmount
|
||||
.& #owner .= stakeInF.owner
|
||||
.& #lockedBy .= stakeOutputLocks
|
||||
)
|
||||
|
||||
pguardC "Only locks updated in the output stake" $
|
||||
templateStakeOut #== stakeOut
|
||||
|
||||
pguardC "All relevant locks removed from the stake" $
|
||||
pgetStakeUsage # pfromData stakeOutputLocks
|
||||
# proposalF.proposalId #== pcon PDidNothing
|
||||
|
||||
pure $ pconstant ()
|
||||
|
||||
------------------------------------------------------------------
|
||||
PAdvanceProposal _ -> do
|
||||
pguardC "Stake should not change" $
|
||||
stakeInputHash #== stakeOutputHash
|
||||
fromOther = withSingleStake $ \_ _ stakeUnchanged -> do
|
||||
pguardC "Stake should not change" stakeUnchanged
|
||||
|
||||
pguardC
|
||||
"Only status changes in the output proposal"
|
||||
|
|
@ -655,6 +668,7 @@ proposalValidator proposal =
|
|||
|
||||
-- TODO: Should check that the GST is not moved
|
||||
-- if the proposal is in 'Locked' state.
|
||||
|
||||
pure $ pconstant ()
|
||||
|
||||
toNextState = pmatchEnum proposalStatus $ \case
|
||||
|
|
@ -685,5 +699,4 @@ proposalValidator proposal =
|
|||
toNextState
|
||||
-- Too late: failed proposal, status set to 'Finished'.
|
||||
toFailedState
|
||||
_ -> pure $ pconstant ()
|
||||
)
|
||||
in pif (currentStatus #== pconstant Draft) fromDraft fromOther
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import Agora.Utils (
|
|||
mustFindDatum',
|
||||
pvalidatorHashToTokenName,
|
||||
)
|
||||
import Data.Function (on)
|
||||
import Data.Tagged (Tagged (..), untag)
|
||||
import Plutarch.Api.V1 (
|
||||
AmountGuarantees (Positive),
|
||||
|
|
@ -303,10 +304,10 @@ stakeValidator stake =
|
|||
# pfromData txInfoF.outputs
|
||||
|
||||
let witnessStake = unTermCont $ do
|
||||
pguardC "Either owner signs the transaction or propsoal token moved" $
|
||||
pguardC "Either owner signs the transaction or proposal token moved" $
|
||||
ownerSignsTransaction #|| proposalTokenMoved
|
||||
|
||||
-- FIXME: refactor this with reference input, once it's supported by plutarch.
|
||||
-- FIXME: remove this once we have reference input.
|
||||
--
|
||||
-- Our goal here is to allow multiple input stakes, and also ensure that every the input stakes has a
|
||||
-- corresponding output stake, which carries the same value and the same datum as the input stake.
|
||||
|
|
@ -335,15 +336,7 @@ stakeValidator stake =
|
|||
# pfromData txInfoF.inputs
|
||||
|
||||
sortTxOuts :: Term _ (PBuiltinList (PAsData PTxOut) :--> PBuiltinList (PAsData PTxOut))
|
||||
sortTxOuts =
|
||||
plam
|
||||
( pmsortBy
|
||||
# plam
|
||||
( \((getDatumHash #) -> dhX)
|
||||
((getDatumHash #) -> dhY) -> dhX #< dhY
|
||||
)
|
||||
#
|
||||
)
|
||||
sortTxOuts = phoistAcyclic $ plam (pmsortBy # plam ((#<) `on` (getDatumHash #)) #)
|
||||
where
|
||||
getDatumHash :: Term _ (PAsData PTxOut :--> PDatumHash)
|
||||
getDatumHash = phoistAcyclic $ plam ((pfromDJust #) . pfromData . (pfield @"datumHash" #))
|
||||
|
|
@ -464,7 +457,7 @@ stakeValidator stake =
|
|||
|
||||
newStakedAmount <- pletC $ oldStakedAmount + delta
|
||||
|
||||
pguardC "New staked amount shoudl be greater than or equal to 0" $
|
||||
pguardC "New staked amount should be greater than or equal to 0" $
|
||||
zero #<= newStakedAmount
|
||||
|
||||
let expectedDatum =
|
||||
|
|
|
|||
108
bench.csv
108
bench.csv
|
|
@ -5,60 +5,60 @@ Agora/Effects/Treasury Withdrawal Effect/effect/Mixed Assets,456007605,1104500,3
|
|||
Agora/Effects/Governor Mutation Effect/validator/valid new governor datum/governor validator should pass,87839169,243032,8561
|
||||
Agora/Effects/Governor Mutation Effect/validator/valid new governor datum/effect validator should pass,106082031,292993,3609
|
||||
Agora/Stake/policy/stakeCreation,50939580,148729,2387
|
||||
Agora/Stake/validator/stakeDepositWithdraw deposit,180222751,492217,5003
|
||||
Agora/Stake/validator/stakeDepositWithdraw withdraw,180222751,492217,4991
|
||||
Agora/Stake/validator/stakeDepositWithdraw deposit,150745141,416137,4995
|
||||
Agora/Stake/validator/stakeDepositWithdraw withdraw,150745141,416137,4983
|
||||
Agora/Proposal/policy/proposalCreation,23140177,69194,1515
|
||||
Agora/Proposal/validator/cosignature/legal/with 1 cosigners/propsoal,237484909,663370,8471
|
||||
Agora/Proposal/validator/cosignature/legal/with 1 cosigners/stake,123296365,319226,5470
|
||||
Agora/Proposal/validator/cosignature/legal/with 5 cosigners/propsoal,675336848,1882805,11101
|
||||
Agora/Proposal/validator/cosignature/legal/with 5 cosigners/stake,554091553,1461634,7980
|
||||
Agora/Proposal/validator/cosignature/legal/with 10 cosigners/propsoal,1336993992,3667352,14389
|
||||
Agora/Proposal/validator/cosignature/legal/with 10 cosigners/stake,1102063894,2914419,11117
|
||||
Agora/Proposal/validator/cosignature/illegal/duplicate cosigners/stake,123296365,319226,5470
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: VotingReady/stake,123296365,319226,5470
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: Locked/stake,123296365,319226,5470
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: Finished/stake,123296365,319226,5470
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: VotingReady/stake,554091553,1461634,7980
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: Locked/stake,554091553,1461634,7980
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: Finished/stake,554091553,1461634,7980
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: VotingReady/stake,1102063894,2914419,11117
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: Locked/stake,1102063894,2914419,11117
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: Finished/stake,1102063894,2914419,11117
|
||||
Agora/Proposal/validator/voting/legal/propsoal,247594094,689025,8443
|
||||
Agora/Proposal/validator/voting/legal/stake,141390725,374830,5489
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/legal/to next state/propsoal,222990625,630700,8426
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/legal/to next state/stake,123296365,319226,5467
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/legal/to failed state/propsoal,217935933,619979,8428
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/legal/to failed state/stake,123296365,319226,5469
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/illegal/insufficient cosigns/stake,117222929,305504,5397
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/legal/to next state/propsoal,600833052,1725797,11249
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/legal/to next state/stake,526604275,1381680,8170
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/legal/to failed state/propsoal,240305281,682043,8789
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/legal/to failed state/stake,123296365,319226,5710
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/illegal/insufficient cosigns/stake,445454241,1167344,7819
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/legal/to next state/propsoal,1164574757,3363392,14778
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/legal/to next state/stake,1154814568,3068129,11548
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/legal/to failed state/propsoal,268266966,759623,9242
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/legal/to failed state/stake,123296365,319226,6012
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/illegal/insufficient cosigns/stake,1024215053,2732615,10845
|
||||
Agora/Proposal/validator/advancing/legal/advance to next state/from: VotingReady/propsoal,251396469,709467,8435
|
||||
Agora/Proposal/validator/advancing/legal/advance to next state/from: VotingReady/stake,123296365,319226,5474
|
||||
Agora/Proposal/validator/advancing/legal/advance to next state/from: Locked/propsoal,240157360,676636,8435
|
||||
Agora/Proposal/validator/advancing/legal/advance to next state/from: Locked/stake,123296365,319226,5474
|
||||
Agora/Proposal/validator/advancing/legal/advance to failed state/from: VotingReady/propsoal,237329915,670626,8429
|
||||
Agora/Proposal/validator/advancing/legal/advance to failed state/from: VotingReady/stake,123296365,319226,5470
|
||||
Agora/Proposal/validator/advancing/legal/advance to failed state/from: Locked/propsoal,238460893,673030,8429
|
||||
Agora/Proposal/validator/advancing/legal/advance to failed state/from: Locked/stake,123296365,319226,5470
|
||||
Agora/Proposal/validator/advancing/illegal/insufficient votes/stake,123296365,319226,5470
|
||||
Agora/Proposal/validator/advancing/illegal/initial state is Finished/stake,123296365,319226,5462
|
||||
"Agora/Proposal/validator/unlocking/legal/1 proposals, voter, unlock stake + retract votes, VotingReady",245987595,688711,8403
|
||||
"Agora/Proposal/validator/unlocking/legal/1 proposals, creator, unlock stake, Finished",215263333,612711,8405
|
||||
"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/1 proposals, voter, unlock stake, Finished",212560614,604622,8407
|
||||
"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/1 proposals, voter, unlock stake, Locked",212560614,604622,8407
|
||||
"Agora/Proposal/validator/unlocking/legal/42 proposals, voter, unlock stake + retract votes, VotingReady",1775652167,5199490,29511
|
||||
"Agora/Proposal/validator/unlocking/legal/42 proposals, creator, unlock stake, Finished",1448293766,4317963,29695
|
||||
"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/42 proposals, voter, unlock stake, Finished",1340653392,3978430,29679
|
||||
"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/42 proposals, voter, unlock stake, Locked",1340653392,3978430,29679
|
||||
Agora/Proposal/validator/cosignature/legal/with 1 cosigners/propsoal,235408912,657765,8097
|
||||
Agora/Proposal/validator/cosignature/legal/with 1 cosigners/stake,125665131,316762,5462
|
||||
Agora/Proposal/validator/cosignature/legal/with 5 cosigners/propsoal,680441047,1897008,10727
|
||||
Agora/Proposal/validator/cosignature/legal/with 5 cosigners/stake,576106975,1490610,7972
|
||||
Agora/Proposal/validator/cosignature/legal/with 10 cosigners/propsoal,1351073436,3706315,14015
|
||||
Agora/Proposal/validator/cosignature/legal/with 10 cosigners/stake,1148637636,2982695,11109
|
||||
Agora/Proposal/validator/cosignature/illegal/duplicate cosigners/stake,125665131,316762,5462
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: VotingReady/stake,125665131,316762,5462
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: Locked/stake,125665131,316762,5462
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 1 cosigners/status: Finished/stake,125665131,316762,5462
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: VotingReady/stake,576106975,1490610,7972
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: Locked/stake,576106975,1490610,7972
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 5 cosigners/status: Finished/stake,576106975,1490610,7972
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: VotingReady/stake,1148637636,2982695,11109
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: Locked/stake,1148637636,2982695,11109
|
||||
Agora/Proposal/validator/cosignature/illegal/proposal status not Draft/with 10 cosigners/status: Finished/stake,1148637636,2982695,11109
|
||||
Agora/Proposal/validator/voting/legal/propsoal,246896882,688919,8069
|
||||
Agora/Proposal/validator/voting/legal/stake,141234659,368136,5481
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/legal/to next state/propsoal,222376736,631090,8052
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/legal/to next state/stake,125665131,316762,5459
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/legal/to failed state/propsoal,217322044,620369,8054
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/legal/to failed state/stake,125665131,316762,5461
|
||||
Agora/Proposal/validator/advancing/from draft/with 1 cosigner(s)/illegal/insufficient cosigns/stake,118020743,304972,5389
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/legal/to next state/propsoal,614587307,1766683,10875
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/legal/to next state/stake,548619697,1410656,8162
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/legal/to failed state/propsoal,239691392,682433,8415
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/legal/to failed state/stake,125665131,316762,5702
|
||||
Agora/Proposal/validator/advancing/from draft/with 5 cosigner(s)/illegal/insufficient cosigns/stake,446252055,1166812,7811
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/legal/to next state/propsoal,1196289192,3454898,14404
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/legal/to next state/stake,1201388310,3136405,11540
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/legal/to failed state/propsoal,267653077,760013,8868
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/legal/to failed state/stake,125665131,316762,6004
|
||||
Agora/Proposal/validator/advancing/from draft/with 10 cosigner(s)/illegal/insufficient cosigns/stake,1025012867,2732083,10837
|
||||
Agora/Proposal/validator/advancing/legal/advance to next state/from: VotingReady/propsoal,250229153,709227,8061
|
||||
Agora/Proposal/validator/advancing/legal/advance to next state/from: VotingReady/stake,125665131,316762,5466
|
||||
Agora/Proposal/validator/advancing/legal/advance to next state/from: Locked/propsoal,238990044,676396,8061
|
||||
Agora/Proposal/validator/advancing/legal/advance to next state/from: Locked/stake,125665131,316762,5466
|
||||
Agora/Proposal/validator/advancing/legal/advance to failed state/from: VotingReady/propsoal,236162599,670386,8055
|
||||
Agora/Proposal/validator/advancing/legal/advance to failed state/from: VotingReady/stake,125665131,316762,5462
|
||||
Agora/Proposal/validator/advancing/legal/advance to failed state/from: Locked/propsoal,237293577,672790,8055
|
||||
Agora/Proposal/validator/advancing/legal/advance to failed state/from: Locked/stake,125665131,316762,5462
|
||||
Agora/Proposal/validator/advancing/illegal/insufficient votes/stake,125665131,316762,5462
|
||||
Agora/Proposal/validator/advancing/illegal/initial state is Finished/stake,125665131,316762,5454
|
||||
"Agora/Proposal/validator/unlocking/legal/1 proposals, voter, unlock stake + retract votes, VotingReady",245855872,689807,8029
|
||||
"Agora/Proposal/validator/unlocking/legal/1 proposals, creator, unlock stake, Finished",215131610,613807,8031
|
||||
"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/1 proposals, voter, unlock stake, Finished",212428891,605718,8033
|
||||
"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/1 proposals, voter, unlock stake, Locked",212428891,605718,8033
|
||||
"Agora/Proposal/validator/unlocking/legal/42 proposals, voter, unlock stake + retract votes, VotingReady",1775520444,5200586,29137
|
||||
"Agora/Proposal/validator/unlocking/legal/42 proposals, creator, unlock stake, Finished",1448162043,4319059,29321
|
||||
"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/42 proposals, voter, unlock stake, Finished",1340521669,3979526,29305
|
||||
"Agora/Proposal/validator/unlocking/legal/voter unlocks stake after voting/42 proposals, voter, unlock stake, Locked",1340521669,3979526,29305
|
||||
Agora/AuthorityToken/singleAuthorityTokenBurned/Correct simple,21017788,55883,806
|
||||
Agora/AuthorityToken/singleAuthorityTokenBurned/Correct many inputs,33204186,88241,900
|
||||
Agora/Treasury/Validator/Positive/Allows for effect changes,31556709,81546,1452
|
||||
|
|
@ -66,5 +66,5 @@ Agora/AuthorityToken/singleAuthorityTokenBurned/Correct simple,21017788,55883,80
|
|||
Agora/AuthorityToken/singleAuthorityTokenBurned/Correct many inputs,33204186,88241,900
|
||||
Agora/Governor/policy/GST minting,51007235,144191,2034
|
||||
Agora/Governor/validator/proposal creation,309689999,834675,9064
|
||||
Agora/Governor/validator/GATs minting,421016677,1141838,9187
|
||||
Agora/Governor/validator/GATs minting,418560845,1137908,9187
|
||||
Agora/Governor/validator/mutate governor state,88986020,248491,8662
|
||||
|
|
|
|||
|
Loading…
Add table
Add a link
Reference in a new issue