Merge pull request #157 from Liqwid-Labs/connor/effect-ref-script
Store `ScriptHash`es in the effects
This commit is contained in:
commit
367a630cef
12 changed files with 897 additions and 574 deletions
|
|
@ -44,6 +44,7 @@ import Agora.Governor (
|
||||||
)
|
)
|
||||||
import Agora.Proposal (
|
import Agora.Proposal (
|
||||||
ProposalDatum (..),
|
ProposalDatum (..),
|
||||||
|
ProposalEffectGroup,
|
||||||
ProposalId (ProposalId),
|
ProposalId (ProposalId),
|
||||||
ProposalRedeemer (AdvanceProposal),
|
ProposalRedeemer (AdvanceProposal),
|
||||||
ProposalStatus (..),
|
ProposalStatus (..),
|
||||||
|
|
@ -67,10 +68,11 @@ import Agora.Stake (
|
||||||
StakeRedeemer (WitnessStake),
|
StakeRedeemer (WitnessStake),
|
||||||
)
|
)
|
||||||
import Agora.Utils (validatorHashToTokenName)
|
import Agora.Utils (validatorHashToTokenName)
|
||||||
|
import Control.Applicative (liftA2)
|
||||||
import Control.Monad.State (execState, modify, when)
|
import Control.Monad.State (execState, modify, when)
|
||||||
import Data.Default (def)
|
import Data.Default (def)
|
||||||
import Data.List (sort)
|
import Data.List (singleton, sort)
|
||||||
import Data.Maybe (catMaybes, fromJust)
|
import Data.Maybe (fromJust)
|
||||||
import Data.Tagged (Tagged (..), untag)
|
import Data.Tagged (Tagged (..), untag)
|
||||||
import Plutarch.Context (
|
import Plutarch.Context (
|
||||||
input,
|
input,
|
||||||
|
|
@ -81,6 +83,7 @@ import Plutarch.Context (
|
||||||
timeRange,
|
timeRange,
|
||||||
withDatum,
|
withDatum,
|
||||||
withRef,
|
withRef,
|
||||||
|
withReferenceScript,
|
||||||
withValue,
|
withValue,
|
||||||
)
|
)
|
||||||
import Plutarch.Lift (PLifted, PUnsafeLiftDecl)
|
import Plutarch.Lift (PLifted, PUnsafeLiftDecl)
|
||||||
|
|
@ -91,6 +94,7 @@ import PlutusLedgerApi.V2 (
|
||||||
POSIXTime,
|
POSIXTime,
|
||||||
POSIXTimeRange,
|
POSIXTimeRange,
|
||||||
PubKeyHash,
|
PubKeyHash,
|
||||||
|
ScriptHash,
|
||||||
TxOutRef (TxOutRef),
|
TxOutRef (TxOutRef),
|
||||||
ValidatorHash,
|
ValidatorHash,
|
||||||
)
|
)
|
||||||
|
|
@ -127,6 +131,7 @@ import Test.Util (
|
||||||
mkMinting,
|
mkMinting,
|
||||||
mkSpending,
|
mkSpending,
|
||||||
pubKeyHashes,
|
pubKeyHashes,
|
||||||
|
scriptHashes,
|
||||||
sortValue,
|
sortValue,
|
||||||
toDatum,
|
toDatum,
|
||||||
updateMap,
|
updateMap,
|
||||||
|
|
@ -144,7 +149,7 @@ data ParameterBundle = ParameterBundle
|
||||||
, governorParameters :: Maybe GovernorParameters
|
, governorParameters :: Maybe GovernorParameters
|
||||||
-- ^ Parameters related to GST moving. If set to 'Nothing', the GST won't
|
-- ^ Parameters related to GST moving. If set to 'Nothing', the GST won't
|
||||||
-- be moved, thus the governor validator won't be run in 'mkTestTree'.
|
-- be moved, thus the governor validator won't be run in 'mkTestTree'.
|
||||||
, authorityTokenParameters :: Maybe AuthorityTokenParameters
|
, authorityTokenParameters :: [AuthorityTokenParameters]
|
||||||
-- ^ Parameters related to GAT minting. If set to 'Nothing', no GAT will
|
-- ^ Parameters related to GAT minting. If set to 'Nothing', no GAT will
|
||||||
-- be minted, thus the GAT minting policy won't be run in 'mkTestTree'.
|
-- be minted, thus the GAT minting policy won't be run in 'mkTestTree'.
|
||||||
, transactionTimeRange :: POSIXTimeRange
|
, transactionTimeRange :: POSIXTimeRange
|
||||||
|
|
@ -171,10 +176,12 @@ data AuthorityTokenParameters = forall
|
||||||
, PIsData pdatum
|
, PIsData pdatum
|
||||||
) =>
|
) =>
|
||||||
AuthorityTokenParameters
|
AuthorityTokenParameters
|
||||||
{ mintGATsFor :: [ValidatorHash]
|
{ mintGATsFor :: ValidatorHash
|
||||||
-- ^ GATs will be minted and sent to the given group of effects.
|
-- ^ GATs will be minted and sent to the given group of effects.
|
||||||
, carryDatum :: Maybe datum
|
, carryDatum :: Maybe datum
|
||||||
-- ^ The datum that GAT UTxOs will be carrying.
|
-- ^ The datum that GAT UTxOs will be carrying.
|
||||||
|
, carryRefScript :: Maybe ScriptHash
|
||||||
|
-- ^ The reference script that GAT UTxOs will be carrying.
|
||||||
, invalidTokenName :: Bool
|
, invalidTokenName :: Bool
|
||||||
-- ^ If set to true, GATs won't be tagged by their corresponding effect
|
-- ^ If set to true, GATs won't be tagged by their corresponding effect
|
||||||
-- hashes.
|
-- hashes.
|
||||||
|
|
@ -193,7 +200,7 @@ data ProposalParameters = ProposalParameters
|
||||||
-- ^ What status is the proposal advancing from
|
-- ^ What status is the proposal advancing from
|
||||||
, toStatus :: ProposalStatus
|
, toStatus :: ProposalStatus
|
||||||
-- ^ What status is the proposal advancing to
|
-- ^ What status is the proposal advancing to
|
||||||
, effectList :: [AssocMap.Map ValidatorHash DatumHash]
|
, effectList :: [ProposalEffectGroup]
|
||||||
-- ^ The effect groups of the proposal. A neutral effect group is not
|
-- ^ The effect groups of the proposal. A neutral effect group is not
|
||||||
-- required here.
|
-- required here.
|
||||||
, winnerAndVotes :: Maybe (Winner, Integer)
|
, winnerAndVotes :: Maybe (Winner, Integer)
|
||||||
|
|
@ -244,7 +251,7 @@ outcomeIdxToResultTag = ResultTag . fromIntegral
|
||||||
-- | Add a neutral effect group and allocate result tags for the effect groups.
|
-- | Add a neutral effect group and allocate result tags for the effect groups.
|
||||||
mkEffects ::
|
mkEffects ::
|
||||||
ProposalParameters ->
|
ProposalParameters ->
|
||||||
AssocMap.Map ResultTag (AssocMap.Map ValidatorHash DatumHash)
|
AssocMap.Map ResultTag ProposalEffectGroup
|
||||||
mkEffects ps =
|
mkEffects ps =
|
||||||
let resultTags = map ResultTag [0 ..]
|
let resultTags = map ResultTag [0 ..]
|
||||||
neutralEffect = AssocMap.empty
|
neutralEffect = AssocMap.empty
|
||||||
|
|
@ -492,27 +499,24 @@ mkAuthorityTokenBuilder ::
|
||||||
CombinableBuilder b =>
|
CombinableBuilder b =>
|
||||||
AuthorityTokenParameters ->
|
AuthorityTokenParameters ->
|
||||||
b
|
b
|
||||||
mkAuthorityTokenBuilder (AuthorityTokenParameters es mdt invalidTokenName) =
|
mkAuthorityTokenBuilder ps@AuthorityTokenParameters {carryDatum} =
|
||||||
foldMap perEffect es
|
let tn =
|
||||||
where
|
if ps.invalidTokenName
|
||||||
perEffect :: ValidatorHash -> b
|
then ""
|
||||||
perEffect vh =
|
else validatorHashToTokenName ps.mintGATsFor
|
||||||
let tn =
|
ac = AssetClass (authorityTokenSymbol, tn)
|
||||||
if invalidTokenName
|
minted = Value.assetClassValue ac 1
|
||||||
then ""
|
value = sortValue $ minAda <> minted
|
||||||
else validatorHashToTokenName vh
|
in mconcat
|
||||||
ac = AssetClass (authorityTokenSymbol, tn)
|
[ mint minted
|
||||||
minted = Value.assetClassValue ac 1
|
, output $
|
||||||
value = sortValue $ minAda <> minted
|
mconcat
|
||||||
in mconcat
|
[ script ps.mintGATsFor
|
||||||
[ mint minted
|
, maybe mempty withDatum carryDatum
|
||||||
, output $
|
, maybe mempty withReferenceScript ps.carryRefScript
|
||||||
mconcat
|
, withValue value
|
||||||
[ script vh
|
]
|
||||||
, maybe mempty withDatum mdt
|
]
|
||||||
, withValue value
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
-- | The redeemer used while running the authority token policy.
|
-- | The redeemer used while running the authority token policy.
|
||||||
authorityTokenRedeemer :: ()
|
authorityTokenRedeemer :: ()
|
||||||
|
|
@ -532,7 +536,7 @@ advance pb =
|
||||||
[ mkProposalBuilder pb.proposalParameters
|
[ mkProposalBuilder pb.proposalParameters
|
||||||
, mkStakeBuilder pb.stakeParameters
|
, mkStakeBuilder pb.stakeParameters
|
||||||
, mkBuilderMaybe mkGovernorBuilder pb.governorParameters
|
, mkBuilderMaybe mkGovernorBuilder pb.governorParameters
|
||||||
, mkBuilderMaybe mkAuthorityTokenBuilder pb.authorityTokenParameters
|
, foldMap mkAuthorityTokenBuilder pb.authorityTokenParameters
|
||||||
, timeRange pb.transactionTimeRange
|
, timeRange pb.transactionTimeRange
|
||||||
, maybe mempty signedWith pb.extraSignature
|
, maybe mempty signedWith pb.extraSignature
|
||||||
]
|
]
|
||||||
|
|
@ -548,14 +552,13 @@ mkTestTree ::
|
||||||
Validity ->
|
Validity ->
|
||||||
SpecificationTree
|
SpecificationTree
|
||||||
mkTestTree name pb val =
|
mkTestTree name pb val =
|
||||||
group name $ catMaybes [proposal, stake, governor, authority]
|
group name $ mconcat [proposal, stake, governor, authority]
|
||||||
where
|
where
|
||||||
spend = mkSpending advance pb
|
spend = mkSpending advance pb
|
||||||
mint = mkMinting advance pb
|
|
||||||
|
|
||||||
proposal =
|
proposal =
|
||||||
let proposalInputDatum = mkProposalInputDatum pb.proposalParameters
|
let proposalInputDatum = mkProposalInputDatum pb.proposalParameters
|
||||||
in Just $
|
in singleton $
|
||||||
testValidator
|
testValidator
|
||||||
val.forProposalValidator
|
val.forProposalValidator
|
||||||
"proposal"
|
"proposal"
|
||||||
|
|
@ -566,7 +569,7 @@ mkTestTree name pb val =
|
||||||
|
|
||||||
stake =
|
stake =
|
||||||
let idx = 0
|
let idx = 0
|
||||||
in Just $
|
in singleton $
|
||||||
testValidator
|
testValidator
|
||||||
val.forStakeValidator
|
val.forStakeValidator
|
||||||
"stake"
|
"stake"
|
||||||
|
|
@ -577,23 +580,27 @@ mkTestTree name pb val =
|
||||||
)
|
)
|
||||||
|
|
||||||
governor =
|
governor =
|
||||||
testValidator
|
maybe [] singleton $
|
||||||
(fromJust val.forGovernorValidator)
|
testValidator
|
||||||
"governor"
|
(fromJust val.forGovernorValidator)
|
||||||
agoraScripts.compiledGovernorValidator
|
"governor"
|
||||||
governorInputDatum
|
agoraScripts.compiledGovernorValidator
|
||||||
governorRedeemer
|
governorInputDatum
|
||||||
(spend governorRef)
|
governorRedeemer
|
||||||
<$ pb.governorParameters
|
(spend governorRef)
|
||||||
|
<$ pb.governorParameters
|
||||||
|
|
||||||
authority =
|
authority = case pb.authorityTokenParameters of
|
||||||
testPolicy
|
[] -> []
|
||||||
(fromJust val.forAuthorityTokenPolicy)
|
_ ->
|
||||||
"authority"
|
singleton
|
||||||
agoraScripts.compiledAuthorityTokenPolicy
|
( testPolicy
|
||||||
authorityTokenRedeemer
|
(fromJust val.forAuthorityTokenPolicy)
|
||||||
(mint authorityTokenSymbol)
|
"authority"
|
||||||
<$ (pb.authorityTokenParameters)
|
agoraScripts.compiledAuthorityTokenPolicy
|
||||||
|
authorityTokenRedeemer
|
||||||
|
(mkMinting advance pb authorityTokenSymbol)
|
||||||
|
)
|
||||||
|
|
||||||
{- | Create a test tree that runs a bunch of parameter bundles. These bundles
|
{- | Create a test tree that runs a bunch of parameter bundles. These bundles
|
||||||
should have the same validity.
|
should have the same validity.
|
||||||
|
|
@ -725,14 +732,26 @@ dummyDatumHash :: DatumHash
|
||||||
dummyDatumHash = datumHash $ toDatum dummyDatum
|
dummyDatumHash = datumHash $ toDatum dummyDatum
|
||||||
|
|
||||||
-- | Create given number of effect groups. Each group will have 3 effects.
|
-- | Create given number of effect groups. Each group will have 3 effects.
|
||||||
mkMockEffects :: Int -> [AssocMap.Map ValidatorHash DatumHash]
|
mkMockEffects :: Bool -> Int -> [ProposalEffectGroup]
|
||||||
mkMockEffects =
|
mkMockEffects useRefScript n = effects
|
||||||
flip
|
where
|
||||||
take
|
effectsPerGroup = 3
|
||||||
( AssocMap.fromList
|
|
||||||
. flip zip (repeat dummyDatumHash)
|
mkRefScripts True = Just <$> scriptHashes
|
||||||
<$> groupsOfN 3 validatorHashes
|
mkRefScripts False = repeat Nothing
|
||||||
)
|
refScripts = mkRefScripts useRefScript
|
||||||
|
|
||||||
|
datums = repeat dummyDatumHash
|
||||||
|
|
||||||
|
effectMetadata = zip datums refScripts
|
||||||
|
effectScripts = validatorHashes
|
||||||
|
|
||||||
|
effects =
|
||||||
|
take n $
|
||||||
|
AssocMap.fromList
|
||||||
|
<$> groupsOfN
|
||||||
|
effectsPerGroup
|
||||||
|
(zip effectScripts effectMetadata)
|
||||||
|
|
||||||
numberOfVotesThatExceedsTheMinimumRequirement :: Integer
|
numberOfVotesThatExceedsTheMinimumRequirement :: Integer
|
||||||
numberOfVotesThatExceedsTheMinimumRequirement =
|
numberOfVotesThatExceedsTheMinimumRequirement =
|
||||||
|
|
@ -767,16 +786,18 @@ defaultWinnerIdx = 0
|
||||||
mkValidToNextStateBundle ::
|
mkValidToNextStateBundle ::
|
||||||
-- | Number of cosigners.
|
-- | Number of cosigners.
|
||||||
Word ->
|
Word ->
|
||||||
-- | Number of effects
|
-- | Number of effects.
|
||||||
Word ->
|
Word ->
|
||||||
|
-- | Toggle the referenc script in GAT UTXO.
|
||||||
|
Bool ->
|
||||||
-- | The initial proposal state, should not be 'Finished'.
|
-- | The initial proposal state, should not be 'Finished'.
|
||||||
ProposalStatus ->
|
ProposalStatus ->
|
||||||
ParameterBundle
|
ParameterBundle
|
||||||
mkValidToNextStateBundle _ _ Finished =
|
mkValidToNextStateBundle _ _ _ Finished =
|
||||||
error "Cannot advance from Finished"
|
error "Cannot advance from Finished"
|
||||||
mkValidToNextStateBundle nCosigners nEffects from =
|
mkValidToNextStateBundle nCosigners nEffects refScript from =
|
||||||
let next = getNextState from
|
let next = getNextState from
|
||||||
effects = mkMockEffects $ fromIntegral nEffects
|
effects = mkMockEffects refScript $ fromIntegral nEffects
|
||||||
winner = defaultWinnerIdx
|
winner = defaultWinnerIdx
|
||||||
|
|
||||||
template =
|
template =
|
||||||
|
|
@ -800,7 +821,7 @@ mkValidToNextStateBundle nCosigners nEffects from =
|
||||||
, invalidStakeOutputDatum = False
|
, invalidStakeOutputDatum = False
|
||||||
}
|
}
|
||||||
, governorParameters = Nothing
|
, governorParameters = Nothing
|
||||||
, authorityTokenParameters = Nothing
|
, authorityTokenParameters = []
|
||||||
, transactionTimeRange = mkInTimeTimeRange from
|
, transactionTimeRange = mkInTimeTimeRange from
|
||||||
, extraSignature = Just signer
|
, extraSignature = Just signer
|
||||||
}
|
}
|
||||||
|
|
@ -830,18 +851,24 @@ mkValidToNextStateBundle nCosigners nEffects from =
|
||||||
when (from == Locked) $
|
when (from == Locked) $
|
||||||
modify $ \b ->
|
modify $ \b ->
|
||||||
let aut =
|
let aut =
|
||||||
AuthorityTokenParameters
|
AssocMap.elems $
|
||||||
{ mintGATsFor = AssocMap.keys $ effects !! winner
|
AssocMap.mapWithKey
|
||||||
, carryDatum = Just dummyDatum
|
( \vh (_, refScript) ->
|
||||||
, invalidTokenName = False
|
AuthorityTokenParameters
|
||||||
}
|
{ mintGATsFor = vh
|
||||||
|
, carryDatum = Just dummyDatum
|
||||||
|
, carryRefScript = refScript
|
||||||
|
, invalidTokenName = False
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(effects !! winner)
|
||||||
gov =
|
gov =
|
||||||
GovernorParameters
|
GovernorParameters
|
||||||
{ invalidGovernorOutputDatum = False
|
{ invalidGovernorOutputDatum = False
|
||||||
}
|
}
|
||||||
in b
|
in b
|
||||||
{ governorParameters = Just gov
|
{ governorParameters = Just gov
|
||||||
, authorityTokenParameters = Just aut
|
, authorityTokenParameters = aut
|
||||||
}
|
}
|
||||||
in execState modifyTemplate template
|
in execState modifyTemplate template
|
||||||
|
|
||||||
|
|
@ -852,11 +879,10 @@ mkValidToNextStateBundles ::
|
||||||
Word ->
|
Word ->
|
||||||
[ParameterBundle]
|
[ParameterBundle]
|
||||||
mkValidToNextStateBundles nCosigners nEffects =
|
mkValidToNextStateBundles nCosigners nEffects =
|
||||||
mkValidToNextStateBundle nCosigners nEffects
|
liftA2
|
||||||
<$> [ Draft
|
(mkValidToNextStateBundle nCosigners nEffects)
|
||||||
, VotingReady
|
[True, False]
|
||||||
, Locked
|
[Draft, VotingReady, Locked]
|
||||||
]
|
|
||||||
|
|
||||||
mkValidToFailedStateBundles ::
|
mkValidToFailedStateBundles ::
|
||||||
-- | Number of cosigners
|
-- | Number of cosigners
|
||||||
|
|
@ -865,15 +891,14 @@ mkValidToFailedStateBundles ::
|
||||||
Word ->
|
Word ->
|
||||||
[ParameterBundle]
|
[ParameterBundle]
|
||||||
mkValidToFailedStateBundles nCosigners nEffects =
|
mkValidToFailedStateBundles nCosigners nEffects =
|
||||||
mkBundle
|
liftA2
|
||||||
<$> [ Draft
|
mkBundle
|
||||||
, VotingReady
|
[True, False]
|
||||||
, Locked
|
[Draft, VotingReady, Locked]
|
||||||
]
|
|
||||||
where
|
where
|
||||||
mkBundle from =
|
mkBundle refScript from =
|
||||||
let next = Finished
|
let next = Finished
|
||||||
effects = mkMockEffects $ fromIntegral nEffects
|
effects = mkMockEffects refScript $ fromIntegral nEffects
|
||||||
in ParameterBundle
|
in ParameterBundle
|
||||||
{ proposalParameters =
|
{ proposalParameters =
|
||||||
ProposalParameters
|
ProposalParameters
|
||||||
|
|
@ -894,7 +919,7 @@ mkValidToFailedStateBundles nCosigners nEffects =
|
||||||
, invalidStakeOutputDatum = False
|
, invalidStakeOutputDatum = False
|
||||||
}
|
}
|
||||||
, governorParameters = Nothing
|
, governorParameters = Nothing
|
||||||
, authorityTokenParameters = Nothing
|
, authorityTokenParameters = []
|
||||||
, transactionTimeRange = mkTooLateTimeRange from
|
, transactionTimeRange = mkTooLateTimeRange from
|
||||||
, extraSignature = Just signer
|
, extraSignature = Just signer
|
||||||
}
|
}
|
||||||
|
|
@ -908,14 +933,13 @@ mkFromFinishedBundles ::
|
||||||
Word ->
|
Word ->
|
||||||
[ParameterBundle]
|
[ParameterBundle]
|
||||||
mkFromFinishedBundles nCosigners nEffects =
|
mkFromFinishedBundles nCosigners nEffects =
|
||||||
mkBundle
|
liftA2
|
||||||
<$> [ Draft
|
mkBundle
|
||||||
, VotingReady
|
[True, False]
|
||||||
, Locked
|
[Draft, VotingReady, Locked]
|
||||||
]
|
|
||||||
where
|
where
|
||||||
mkBundle from =
|
mkBundle refScript from =
|
||||||
let template = mkValidToNextStateBundle nCosigners nEffects from
|
let template = mkValidToNextStateBundle nCosigners nEffects refScript from
|
||||||
in template
|
in template
|
||||||
{ proposalParameters =
|
{ proposalParameters =
|
||||||
template.proposalParameters
|
template.proposalParameters
|
||||||
|
|
@ -926,24 +950,26 @@ mkFromFinishedBundles nCosigners nEffects =
|
||||||
|
|
||||||
mkToNextStateTooLateBundles :: Word -> Word -> [ParameterBundle]
|
mkToNextStateTooLateBundles :: Word -> Word -> [ParameterBundle]
|
||||||
mkToNextStateTooLateBundles nCosigners nEffects =
|
mkToNextStateTooLateBundles nCosigners nEffects =
|
||||||
mkBundle
|
liftA2
|
||||||
<$> [ Draft
|
mkBundle
|
||||||
, VotingReady
|
[True, False]
|
||||||
, Locked
|
[Draft, VotingReady, Locked]
|
||||||
]
|
|
||||||
where
|
where
|
||||||
mkBundle from =
|
mkBundle refScript from =
|
||||||
let template = mkValidToNextStateBundle nCosigners nEffects from
|
let template = mkValidToNextStateBundle nCosigners nEffects refScript from
|
||||||
in template
|
in template
|
||||||
{ transactionTimeRange = mkTooLateTimeRange from
|
{ transactionTimeRange = mkTooLateTimeRange from
|
||||||
}
|
}
|
||||||
|
|
||||||
mkInvalidOutputStakeBundles :: Word -> Word -> [ParameterBundle]
|
mkInvalidOutputStakeBundles :: Word -> Word -> [ParameterBundle]
|
||||||
mkInvalidOutputStakeBundles nCosigners nEffects =
|
mkInvalidOutputStakeBundles nCosigners nEffects =
|
||||||
mkBundle <$> [Draft, VotingReady, Locked]
|
liftA2
|
||||||
|
mkBundle
|
||||||
|
[True, False]
|
||||||
|
[Draft, VotingReady, Locked]
|
||||||
where
|
where
|
||||||
mkBundle from =
|
mkBundle refScript from =
|
||||||
let template = mkValidToNextStateBundle nCosigners nEffects from
|
let template = mkValidToNextStateBundle nCosigners nEffects refScript from
|
||||||
in template
|
in template
|
||||||
{ stakeParameters =
|
{ stakeParameters =
|
||||||
template.stakeParameters
|
template.stakeParameters
|
||||||
|
|
@ -965,7 +991,7 @@ mkInsufficientCosignsBundle nCosigners nEffects =
|
||||||
insuffcientPerStakeGTs =
|
insuffcientPerStakeGTs =
|
||||||
untag (def :: ProposalThresholds).vote
|
untag (def :: ProposalThresholds).vote
|
||||||
`div` fromIntegral nCosigners - 1
|
`div` fromIntegral nCosigners - 1
|
||||||
template = mkValidToNextStateBundle nCosigners nEffects Draft
|
template = mkValidToNextStateBundle nCosigners nEffects False Draft
|
||||||
|
|
||||||
-- * From VotingReady
|
-- * From VotingReady
|
||||||
|
|
||||||
|
|
@ -986,7 +1012,7 @@ mkInsufficientVotesBundle ::
|
||||||
Word ->
|
Word ->
|
||||||
ParameterBundle
|
ParameterBundle
|
||||||
mkInsufficientVotesBundle nCosigners nEffects =
|
mkInsufficientVotesBundle nCosigners nEffects =
|
||||||
mkValidToNextStateBundle nCosigners nEffects VotingReady
|
mkValidToNextStateBundle nCosigners nEffects False VotingReady
|
||||||
`setWinnerAndVotes` Nothing
|
`setWinnerAndVotes` Nothing
|
||||||
|
|
||||||
mkAmbiguousWinnerBundle ::
|
mkAmbiguousWinnerBundle ::
|
||||||
|
|
@ -994,14 +1020,14 @@ mkAmbiguousWinnerBundle ::
|
||||||
Word ->
|
Word ->
|
||||||
ParameterBundle
|
ParameterBundle
|
||||||
mkAmbiguousWinnerBundle nCosigners nEffects =
|
mkAmbiguousWinnerBundle nCosigners nEffects =
|
||||||
mkValidToNextStateBundle nCosigners nEffects VotingReady
|
mkValidToNextStateBundle nCosigners nEffects False VotingReady
|
||||||
`setWinnerAndVotes` Just ambiguousWinnerVotes
|
`setWinnerAndVotes` Just ambiguousWinnerVotes
|
||||||
|
|
||||||
-- * From Locked
|
-- * From Locked
|
||||||
|
|
||||||
mkValidFromLockedBundle :: Word -> Word -> ParameterBundle
|
mkValidFromLockedBundle :: Word -> Word -> ParameterBundle
|
||||||
mkValidFromLockedBundle nCosigners nEffects =
|
mkValidFromLockedBundle nCosigners nEffects =
|
||||||
mkValidToNextStateBundle nCosigners nEffects Locked
|
mkValidToNextStateBundle nCosigners nEffects False Locked
|
||||||
|
|
||||||
mkMintGATsForWrongEffectsBundle ::
|
mkMintGATsForWrongEffectsBundle ::
|
||||||
Word ->
|
Word ->
|
||||||
|
|
@ -1010,17 +1036,11 @@ mkMintGATsForWrongEffectsBundle ::
|
||||||
mkMintGATsForWrongEffectsBundle nCosigners nEffects =
|
mkMintGATsForWrongEffectsBundle nCosigners nEffects =
|
||||||
template
|
template
|
||||||
{ authorityTokenParameters =
|
{ authorityTokenParameters =
|
||||||
( \aut ->
|
take 4 $
|
||||||
aut
|
zipWith
|
||||||
{ mintGATsFor =
|
(\a i -> a {mintGATsFor = validatorHashes !! i})
|
||||||
[ validatorHashes !! 1
|
template.authorityTokenParameters
|
||||||
, validatorHashes !! 3
|
[1, 3 ..]
|
||||||
, validatorHashes !! 5
|
|
||||||
, validatorHashes !! 7
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
<$> template.authorityTokenParameters
|
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
template = mkValidFromLockedBundle nCosigners nEffects
|
template = mkValidFromLockedBundle nCosigners nEffects
|
||||||
|
|
@ -1031,7 +1051,7 @@ mkNoGATMintedBundle ::
|
||||||
ParameterBundle
|
ParameterBundle
|
||||||
mkNoGATMintedBundle nCosigners nEffects =
|
mkNoGATMintedBundle nCosigners nEffects =
|
||||||
template
|
template
|
||||||
{ authorityTokenParameters = Nothing
|
{ authorityTokenParameters = []
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
template = mkValidFromLockedBundle nCosigners nEffects
|
template = mkValidFromLockedBundle nCosigners nEffects
|
||||||
|
|
@ -1059,16 +1079,19 @@ mkGATsWithWrongDatumBundle ::
|
||||||
ParameterBundle
|
ParameterBundle
|
||||||
mkGATsWithWrongDatumBundle nCosigners nEffects =
|
mkGATsWithWrongDatumBundle nCosigners nEffects =
|
||||||
template
|
template
|
||||||
{ authorityTokenParameters = Just newAut
|
{ authorityTokenParameters = newAut
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
template = mkValidFromLockedBundle nCosigners nEffects
|
template = mkValidFromLockedBundle nCosigners nEffects
|
||||||
aut = fromJust template.authorityTokenParameters
|
|
||||||
newAut =
|
newAut =
|
||||||
AuthorityTokenParameters
|
( \aut ->
|
||||||
aut.mintGATsFor
|
AuthorityTokenParameters
|
||||||
(Just (1 :: Integer))
|
aut.mintGATsFor
|
||||||
False
|
(Just (1 :: Integer))
|
||||||
|
aut.carryRefScript
|
||||||
|
False
|
||||||
|
)
|
||||||
|
<$> template.authorityTokenParameters
|
||||||
|
|
||||||
mkBadGovernorOutputDatumBundle ::
|
mkBadGovernorOutputDatumBundle ::
|
||||||
Word ->
|
Word ->
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import Agora.Governor (
|
||||||
)
|
)
|
||||||
import Agora.Proposal (
|
import Agora.Proposal (
|
||||||
ProposalDatum (..),
|
ProposalDatum (..),
|
||||||
|
ProposalEffectGroup,
|
||||||
ProposalId (ProposalId),
|
ProposalId (ProposalId),
|
||||||
ProposalStatus (..),
|
ProposalStatus (..),
|
||||||
ResultTag (ResultTag),
|
ResultTag (ResultTag),
|
||||||
|
|
@ -60,12 +61,10 @@ import Plutarch.Context (
|
||||||
)
|
)
|
||||||
import PlutusLedgerApi.V1.Value qualified as Value
|
import PlutusLedgerApi.V1.Value qualified as Value
|
||||||
import PlutusLedgerApi.V2 (
|
import PlutusLedgerApi.V2 (
|
||||||
DatumHash,
|
|
||||||
POSIXTime (POSIXTime),
|
POSIXTime (POSIXTime),
|
||||||
POSIXTimeRange,
|
POSIXTimeRange,
|
||||||
PubKeyHash,
|
PubKeyHash,
|
||||||
TxOutRef (TxOutRef),
|
TxOutRef (TxOutRef),
|
||||||
ValidatorHash,
|
|
||||||
always,
|
always,
|
||||||
)
|
)
|
||||||
import PlutusTx.AssocMap qualified as AssocMap
|
import PlutusTx.AssocMap qualified as AssocMap
|
||||||
|
|
@ -136,7 +135,7 @@ defLocks :: [ProposalLock]
|
||||||
defLocks = [Created (ProposalId 0)]
|
defLocks = [Created (ProposalId 0)]
|
||||||
|
|
||||||
-- | The effect of the newly created proposal.
|
-- | The effect of the newly created proposal.
|
||||||
defEffects :: AssocMap.Map ResultTag (AssocMap.Map ValidatorHash DatumHash)
|
defEffects :: AssocMap.Map ResultTag ProposalEffectGroup
|
||||||
defEffects =
|
defEffects =
|
||||||
AssocMap.fromList
|
AssocMap.fromList
|
||||||
[ (ResultTag 0, AssocMap.empty)
|
[ (ResultTag 0, AssocMap.empty)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ module Sample.Proposal.UnlockStake (
|
||||||
import Agora.Governor (Governor (..))
|
import Agora.Governor (Governor (..))
|
||||||
import Agora.Proposal (
|
import Agora.Proposal (
|
||||||
ProposalDatum (..),
|
ProposalDatum (..),
|
||||||
|
ProposalEffectGroup,
|
||||||
ProposalId (..),
|
ProposalId (..),
|
||||||
ProposalRedeemer (Unlock),
|
ProposalRedeemer (Unlock),
|
||||||
ProposalStatus (..),
|
ProposalStatus (..),
|
||||||
|
|
@ -51,10 +52,8 @@ import Plutarch.Context (
|
||||||
)
|
)
|
||||||
import PlutusLedgerApi.V1.Value qualified as Value
|
import PlutusLedgerApi.V1.Value qualified as Value
|
||||||
import PlutusLedgerApi.V2 (
|
import PlutusLedgerApi.V2 (
|
||||||
DatumHash,
|
|
||||||
PubKeyHash,
|
PubKeyHash,
|
||||||
TxOutRef (..),
|
TxOutRef (..),
|
||||||
ValidatorHash,
|
|
||||||
)
|
)
|
||||||
import PlutusTx.AssocMap qualified as AssocMap
|
import PlutusTx.AssocMap qualified as AssocMap
|
||||||
import Sample.Proposal.Shared (stakeTxRef)
|
import Sample.Proposal.Shared (stakeTxRef)
|
||||||
|
|
@ -85,7 +84,7 @@ votesTemplate =
|
||||||
-- | Create empty effects for every result tag given the votes.
|
-- | Create empty effects for every result tag given the votes.
|
||||||
emptyEffectFor ::
|
emptyEffectFor ::
|
||||||
ProposalVotes ->
|
ProposalVotes ->
|
||||||
AssocMap.Map ResultTag (AssocMap.Map ValidatorHash DatumHash)
|
AssocMap.Map ResultTag ProposalEffectGroup
|
||||||
emptyEffectFor (ProposalVotes vs) =
|
emptyEffectFor (ProposalVotes vs) =
|
||||||
AssocMap.fromList $
|
AssocMap.fromList $
|
||||||
map (,AssocMap.empty) (AssocMap.keys vs)
|
map (,AssocMap.empty) (AssocMap.keys vs)
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ module Test.Util (
|
||||||
sortValue,
|
sortValue,
|
||||||
blake2b_224,
|
blake2b_224,
|
||||||
pubKeyHashes,
|
pubKeyHashes,
|
||||||
|
scriptHashes,
|
||||||
userCredentials,
|
userCredentials,
|
||||||
scriptCredentials,
|
scriptCredentials,
|
||||||
validatorHashes,
|
validatorHashes,
|
||||||
|
|
@ -43,7 +44,6 @@ import Plutarch.Context (
|
||||||
)
|
)
|
||||||
import Plutarch.Crypto (pblake2b_256)
|
import Plutarch.Crypto (pblake2b_256)
|
||||||
import PlutusLedgerApi.V1.Interval qualified as PlutusTx
|
import PlutusLedgerApi.V1.Interval qualified as PlutusTx
|
||||||
import PlutusLedgerApi.V1.Scripts (Datum (Datum), DatumHash (DatumHash))
|
|
||||||
import PlutusLedgerApi.V1.Value (Value (..))
|
import PlutusLedgerApi.V1.Value (Value (..))
|
||||||
import PlutusLedgerApi.V2 (
|
import PlutusLedgerApi.V2 (
|
||||||
Credential (
|
Credential (
|
||||||
|
|
@ -51,8 +51,11 @@ import PlutusLedgerApi.V2 (
|
||||||
ScriptCredential
|
ScriptCredential
|
||||||
),
|
),
|
||||||
CurrencySymbol,
|
CurrencySymbol,
|
||||||
|
Datum (Datum),
|
||||||
|
DatumHash (DatumHash),
|
||||||
PubKeyHash (..),
|
PubKeyHash (..),
|
||||||
ScriptContext,
|
ScriptContext,
|
||||||
|
ScriptHash (ScriptHash),
|
||||||
TxOutRef,
|
TxOutRef,
|
||||||
ValidatorHash (ValidatorHash),
|
ValidatorHash (ValidatorHash),
|
||||||
)
|
)
|
||||||
|
|
@ -162,6 +165,10 @@ validatorHashes = ValidatorHash . PlutusTx.toBuiltin <$> blake2b_224Hashes
|
||||||
scriptCredentials :: [Credential]
|
scriptCredentials :: [Credential]
|
||||||
scriptCredentials = ScriptCredential <$> validatorHashes
|
scriptCredentials = ScriptCredential <$> validatorHashes
|
||||||
|
|
||||||
|
-- | An infinite list of *valid* script hashes.
|
||||||
|
scriptHashes :: [ScriptHash]
|
||||||
|
scriptHashes = ScriptHash . PlutusTx.toBuiltin <$> blake2b_224Hashes
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Turn the given list in to groups which have the given length.
|
-- | Turn the given list in to groups which have the given length.
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import Agora.Governor (
|
||||||
)
|
)
|
||||||
import Agora.Proposal (
|
import Agora.Proposal (
|
||||||
PProposalDatum (..),
|
PProposalDatum (..),
|
||||||
|
PProposalEffectGroup,
|
||||||
ProposalStatus (Draft, Locked),
|
ProposalStatus (Draft, Locked),
|
||||||
phasNeutralEffect,
|
phasNeutralEffect,
|
||||||
pisEffectsVotesCompatible,
|
pisEffectsVotesCompatible,
|
||||||
|
|
@ -36,7 +37,14 @@ import Agora.Proposal (
|
||||||
pwinner,
|
pwinner,
|
||||||
)
|
)
|
||||||
import Agora.Proposal.Time (createProposalStartingTime)
|
import Agora.Proposal.Time (createProposalStartingTime)
|
||||||
import Agora.Scripts (AgoraScripts, authorityTokenSymbol, governorSTSymbol, proposalSTSymbol, proposalValidatoHash, stakeSTSymbol)
|
import Agora.Scripts (
|
||||||
|
AgoraScripts,
|
||||||
|
authorityTokenSymbol,
|
||||||
|
governorSTSymbol,
|
||||||
|
proposalSTSymbol,
|
||||||
|
proposalValidatoHash,
|
||||||
|
stakeSTSymbol,
|
||||||
|
)
|
||||||
import Agora.Stake (
|
import Agora.Stake (
|
||||||
PProposalLock (..),
|
PProposalLock (..),
|
||||||
PStakeDatum (..),
|
PStakeDatum (..),
|
||||||
|
|
@ -45,17 +53,17 @@ import Agora.Stake (
|
||||||
import Agora.Utils (
|
import Agora.Utils (
|
||||||
pfindDatum,
|
pfindDatum,
|
||||||
pfromDatumHash,
|
pfromDatumHash,
|
||||||
|
pfstTuple,
|
||||||
pmustFindDatum,
|
pmustFindDatum,
|
||||||
|
psndTuple,
|
||||||
validatorHashToAddress,
|
validatorHashToAddress,
|
||||||
)
|
)
|
||||||
import Plutarch.Api.V1 (
|
import Plutarch.Api.V1 (
|
||||||
PCurrencySymbol,
|
PCurrencySymbol,
|
||||||
PMap,
|
|
||||||
PValidatorHash,
|
|
||||||
)
|
)
|
||||||
|
import Plutarch.Api.V1.AssocMap qualified as AssocMap
|
||||||
import Plutarch.Api.V2 (
|
import Plutarch.Api.V2 (
|
||||||
PAddress,
|
PAddress,
|
||||||
PDatumHash,
|
|
||||||
PMintingPolicy,
|
PMintingPolicy,
|
||||||
PScriptPurpose (PMinting, PSpending),
|
PScriptPurpose (PMinting, PSpending),
|
||||||
PTxOut,
|
PTxOut,
|
||||||
|
|
@ -66,10 +74,9 @@ import Plutarch.Extra.Field (pletAllC)
|
||||||
import Plutarch.Extra.IsData (pmatchEnumFromData)
|
import Plutarch.Extra.IsData (pmatchEnumFromData)
|
||||||
import Plutarch.Extra.List (pfirstJust)
|
import Plutarch.Extra.List (pfirstJust)
|
||||||
import Plutarch.Extra.Map (
|
import Plutarch.Extra.Map (
|
||||||
plookup,
|
|
||||||
plookup',
|
plookup',
|
||||||
)
|
)
|
||||||
import Plutarch.Extra.Maybe (passertPJust, pfromJust, pnothing)
|
import Plutarch.Extra.Maybe (passertPDJust, passertPJust, pfromJust, pmaybeData, pnothing)
|
||||||
import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=))
|
import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=))
|
||||||
import Plutarch.Extra.ScriptContext (
|
import Plutarch.Extra.ScriptContext (
|
||||||
pfindOutputsToAddress,
|
pfindOutputsToAddress,
|
||||||
|
|
@ -489,35 +496,44 @@ governorValidator as =
|
||||||
pguardC "Output GATs is more than minted GATs" $
|
pguardC "Output GATs is more than minted GATs" $
|
||||||
plength # outputsWithGAT #== gatCount
|
plength # outputsWithGAT #== gatCount
|
||||||
|
|
||||||
let gatOutputValidator' :: Term s (PMap _ PValidatorHash PDatumHash :--> PTxOut :--> PBool)
|
let validateGATOutput' :: Term s (PProposalEffectGroup :--> PTxOut :--> PBool)
|
||||||
gatOutputValidator' =
|
validateGATOutput' =
|
||||||
phoistAcyclic $
|
phoistAcyclic $
|
||||||
plam
|
plam
|
||||||
( \effects output' -> unTermCont $ do
|
( \effects output -> unTermCont $ do
|
||||||
output <- pletFieldsC @'["address", "datum"] output'
|
outputF <- pletFieldsC @'["address", "datum", "referenceScript"] output
|
||||||
|
|
||||||
let scriptHash =
|
let receiverScriptHash =
|
||||||
passertPJust # "GAT receiver is not a script"
|
passertPJust # "GAT receiver should be a script"
|
||||||
#$ pscriptHashFromAddress # output.address
|
#$ pscriptHashFromAddress # outputF.address
|
||||||
datumHash =
|
effect =
|
||||||
ptrace
|
passertPJust # "Receiver should be in the effect group"
|
||||||
"Output to effect should have datum"
|
#$ AssocMap.plookup # receiverScriptHash # effects
|
||||||
pfromDatumHash
|
hasCorrectReferenceScript =
|
||||||
# output.datum
|
pmaybeData
|
||||||
|
# pconstant True
|
||||||
expectedDatumHash =
|
# plam
|
||||||
passertPJust # "Receiver is not in the effect list"
|
( ( passertPDJust
|
||||||
#$ plookup # scriptHash # effects
|
# "Output UTXO should have a reference script"
|
||||||
|
# outputF.referenceScript
|
||||||
|
#==
|
||||||
|
)
|
||||||
|
. pfromData
|
||||||
|
)
|
||||||
|
# (psndTuple # effect)
|
||||||
|
hasCorrectDatum =
|
||||||
|
pfstTuple # effect #== pfromDatumHash # outputF.datum
|
||||||
|
|
||||||
pure $
|
pure $
|
||||||
foldr1
|
foldr1
|
||||||
(#&&)
|
(#&&)
|
||||||
[ ptraceIfFalse "GAT must be tagged by the effect hash" $ authorityTokensValidIn # patSymbol # output'
|
[ ptraceIfFalse "GAT valid" $ authorityTokensValidIn # patSymbol # output
|
||||||
, ptraceIfFalse "Unexpected datum" $ datumHash #== expectedDatumHash
|
, ptraceIfFalse "Correct datum" hasCorrectDatum
|
||||||
|
, ptraceIfFalse "Reference script correct" hasCorrectReferenceScript
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
gatOutputValidator = gatOutputValidator' # effectGroup
|
validateGATOutput = validateGATOutput' # effectGroup
|
||||||
|
|
||||||
pguardC "GATs valid" $
|
pguardC "GATs valid" $
|
||||||
pfoldr
|
pfoldr
|
||||||
|
|
@ -526,7 +542,7 @@ governorValidator as =
|
||||||
let value = pfield @"value" # txOut
|
let value = pfield @"value" # txOut
|
||||||
atValue = psymbolValueOf # patSymbol # value
|
atValue = psymbolValueOf # patSymbol # value
|
||||||
in pif (atValue #== 0) r $
|
in pif (atValue #== 0) r $
|
||||||
pif (atValue #== 1) (r #&& gatOutputValidator # txOut) $ pconstant False
|
pif (atValue #== 1) (r #&& validateGATOutput # txOut) $ pconstant False
|
||||||
)
|
)
|
||||||
# pconstant True
|
# pconstant True
|
||||||
# pfromData txInfoF.outputs
|
# pfromData txInfoF.outputs
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
module Agora.Plutarch.Orphans () where
|
module Agora.Plutarch.Orphans () where
|
||||||
|
|
||||||
import Plutarch.Api.V1 (PDatumHash (..))
|
import Plutarch.Api.V2 (PDatumHash (..), PScriptHash (..))
|
||||||
import Plutarch.Builtin (PIsData (..))
|
import Plutarch.Builtin (PIsData (..))
|
||||||
import Plutarch.Extra.TermCont (ptryFromC)
|
import Plutarch.Extra.TermCont (ptryFromC)
|
||||||
import Plutarch.TryFrom (PTryFrom (..))
|
import Plutarch.TryFrom (PTryFrom (..))
|
||||||
|
|
@ -37,3 +37,18 @@ instance PTryFrom PData (PAsData PUnit)
|
||||||
instance (PIsData a) => PIsData (PAsData a) where
|
instance (PIsData a) => PIsData (PAsData a) where
|
||||||
pfromDataImpl = punsafeCoerce
|
pfromDataImpl = punsafeCoerce
|
||||||
pdataImpl = pdataImpl . pfromData
|
pdataImpl = pdataImpl . pfromData
|
||||||
|
|
||||||
|
-- | @since 1.0.0
|
||||||
|
instance PTryFrom PData (PAsData PScriptHash) where
|
||||||
|
type PTryFromExcess PData (PAsData PScriptHash) = Flip Term PScriptHash
|
||||||
|
ptryFrom' opq = runTermCont $ do
|
||||||
|
(pfromData -> unwrapped, _) <- ptryFromC @(PAsData PByteString) opq
|
||||||
|
|
||||||
|
tcont $ \f ->
|
||||||
|
pif
|
||||||
|
-- Blake2b_224 hash: 224 bits/28 bytes.
|
||||||
|
(plengthBS # unwrapped #== 28)
|
||||||
|
(f ())
|
||||||
|
(ptraceError "ptryFrom(PScriptHash): must be 32 bytes long")
|
||||||
|
|
||||||
|
pure (punsafeCoerce opq, pcon $ PScriptHash unwrapped)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ module Agora.Proposal (
|
||||||
-- * Haskell-land
|
-- * Haskell-land
|
||||||
|
|
||||||
-- Proposal (..),
|
-- Proposal (..),
|
||||||
|
ProposalEffectGroup,
|
||||||
ProposalDatum (..),
|
ProposalDatum (..),
|
||||||
ProposalRedeemer (..),
|
ProposalRedeemer (..),
|
||||||
ProposalStatus (..),
|
ProposalStatus (..),
|
||||||
|
|
@ -21,6 +22,7 @@ module Agora.Proposal (
|
||||||
emptyVotesFor,
|
emptyVotesFor,
|
||||||
|
|
||||||
-- * Plutarch-land
|
-- * Plutarch-land
|
||||||
|
PProposalEffectGroup,
|
||||||
PProposalDatum (..),
|
PProposalDatum (..),
|
||||||
PProposalRedeemer (..),
|
PProposalRedeemer (..),
|
||||||
PProposalStatus (..),
|
PProposalStatus (..),
|
||||||
|
|
@ -41,7 +43,12 @@ module Agora.Proposal (
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Agora.Plutarch.Orphans ()
|
import Agora.Plutarch.Orphans ()
|
||||||
import Agora.Proposal.Time (PProposalStartingTime, PProposalTimingConfig, ProposalStartingTime, ProposalTimingConfig)
|
import Agora.Proposal.Time (
|
||||||
|
PProposalStartingTime,
|
||||||
|
PProposalTimingConfig,
|
||||||
|
ProposalStartingTime,
|
||||||
|
ProposalTimingConfig,
|
||||||
|
)
|
||||||
import Agora.SafeMoney (GTTag)
|
import Agora.SafeMoney (GTTag)
|
||||||
import Data.Tagged (Tagged)
|
import Data.Tagged (Tagged)
|
||||||
import Generics.SOP qualified as SOP
|
import Generics.SOP qualified as SOP
|
||||||
|
|
@ -50,7 +57,10 @@ import Plutarch.Api.V1.AssocMap qualified as PAssocMap
|
||||||
import Plutarch.Api.V2 (
|
import Plutarch.Api.V2 (
|
||||||
KeyGuarantees (Unsorted),
|
KeyGuarantees (Unsorted),
|
||||||
PDatumHash,
|
PDatumHash,
|
||||||
|
PMaybeData,
|
||||||
PPubKeyHash,
|
PPubKeyHash,
|
||||||
|
PScriptHash,
|
||||||
|
PTuple,
|
||||||
)
|
)
|
||||||
import Plutarch.DataRepr (DerivePConstantViaData (..), PDataFields)
|
import Plutarch.DataRepr (DerivePConstantViaData (..), PDataFields)
|
||||||
import Plutarch.Extra.Comonad (pextract)
|
import Plutarch.Extra.Comonad (pextract)
|
||||||
|
|
@ -75,7 +85,7 @@ import Plutarch.Lift (
|
||||||
)
|
)
|
||||||
import Plutarch.SafeMoney (PDiscrete (..))
|
import Plutarch.SafeMoney (PDiscrete (..))
|
||||||
import Plutarch.Show (PShow (..))
|
import Plutarch.Show (PShow (..))
|
||||||
import PlutusLedgerApi.V1 (DatumHash, PubKeyHash, ValidatorHash)
|
import PlutusLedgerApi.V2 (DatumHash, PubKeyHash, ScriptHash, ValidatorHash)
|
||||||
import PlutusTx qualified
|
import PlutusTx qualified
|
||||||
import PlutusTx.AssocMap qualified as AssocMap
|
import PlutusTx.AssocMap qualified as AssocMap
|
||||||
|
|
||||||
|
|
@ -272,6 +282,9 @@ newtype ProposalVotes = ProposalVotes
|
||||||
emptyVotesFor :: forall a. AssocMap.Map ResultTag a -> ProposalVotes
|
emptyVotesFor :: forall a. AssocMap.Map ResultTag a -> ProposalVotes
|
||||||
emptyVotesFor = ProposalVotes . AssocMap.mapWithKey (const . const 0)
|
emptyVotesFor = ProposalVotes . AssocMap.mapWithKey (const . const 0)
|
||||||
|
|
||||||
|
-- | @since 0.3.0
|
||||||
|
type ProposalEffectGroup = AssocMap.Map ValidatorHash (DatumHash, Maybe ScriptHash)
|
||||||
|
|
||||||
{- | Haskell-level datum for Proposal scripts.
|
{- | Haskell-level datum for Proposal scripts.
|
||||||
|
|
||||||
@since 0.1.0
|
@since 0.1.0
|
||||||
|
|
@ -282,7 +295,7 @@ data ProposalDatum = ProposalDatum
|
||||||
-- TODO: could we encode this more efficiently?
|
-- TODO: could we encode this more efficiently?
|
||||||
-- This is shaped this way for future proofing.
|
-- This is shaped this way for future proofing.
|
||||||
-- See https://github.com/Liqwid-Labs/agora/issues/39
|
-- See https://github.com/Liqwid-Labs/agora/issues/39
|
||||||
, effects :: AssocMap.Map ResultTag (AssocMap.Map ValidatorHash DatumHash)
|
, effects :: AssocMap.Map ResultTag ProposalEffectGroup
|
||||||
-- ^ Effect lookup table. First by result, then by effect hash.
|
-- ^ Effect lookup table. First by result, then by effect hash.
|
||||||
, status :: ProposalStatus
|
, status :: ProposalStatus
|
||||||
-- ^ The status the proposal is in.
|
-- ^ The status the proposal is in.
|
||||||
|
|
@ -583,6 +596,15 @@ deriving via
|
||||||
instance
|
instance
|
||||||
(PConstantDecl ProposalVotes)
|
(PConstantDecl ProposalVotes)
|
||||||
|
|
||||||
|
type PProposalEffectGroup =
|
||||||
|
PMap
|
||||||
|
'Unsorted
|
||||||
|
PValidatorHash
|
||||||
|
( PTuple
|
||||||
|
PDatumHash
|
||||||
|
(PMaybeData (PAsData PScriptHash))
|
||||||
|
)
|
||||||
|
|
||||||
{- | Plutarch-level version of 'ProposalDatum'.
|
{- | Plutarch-level version of 'ProposalDatum'.
|
||||||
|
|
||||||
@since 0.1.0
|
@since 0.1.0
|
||||||
|
|
@ -593,7 +615,7 @@ newtype PProposalDatum (s :: S) = PProposalDatum
|
||||||
s
|
s
|
||||||
( PDataRecord
|
( PDataRecord
|
||||||
'[ "proposalId" ':= PProposalId
|
'[ "proposalId" ':= PProposalId
|
||||||
, "effects" ':= PMap 'Unsorted PResultTag (PMap 'Unsorted PValidatorHash PDatumHash)
|
, "effects" ':= PMap 'Unsorted PResultTag PProposalEffectGroup
|
||||||
, "status" ':= PProposalStatus
|
, "status" ':= PProposalStatus
|
||||||
, "cosigners" ':= PBuiltinList (PAsData PPubKeyHash)
|
, "cosigners" ':= PBuiltinList (PAsData PPubKeyHash)
|
||||||
, "thresholds" ':= PProposalThresholds
|
, "thresholds" ':= PProposalThresholds
|
||||||
|
|
@ -678,7 +700,7 @@ phasNeutralEffect ::
|
||||||
forall (s :: S).
|
forall (s :: S).
|
||||||
Term
|
Term
|
||||||
s
|
s
|
||||||
( PMap 'Unsorted PResultTag (PMap 'Unsorted PValidatorHash PDatumHash)
|
( PMap 'Unsorted PResultTag PProposalEffectGroup
|
||||||
:--> PBool
|
:--> PBool
|
||||||
)
|
)
|
||||||
phasNeutralEffect = phoistAcyclic $ PAssocMap.pany # PAssocMap.pnull
|
phasNeutralEffect = phoistAcyclic $ PAssocMap.pany # PAssocMap.pnull
|
||||||
|
|
@ -691,7 +713,7 @@ pisEffectsVotesCompatible ::
|
||||||
forall (s :: S).
|
forall (s :: S).
|
||||||
Term
|
Term
|
||||||
s
|
s
|
||||||
( PMap 'Unsorted PResultTag (PMap 'Unsorted PValidatorHash PDatumHash)
|
( PMap 'Unsorted PResultTag PProposalEffectGroup
|
||||||
:--> PProposalVotes
|
:--> PProposalVotes
|
||||||
:--> PBool
|
:--> PBool
|
||||||
)
|
)
|
||||||
|
|
@ -811,7 +833,7 @@ phighestVotes = phoistAcyclic $
|
||||||
pneutralOption ::
|
pneutralOption ::
|
||||||
Term
|
Term
|
||||||
s
|
s
|
||||||
( PMap 'Unsorted PResultTag (PMap 'Unsorted PValidatorHash PDatumHash)
|
( PMap 'Unsorted PResultTag PProposalEffectGroup
|
||||||
:--> PResultTag
|
:--> PResultTag
|
||||||
)
|
)
|
||||||
pneutralOption = phoistAcyclic $
|
pneutralOption = phoistAcyclic $
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,9 @@ 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, pmaybe, pnothing)
|
import Plutarch.Extra.Maybe (pjust, pnothing)
|
||||||
import Plutarch.Extra.TermCont (pmatchC)
|
import Plutarch.Extra.TermCont (pmatchC)
|
||||||
import Plutarch.Lift (
|
import Plutarch.Lift (
|
||||||
DerivePConstantViaNewtype (..),
|
DerivePConstantViaNewtype (..),
|
||||||
|
|
@ -357,8 +358,7 @@ createProposalStartingTime = phoistAcyclic $
|
||||||
"createProposalStartingTime: given time range should be tight enough"
|
"createProposalStartingTime: given time range should be tight enough"
|
||||||
pnothing
|
pnothing
|
||||||
)
|
)
|
||||||
in -- TODO: PMonad when?
|
in ct #>>= f
|
||||||
pmaybe # pnothing # f # ct
|
|
||||||
|
|
||||||
{- | Get the current proposal time, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field.
|
{- | Get the current proposal time, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ module Agora.Utils (
|
||||||
pfromDatumHash,
|
pfromDatumHash,
|
||||||
pfromInlineDatum,
|
pfromInlineDatum,
|
||||||
ptryFindDatum,
|
ptryFindDatum,
|
||||||
|
pfstTuple,
|
||||||
|
psndTuple,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Plutarch.Api.V1.AssocMap (KeyGuarantees (Unsorted), PMap)
|
import Plutarch.Api.V1.AssocMap (KeyGuarantees (Unsorted), PMap)
|
||||||
|
|
@ -32,6 +34,7 @@ import Plutarch.Api.V2 (
|
||||||
PDatum,
|
PDatum,
|
||||||
PDatumHash,
|
PDatumHash,
|
||||||
POutputDatum (..),
|
POutputDatum (..),
|
||||||
|
PTuple,
|
||||||
)
|
)
|
||||||
import Plutarch.Extra.Functor (pfmap)
|
import Plutarch.Extra.Functor (pfmap)
|
||||||
import Plutarch.Extra.Maybe (passertPJust, pjust, pnothing)
|
import Plutarch.Extra.Maybe (passertPJust, pjust, pnothing)
|
||||||
|
|
@ -235,3 +238,17 @@ infixr 8 #.**
|
||||||
Term s c ->
|
Term s c ->
|
||||||
Term s e
|
Term s e
|
||||||
(#.**) f g x y z = f #$ g # x # y # z
|
(#.**) f g x y z = f #$ g # x # y # z
|
||||||
|
|
||||||
|
{- | Extract the first component of a 'PTuple'.
|
||||||
|
|
||||||
|
@since 1.0.0
|
||||||
|
-}
|
||||||
|
pfstTuple :: forall a b s. (PIsData a) => Term s (PTuple a b :--> a)
|
||||||
|
pfstTuple = phoistAcyclic $ plam $ pfromData . (pfield @"_0" #)
|
||||||
|
|
||||||
|
{- | Extract the second component of a 'PTuple'.
|
||||||
|
|
||||||
|
@since 1.0.0
|
||||||
|
-}
|
||||||
|
psndTuple :: forall b a s. (PIsData b) => Term s (PTuple a b :--> b)
|
||||||
|
psndTuple = phoistAcyclic $ plam $ pfromData . (pfield @"_1" #)
|
||||||
|
|
|
||||||
8
flake.lock
generated
8
flake.lock
generated
|
|
@ -12940,16 +12940,16 @@
|
||||||
"plutarch": "plutarch_7"
|
"plutarch": "plutarch_7"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1660151677,
|
"lastModified": 1660709756,
|
||||||
"narHash": "sha256-sUdXtVdCpm7pgmw0f+b0FyF4Bf0VX+1kTY5U8O3H4uk=",
|
"narHash": "sha256-L9S9UYtpeTVGFmKNj8c/H3i17Jx8asCiW43xblN5nBo=",
|
||||||
"owner": "Liqwid-Labs",
|
"owner": "Liqwid-Labs",
|
||||||
"repo": "plutarch-context-builder",
|
"repo": "plutarch-context-builder",
|
||||||
"rev": "7033ca3c18968cfd206afbbd40861a0a778b414c",
|
"rev": "cc91cd134ce01e280df3b0ce09a25ede54dbf9b6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "Liqwid-Labs",
|
"owner": "Liqwid-Labs",
|
||||||
"ref": "staging",
|
"ref": "main",
|
||||||
"repo": "plutarch-context-builder",
|
"repo": "plutarch-context-builder",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
plutarch-quickcheck.url =
|
plutarch-quickcheck.url =
|
||||||
"github:liqwid-labs/plutarch-quickcheck?ref=staging";
|
"github:liqwid-labs/plutarch-quickcheck?ref=staging";
|
||||||
plutarch-context-builder.url =
|
plutarch-context-builder.url =
|
||||||
"github:Liqwid-Labs/plutarch-context-builder?ref=staging";
|
"github:Liqwid-Labs/plutarch-context-builder?ref=main";
|
||||||
plutarch-script-export.url =
|
plutarch-script-export.url =
|
||||||
"github:Liqwid-Labs/plutarch-script-export?ref=main";
|
"github:Liqwid-Labs/plutarch-script-export?ref=main";
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue