fix tests; add negative tests for unlocking in cooldown

This commit is contained in:
Hongrui Fang 2022-11-14 20:42:52 +08:00
parent 07f6f1e04d
commit 688ed1ef02
11 changed files with 124 additions and 50 deletions

View file

@ -40,7 +40,8 @@ import Agora.Proposal.Time (
)
import Agora.SafeMoney (GTTag)
import Agora.Stake (
ProposalLock (Cosigned, Created),
ProposalAction (Cosigned, Created),
ProposalLock (ProposalLock),
StakeDatum (..),
StakeRedeemer (PermitVote),
)
@ -196,7 +197,7 @@ mkStakeInputDatum ps =
amount = mkStakeAmount sps.gtAmount
owner = mkStakeOwner sps.stakeOwner
locks = case sps.stakeOwner of
Creator -> [Created defProposalId]
Creator -> [ProposalLock defProposalId Created]
_ -> []
in StakeDatum
{ stakedAmount = amount
@ -212,7 +213,7 @@ mkStakeOuputDatum ps =
locks =
if sps.dontUpdateLocks
then inpDatum.lockedBy
else Cosigned defProposalId : inpDatum.lockedBy
else ProposalLock defProposalId Cosigned : inpDatum.lockedBy
in inpDatum {lockedBy = locks}
stakeRedeemer :: StakeRedeemer

View file

@ -47,7 +47,8 @@ import Agora.Proposal.Time (
)
import Agora.SafeMoney (GTTag)
import Agora.Stake (
ProposalLock (..),
ProposalAction (Created, Voted),
ProposalLock (ProposalLock),
StakeDatum (..),
StakeRedeemer (PermitVote),
)
@ -160,7 +161,7 @@ alteredStakeOwner = PubKeyCredential signer2
-- | Locks the stake that the input stake already has.
defLocks :: [ProposalLock]
defLocks = [Created (ProposalId 0)]
defLocks = [ProposalLock (ProposalId 0) Created]
-- | The effect of the newly created proposal.
defEffects :: StrictMap.Map ResultTag ProposalEffectGroup
@ -207,7 +208,7 @@ mkStakeInputDatum ps =
let locks =
if ps.createdMoreThanMaximumProposals
then
Created . ProposalId
flip ProposalLock Created . ProposalId
<$> take
(fromInteger maxProposalPerStake)
[1 ..]
@ -226,10 +227,10 @@ mkStakeOutputDatum ps =
newLocks =
if ps.invalidNewLocks
then
[ Voted thisProposalId (ResultTag 0)
, Voted thisProposalId (ResultTag 1)
[ ProposalLock thisProposalId $ Voted (ResultTag 0) 100
, ProposalLock thisProposalId $ Voted (ResultTag 1) 100
]
else [Created thisProposalId]
else [ProposalLock thisProposalId Created]
locks = newLocks <> inputDatum.lockedBy
newOwner = mkOwner ps
in inputDatum

View file

@ -20,9 +20,10 @@ import Agora.Proposal.Time (
)
import Agora.SafeMoney (GTTag)
import Agora.Stake (
ProposalLock (
ProposalAction (
Voted
),
ProposalLock (ProposalLock),
StakeDatum (..),
StakeRedeemer (PermitVote, RetractVotes),
)
@ -128,8 +129,19 @@ mkStakeInputOutputDatums op =
allStakes = take 10 $ firstStake : otherStakes
createdAt = (def :: ProposalTimingConfig).votingTime - 1
stakeWithLock =
(\stake -> stake {lockedBy = [Voted defProposalId defResultTag]})
( \stake ->
stake
{ lockedBy =
[ ProposalLock defProposalId $
Voted
defResultTag
createdAt
]
}
)
<$> allStakes
in wrap op (,) allStakes stakeWithLock

View file

@ -28,6 +28,7 @@ module Sample.Proposal.Unlock (
mkCreatorRetractVotes,
mkChangeOutputStakeValue,
mkUseFakeStakes,
mkDisrespectCooldown,
) where
--------------------------------------------------------------------------------
@ -42,13 +43,18 @@ import Agora.Proposal (
ProposalVotes (..),
ResultTag (..),
)
import Agora.Proposal.Time (ProposalStartingTime (ProposalStartingTime), ProposalTimingConfig (..))
import Agora.Proposal.Time (
ProposalStartingTime (ProposalStartingTime),
ProposalTimingConfig (..),
)
import Agora.SafeMoney (GTTag)
import Agora.Stake (
ProposalAction (Created, Voted),
ProposalLock (..),
StakeDatum (..),
StakeRedeemer (RetractVotes),
)
import Data.Coerce (coerce)
import Data.Default.Class (Default (def))
import Data.Map.Strict qualified as StrictMap
import Data.Tagged (Tagged, untag)
@ -70,6 +76,7 @@ import Plutarch.Extra.ScriptContext (validatorHashToTokenName)
import PlutusLedgerApi.V1.Value qualified as Value
import PlutusLedgerApi.V2 (
Credential (PubKeyCredential),
POSIXTime,
PubKeyHash,
TxOutRef (..),
)
@ -142,7 +149,7 @@ data ParameterBundle = ParameterBundle
data SignedBy = Owner | Delegatee | Unknown
data TimeRange = WhileVoting | AfterVoting
data TimeRange = WhileVoting {offset :: POSIXTime} | AfterVoting
data TransactionParameters = TransactionParameters
{ signedBy :: SignedBy
@ -177,6 +184,7 @@ data StakeParameters = StakeParameters
, removeCreatorLock :: Bool
, alterOutputValue :: Bool
, sstOwner :: SSTOwner
, votingLockCreatedAt :: POSIXTime
}
data Validity = Validity
@ -203,14 +211,20 @@ mkStakeInputDatum ps =
where
stakeLocks = mkStakeLocks' ps.stakeRole
mkStakeLocks' Voter = [Voted defProposalId defVoteFor]
mkStakeLocks' Creator = [Created defProposalId]
mkStakeLocks' Voter =
[ ProposalLock defProposalId $
Voted defVoteFor ps.votingLockCreatedAt
]
mkStakeLocks' Creator = [ProposalLock defProposalId Created]
mkStakeLocks' Both = mkStakeLocks' Voter <> mkStakeLocks' Creator
mkStakeLocks' Irrelevant =
let ProposalId pid = defProposalId
ResultTag vid = defVoteFor
in [ Voted (ProposalId $ pid + 1) (ResultTag $ vid + 1)
, Created (ProposalId $ pid + 1)
in [ ProposalLock (ProposalId $ pid + 1) $
Voted
(ResultTag $ vid + 1)
ps.votingLockCreatedAt
, ProposalLock (ProposalId $ pid + 1) Created
]
--------------------------------------------------------------------------------
@ -292,14 +306,13 @@ unlock ps = builder
stakeInputDatum = mkStakeInputDatum ps.stakeParameters
-- TODO respect timing
removeLocks v c =
filter $
not
. ( \case
Created pid -> c && pid == defProposalId
Cosigned pid -> c && pid == defProposalId
Voted pid _ -> v && pid == defProposalId
)
filter $ \(ProposalLock pid action) ->
pid == defProposalId
&& case action of
Voted _ _ -> v
_ -> c
stakeOutputDatum =
stakeInputDatum
@ -355,9 +368,14 @@ unlock ps = builder
ProposalStartingTime s = defStartingTime
time = case ps.transactionParameters.timeRange of
WhileVoting ->
let lb = s + (def :: ProposalTimingConfig).draftTime
ub = lb + (def :: ProposalTimingConfig).votingTime
WhileVoting offset ->
let lb =
ps.stakeParameters.votingLockCreatedAt
+ offset
ub =
s
+ (def :: ProposalTimingConfig).draftTime
+ (def :: ProposalTimingConfig).votingTime
in closedBoundedInterval (lb + 1) (ub - 1)
AfterVoting ->
let lb =
@ -429,12 +447,21 @@ mkValidVoterRetractVotes i =
, removeCreatorLock = False
, alterOutputValue = False
, sstOwner = StakeValidator
, votingLockCreatedAt =
coerce defStartingTime
+ (def :: ProposalTimingConfig).draftTime
+ 1
}
, transactionParameters =
TransactionParameters
{ signedBy = Owner
, timeRange =
WhileVoting
{ offset =
coerce
(def :: ProposalTimingConfig).minStakeVotingTime
+ 5
}
}
}
@ -544,10 +571,6 @@ mkCreatorRetractVotes i =
template.stakeParameters
{ stakeRole = Creator
}
, transactionParameters =
template.transactionParameters
{ timeRange = WhileVoting
}
}
mkChangeOutputStakeValue :: Integer -> ParameterBundle
@ -569,3 +592,19 @@ mkUseFakeStakes i =
{ sstOwner = Attacker
}
}
mkDisrespectCooldown :: Integer -> ParameterBundle
mkDisrespectCooldown i =
let template = mkValidVoterCreatorRetractVotes i
in template
{ transactionParameters =
template.transactionParameters
{ timeRange =
WhileVoting
{ offset =
coerce
(def :: ProposalTimingConfig).minStakeVotingTime
- 5
}
}
}

