agora/agora-specs/Sample/Governor/Mutate.hs
Seungheon Oh d2018afd4d Use liqwid-script-export
commit ec70bfd539fe2e27fd48f5f76395400287ac72d7
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Tue Oct 18 18:58:59 2022 -0500

    use LSE

commit 25fff9b3ad1f2dde4cd7cf36977530b06a87d23c
Merge: 01cd3aa 1821dd6
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Tue Oct 18 18:17:45 2022 -0500

    Merge branch 'staging' into seungheonoh/ply

commit 01cd3aa7a235e6fe6658246ca1026fa26dc71a83
Author: Hongrui Fang <chfanghr@gmail.com>
Date:   Tue Oct 11 12:02:03 2022 +0800

    update benchmark

commit a8513244892ce33cfdc9edf8cd501c4985ae8008
Author: Hongrui Fang <chfanghr@gmail.com>
Date:   Tue Oct 11 11:59:22 2022 +0800

    fix tests

commit 20ca40823485c2e2f78253643cf4453ac7b7ddd5
Author: Hongrui Fang <chfanghr@gmail.com>
Date:   Tue Oct 11 11:57:37 2022 +0800

    better import

commit a19fe49424210891bd03db71e4083fc1e0edfd98
Author: Hongrui Fang <chfanghr@gmail.com>
Date:   Tue Oct 11 11:08:20 2022 +0800

    update flake inputs

commit c93b21f1f9441e5c6f54525bf7c6a54757ec36cc
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Mon Oct 10 12:54:12 2022 -0500

    tried to make tests pass

commit 1046ae1237299a33c58b48661bdb6d325a22147e
Merge: 2bf4e36 363bd83
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Mon Oct 10 12:18:48 2022 -0500

    Merge branch 'staging' into seungheonoh/ply

commit 2bf4e3627c1b229f58078695082da85c80efd560
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Mon Oct 10 10:48:36 2022 -0500

    remove junkpile

commit a1dbc9ad9e531fe0d0a0480c4aef9cf9ffa90f1d
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Mon Oct 10 10:47:25 2022 -0500

    versions

commit 4542a06ac733858297d3a48c53368fad19dedc43
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Thu Oct 6 22:57:48 2022 -0500

    script exporting interface

commit 6bd8c1a1d57e4bf9dc25c3068a9c8eae6bf6a19d
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Thu Oct 6 22:58:41 2022 -0500

    fixed tests

commit d3ce2cf95633d336f3e621833677bd5bf10ee2c8
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Sun Oct 2 00:55:18 2022 -0500

    fixed tests

commit 1ae64c9f692652b77b0506013853b2ba44267c65
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Sat Oct 1 13:28:20 2022 -0500

    linker

commit db88cb75c7b74843141ad8ab4e6522b66d0dcfbc
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Sat Oct 1 01:03:50 2022 -0500

    exporting scripts

commit 6389fce28e885a8a7f8669629c266f59c0edb51f
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Sat Oct 1 00:51:49 2022 -0500

    made scripts parameterized on the script level

commit aea1e518a8890550bdebd0e5251da11d915c53a9
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date:   Wed Sep 28 19:53:29 2022 -0500

    Use `TypedScriptEnvelope` for `Agora.Bootstrap`
2022-10-18 19:02:10 -05:00

287 lines
7.4 KiB
Haskell

