add HasParameterisedGenerator and wire tests up

This commit is contained in:
Emily Martins 2022-03-18 15:23:07 +01:00
parent 060e46814a
commit 93acd81e79
4 changed files with 107 additions and 14 deletions

View file

@ -1,9 +1,28 @@
module Model.MultiSig () where module Model.MultiSig (plutarchTests, genTests) where
import Agora.MultiSig (MultiSig (..)) import Agora.MultiSig (MultiSig (..), validatedByMultisig)
import Apropos (Apropos (Apropos), Formula (ExactlyOne), (:+)) import Apropos (Apropos (Apropos), Formula (ExactlyOne, Var, Yes), HasLogicalModel (..), HasParameterisedGenerator, LogicalModel (logic), parameterisedGenerator, runGeneratorTestsWhere, (:+))
import Apropos.Script (HasScriptRunner (expect, script)) import Apropos.Gen (Gen, choice, int, linear, list)
import Plutus.V1.Ledger.Api (PubKeyHash, Script) import Apropos.LogicalModel (Enumerable)
import Apropos.LogicalModel.Enumerable (Enumerable (enumerated))
import Apropos.Script (HasScriptRunner (expect, runScriptTestsWhere, script))
import Data.List (intersect)
import Plutarch (compile)
import Plutus.V1.Ledger.Api (
Script,
ScriptContext (scriptContextPurpose),
ScriptPurpose (Spending),
TxInfo (txInfoDCert, txInfoData, txInfoFee, txInfoId, txInfoInputs, txInfoMint, txInfoOutputs, txInfoValidRange, txInfoWdrl),
TxOutRef (TxOutRef),
scriptContextTxInfo,
txInfoSignatories,
)
import Plutus.V1.Ledger.Contexts (ScriptContext (ScriptContext), TxInfo (TxInfo))
import Plutus.V1.Ledger.Crypto (PubKeyHash)
import Plutus.V1.Ledger.Interval qualified as Interval
import Plutus.V1.Ledger.Value qualified as Value
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.Hedgehog (fromGroup)
{- {-
@ -33,27 +52,94 @@ data MultiSigModel = MultiSigModel
{ ms :: MultiSig { ms :: MultiSig
, ctx :: ScriptContext , ctx :: ScriptContext
} }
deriving stock (Eq, Show)
data MultiSigProp data MultiSigProp
= MeetsMinSigs = MeetsMinSigs
| DoesNotMeetMinSigs | DoesNotMeetMinSigs
deriving stock (Eq, Show, Ord)
instance LogicalModel MultiSigModel where instance Enumerable MultiSigProp where
enumerated = [MeetsMinSigs, DoesNotMeetMinSigs]
instance LogicalModel MultiSigProp where
logic = ExactlyOne [Var MeetsMinSigs, Var DoesNotMeetMinSigs] logic = ExactlyOne [Var MeetsMinSigs, Var DoesNotMeetMinSigs]
instance HasLogicalModel MultiSigProp MultiSigModel where instance HasLogicalModel MultiSigProp MultiSigModel where
satisfiesProperty :: MultiSigProp -> MultiSigModel -> Bool satisfiesProperty :: MultiSigProp -> MultiSigModel -> Bool
satisfiesProperty p m = satisfiesProperty p m =
let minSigs = m.ms.minSigs let minSigs = m.ms.minSigs
signatories = m.ctx.txInfo.txInfoSignatories signatories = txInfoSignatories $ scriptContextTxInfo $ m.ctx
matchingSigs = intersect m.ms.keys signatories matchingSigs = intersect m.ms.keys signatories
in case p of in case p of
MeetsMinSigs -> length matchingSigs >= minSigs MeetsMinSigs -> length matchingSigs >= fromInteger minSigs
DoesNotMeetMinSigs -> length matchingSigs < minSigs DoesNotMeetMinSigs -> length matchingSigs < fromInteger minSigs
instance HasScriptRunner MultiSigProp MultiSig where contextWithSignatures :: [PubKeyHash] -> ScriptContext
contextWithSignatures sigs =
ScriptContext
{ scriptContextTxInfo =
TxInfo
{ txInfoInputs = []
, txInfoOutputs = []
, txInfoFee = Value.singleton "" "" 2
, txInfoMint = mempty
, txInfoDCert = []
, txInfoWdrl = []
, txInfoValidRange = Interval.always
, txInfoSignatories = sigs
, txInfoData = []
, txInfoId = "0b2086cbf8b6900f8cb65e012de4516cb66b5cb08a9aaba12a8b88be"
}
, scriptContextPurpose = Spending (TxOutRef "" 0)
}
genPK :: Gen PubKeyHash
genPK =
choice
[ pure "8a30896c4fd5e79843e4ca1bd2cdbaa36f8c0bc3be7401214142019c"
, pure "0b12051dd2da4b3629cebb92e2be111e0e99c63c04727ed55b74a296"
, pure "87f5f31e4d7437463cd901c4c9edb7a51903ac858661503e9d72f492"
, pure "f74ccaee8244264b3c73fce3b66bd2337de3db70efff4261d6ff145b"
]
instance HasParameterisedGenerator MultiSigProp MultiSigModel where
parameterisedGenerator s = do
expectedSignatures <- list (linear 1 4) genPK
minSigs <- toInteger <$> int (linear 1 (length expectedSignatures))
let msig = MultiSig expectedSignatures minSigs
actualSignaturesLength <-
if MeetsMinSigs `elem` s
then int (linear (fromInteger minSigs) (length expectedSignatures))
else pure 0
let actualSignatures = take actualSignaturesLength expectedSignatures
let ctx = contextWithSignatures actualSignatures
pure (MultiSigModel msig ctx)
instance HasScriptRunner MultiSigProp MultiSigModel where
expect :: (MultiSigModel :+ MultiSigProp) -> Formula MultiSigProp expect :: (MultiSigModel :+ MultiSigProp) -> Formula MultiSigProp
expect = undefined expect Apropos = Var MeetsMinSigs
script :: (MultiSigModel :+ MultiSigProp) -> MultiSig -> Script script :: (MultiSigModel :+ MultiSigProp) -> MultiSigModel -> Script
script Apropos msm = compile $ validatedByMultisig msm . ms script Apropos msm =
compile $
pif
(validatedByMultisig msm.ms # pconstant msm.ctx.scriptContextTxInfo)
(pcon PUnit)
perror
genTests :: TestTree
genTests =
testGroup "genTests" $
fromGroup
<$> [ runGeneratorTestsWhere (Apropos :: MultiSigModel :+ MultiSigProp) "Generator" Yes
]
plutarchTests :: TestTree
plutarchTests =
testGroup "plutarchTests" $
fromGroup
<$> [ runScriptTestsWhere (Apropos :: MultiSigModel :+ MultiSigProp) "ScriptValid" Yes
]

View file

@ -8,6 +8,7 @@ import Test.Tasty (defaultMain, testGroup)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Model.MultiSig qualified
import Spec.Int import Spec.Int
import Spec.Stake qualified as Stake import Spec.Stake qualified as Stake
@ -25,5 +26,10 @@ main =
"Int" "Int"
[ intPlutarchTests [ intPlutarchTests
] ]
, testGroup
"MultiSig"
[ Model.MultiSig.plutarchTests
, Model.MultiSig.genTests
]
] ]
] ]

View file

@ -151,6 +151,7 @@ test-suite agora-test
Spec.Int Spec.Int
Spec.Sample.Stake Spec.Sample.Stake
Spec.Stake Spec.Stake
Model.MultiSig
Spec.Util Spec.Util
build-depends: agora build-depends: agora

View file

@ -47,7 +47,7 @@ data MultiSig = MultiSig
-- ^ List of PubKeyHashes that must be present in the list of signatories. -- ^ List of PubKeyHashes that must be present in the list of signatories.
, minSigs :: Integer , minSigs :: Integer
} }
deriving stock (GHC.Generic) deriving stock (GHC.Generic, Eq, Show)
deriving anyclass (Generic) deriving anyclass (Generic)
PlutusTx.makeLift ''MultiSig PlutusTx.makeLift ''MultiSig