View file

@ -46,7 +46,8 @@ import Agora.Proposal.Time (
)
import Agora.SafeMoney (GTTag)
import Agora.Stake (
ProposalLock (Voted),
ProposalAction (Voted),
ProposalLock (ProposalLock),
StakeDatum (..),
StakeRedeemer (Destroy, PermitVote),
)
@ -68,7 +69,7 @@ import Plutarch.Context (
withValue,
)
import Plutarch.Extra.AssetClass (adaClass, assetClassValue)
import PlutusLedgerApi.V2 (Credential (PubKeyCredential), PubKeyHash)
import PlutusLedgerApi.V2 (Credential (PubKeyCredential), Interval, POSIXTime, PubKeyHash)
import PlutusLedgerApi.V2.Contexts (TxOutRef (TxOutRef))
import Sample.Proposal.Shared (proposalTxRef)
import Sample.Shared (
@ -145,6 +146,24 @@ delegatee = pubKeyHashes !! 1
unknownSig :: PubKeyHash
unknownSig = pubKeyHashes !! 2
validTimeRangeLowerBound :: POSIXTime
validTimeRangeLowerBound =
0
+ (def :: ProposalTimingConfig).draftTime
+ 1
validTimeRangeUpperBound :: POSIXTime
validTimeRangeUpperBound =
validTimeRangeLowerBound
+ (def :: ProposalTimingConfig).votingTime
- 2
validTimeRange :: Interval POSIXTime
validTimeRange =
closedBoundedInterval
validTimeRangeLowerBound
validTimeRangeUpperBound
--------------------------------------------------------------------------------
initialVotes :: StrictMap.Map ResultTag Integer
@ -197,8 +216,8 @@ mkStakeInputDatum params =
, owner = PubKeyCredential stakeOwner
, delegatedTo = Just (PubKeyCredential delegatee)
, lockedBy =
[ Voted (ProposalId 0) (ResultTag 0)
, Voted (ProposalId 1) (ResultTag 2)
[ ProposalLock (ProposalId 0) $ Voted (ResultTag 0) 100
, ProposalLock (ProposalId 1) $ Voted (ResultTag 2) 200
]
}
@ -227,9 +246,11 @@ vote params =
<> minAda
newLock =
Voted
ProposalLock
proposalInputDatum.proposalId
params.voteParameters.voteFor
$ Voted
params.voteParameters.voteFor
validTimeRangeUpperBound
updatedLocks =
if params.stakeParameters.stakeOutputParameters.dontAddNewLock
@ -357,13 +378,6 @@ vote params =
--------------------------------------------------------------------------
validTimeRange =
closedBoundedInterval
((def :: ProposalTimingConfig).draftTime + 1)
((def :: ProposalTimingConfig).votingTime - 1)
--------------------------------------------------------------------------
miscBuilder :: b
miscBuilder =
mconcat