module Sample.Governor.Mutate (
-- * Testing Utilities
GovernorOutputDatumValidity (..),
GATValidity (..),
GovernorParameters (..),
MockEffectParameters (..),
ParameterBundle (..),
-- * Testing Utilities
Validity (..),
mutate,
mkTestCase,
-- * Parameters Bundles
totallyValidBundle,
invalidBundles,
) where
import Agora.Governor (GovernorDatum (..), GovernorRedeemer (MutateGovernor))
import Agora.Proposal (ProposalId (ProposalId), ProposalThresholds (..))
import Agora.Utils (scriptHashToTokenName)
import Data.Default (def)
import Data.Map ((!))
import Plutarch.Api.V2 (PMintingPolicy, mintingPolicySymbol, mkMintingPolicy, validatorHash)
import Plutarch.Context (
input,
mint,
output,
pubKey,
script,
withDatum,
withRef,
withValue,
)
import PlutusLedgerApi.V1.Value qualified as Value
import PlutusLedgerApi.V2 (
CurrencySymbol (CurrencySymbol),
Data,
ScriptHash (ScriptHash),
TxOutRef (TxOutRef),
Validator (Validator),
ValidatorHash,
Value,
toData,
)
import Sample.Shared (
agoraScripts,
authorityTokenSymbol,
govAssetClass,
govValidator,
govValidatorHash,
minAda,
)
import Test.Specification (SpecificationTree, testValidator)
import Test.Util (
CombinableBuilder,
mkSpending,
pubKeyHashes,
sortValue,
)
--------------------------------------------------------------------------------
-- | Represent the validity property of the governor output datum.
data GovernorOutputDatumValidity
= DatumValid
| ValueInvalid
| WrongType
| NoDatum
deriving stock (Bounded, Enum)
-- | Represent the validity property of the authority token UTxO.
data GATValidity
= GATValid
| WrongTag
| NoGAT
deriving stock (Bounded, Enum)
data GovernorParameters = GovernorParameters
{ governorOutputDatumValidity :: GovernorOutputDatumValidity
, stealGST :: Bool
-- ^ Send the GST to somewhere else other than the govenor validator.
}
data MockEffectParameters = MockEffectParameters
{ gatValidity :: GATValidity
, burnGAT :: Bool
-- ^ Whether to burn the GAT in the transaction or not.
}
data ParameterBundle = ParameterBundle
{ governorParameters :: GovernorParameters
, mockEffectParameters :: MockEffectParameters
}
newtype Validity = Validity {forGovernorValidator :: Bool}
--------------------------------------------------------------------------------
governorInputDatum :: GovernorDatum
governorInputDatum =
GovernorDatum
{ proposalThresholds = def
, nextProposalId = ProposalId 0
, proposalTimings = def
, createProposalTimeRangeMaxWidth = def
, maximumProposalsPerStake = 3
}
mkGovernorOutputDatum ::
GovernorOutputDatumValidity ->
Maybe Data
mkGovernorOutputDatum DatumValid =
Just $
toData $
governorInputDatum
{ maximumProposalsPerStake = 4
}
mkGovernorOutputDatum ValueInvalid =
let invalidProposalThresholds =
ProposalThresholds
{ execute = -1
, create = -1
, toVoting = -1
, vote = -1
, cosign = -1
}
in Just $
toData $
governorInputDatum
{ proposalThresholds =
invalidProposalThresholds
}
mkGovernorOutputDatum WrongType = Just $ toData ()
mkGovernorOutputDatum NoDatum = Nothing
governorRef :: TxOutRef
governorRef =
TxOutRef
"6cce6dfbb697f9e2c4fe9786bb576eb7bd6cbcf7801a4ba13d596006c2d5b957"
1
governorRedeemer :: GovernorRedeemer
governorRedeemer = MutateGovernor
mkGovernorBuilder :: forall b. CombinableBuilder b => GovernorParameters -> b
mkGovernorBuilder ps =
let gst = Value.assetClassValue govAssetClass 1
value = sortValue $ gst <> minAda
gstOutput =
if ps.stealGST
then pubKey $ head pubKeyHashes
else script govValidatorHash
withGSTDatum =
maybe mempty withDatum $
mkGovernorOutputDatum ps.governorOutputDatumValidity
in mconcat
[ input $
mconcat
[ script govValidatorHash
, withDatum governorInputDatum
, withValue value
, withRef governorRef
]
, output $
mconcat
[ gstOutput
, withGSTDatum
, withValue value
]
]
--------------------------------------------------------------------------------
mockEffectValidator :: Validator
mockEffectValidator = Validator $ agoraScripts ! "agora:noOpValidator"
mockEffectValidatorHash :: ValidatorHash
mockEffectValidatorHash = validatorHash mockEffectValidator
mockAuthScript :: ClosedTerm PMintingPolicy
mockAuthScript = plam $ \_ _ -> popaque $ pcon PUnit
mockAuthScriptHash :: ScriptHash
mockAuthScriptHash =
let CurrencySymbol h = mintingPolicySymbol $ mkMintingPolicy def mockAuthScript
in ScriptHash h
mkGATValue :: GATValidity -> Integer -> Value
mkGATValue NoGAT _ = mempty
mkGATValue v q =
let authScript = case v of
GATValid -> mockAuthScriptHash
WrongTag -> ""
in Value.singleton
authorityTokenSymbol
(scriptHashToTokenName authScript)
q
mkMockEffectBuilder :: forall b. CombinableBuilder b => MockEffectParameters -> b
mkMockEffectBuilder ps =
let mkGATValue' = mkGATValue ps.gatValidity
inputValue = mkGATValue' 1
outputValue = inputValue <> burnt
burnt =
if ps.burnGAT
then mkGATValue' (-1)
else mempty
in mconcat
[ mint burnt
, input $
mconcat
[ script mockEffectValidatorHash
, withValue inputValue
]
, output $
mconcat
[ script mockEffectValidatorHash
, withValue outputValue
]
]
--------------------------------------------------------------------------------
mutate :: forall b. CombinableBuilder b => ParameterBundle -> b
mutate pb =
mconcat
[ mkGovernorBuilder pb.governorParameters
, mkMockEffectBuilder pb.mockEffectParameters
]
--------------------------------------------------------------------------------
-- | Run the governor to test the mutation functionality.
mkTestCase :: String -> ParameterBundle -> Validity -> SpecificationTree
mkTestCase name pb (Validity forGov) =
testValidator
forGov
name
govValidator
governorInputDatum
governorRedeemer
(mkSpending mutate pb governorRef)
--------------------------------------------------------------------------------
-- | The only one valid combination of all the parameters.
totallyValidBundle :: ParameterBundle
totallyValidBundle =
ParameterBundle
{ governorParameters =
GovernorParameters
{ governorOutputDatumValidity = DatumValid
, stealGST = False
}
, mockEffectParameters =
MockEffectParameters
{ gatValidity = GATValid
, burnGAT = True
}
}
--------------------------------------------------------------------------------
{- | All the invalid combination of the parameters.
TODO: use 'Gen'?
-}
invalidBundles :: [ParameterBundle]
invalidBundles = do
gdv <- enumFrom ValueInvalid
sg <- [True, False]
gtv <- enumFrom WrongTag
bgt <- [True, False]
pure $
ParameterBundle
{ governorParameters =
GovernorParameters
{ governorOutputDatumValidity = gdv
, stealGST = sg
}
, mockEffectParameters =
MockEffectParameters
{ gatValidity = gtv
, burnGAT = bgt
}
}