Added some annotations to work on multisig apropos testing
This commit is contained in:
parent
93acd81e79
commit
745e576d33
1 changed files with 76 additions and 28 deletions
|
|
@ -1,7 +1,16 @@
|
||||||
module Model.MultiSig (plutarchTests, genTests) where
|
module Model.MultiSig (plutarchTests, genTests) where
|
||||||
|
|
||||||
import Agora.MultiSig (MultiSig (..), validatedByMultisig)
|
import Agora.MultiSig (MultiSig (..), validatedByMultisig)
|
||||||
import Apropos (Apropos (Apropos), Formula (ExactlyOne, Var, Yes), HasLogicalModel (..), HasParameterisedGenerator, LogicalModel (logic), parameterisedGenerator, runGeneratorTestsWhere, (:+))
|
import Apropos (
|
||||||
|
Apropos (Apropos),
|
||||||
|
Formula (ExactlyOne, Var, Yes),
|
||||||
|
HasLogicalModel (..),
|
||||||
|
HasParameterisedGenerator,
|
||||||
|
LogicalModel (logic),
|
||||||
|
parameterisedGenerator,
|
||||||
|
runGeneratorTestsWhere,
|
||||||
|
(:+),
|
||||||
|
)
|
||||||
import Apropos.Gen (Gen, choice, int, linear, list)
|
import Apropos.Gen (Gen, choice, int, linear, list)
|
||||||
import Apropos.LogicalModel (Enumerable)
|
import Apropos.LogicalModel (Enumerable)
|
||||||
import Apropos.LogicalModel.Enumerable (Enumerable (enumerated))
|
import Apropos.LogicalModel.Enumerable (Enumerable (enumerated))
|
||||||
|
|
@ -12,7 +21,17 @@ import Plutus.V1.Ledger.Api (
|
||||||
Script,
|
Script,
|
||||||
ScriptContext (scriptContextPurpose),
|
ScriptContext (scriptContextPurpose),
|
||||||
ScriptPurpose (Spending),
|
ScriptPurpose (Spending),
|
||||||
TxInfo (txInfoDCert, txInfoData, txInfoFee, txInfoId, txInfoInputs, txInfoMint, txInfoOutputs, txInfoValidRange, txInfoWdrl),
|
TxInfo (
|
||||||
|
txInfoDCert,
|
||||||
|
txInfoData,
|
||||||
|
txInfoFee,
|
||||||
|
txInfoId,
|
||||||
|
txInfoInputs,
|
||||||
|
txInfoMint,
|
||||||
|
txInfoOutputs,
|
||||||
|
txInfoValidRange,
|
||||||
|
txInfoWdrl
|
||||||
|
),
|
||||||
TxOutRef (TxOutRef),
|
TxOutRef (TxOutRef),
|
||||||
scriptContextTxInfo,
|
scriptContextTxInfo,
|
||||||
txInfoSignatories,
|
txInfoSignatories,
|
||||||
|
|
@ -24,45 +43,50 @@ import Plutus.V1.Ledger.Value qualified as Value
|
||||||
import Test.Tasty (TestTree, testGroup)
|
import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.Hedgehog (fromGroup)
|
import Test.Tasty.Hedgehog (fromGroup)
|
||||||
|
|
||||||
{-
|
{- Function definitions for reference:
|
||||||
|
|
||||||
1. Create proposition sum type.
|
{- | A MultiSig represents a proof that a particular set of
|
||||||
2. Create logical model defining relationships between propositions.
|
signatures are present on a transaction.
|
||||||
3. Associating propositions with the "concrete" type i.e. MultiSig.
|
-}
|
||||||
4. Create Generators.
|
data MultiSig = MultiSig
|
||||||
5. Run tests (with magic).
|
{ keys :: [PubKeyHash]
|
||||||
|
-- ^ List of PubKeyHashes that must be present in the list of signatories.
|
||||||
-}
|
, minSigs :: Integer
|
||||||
|
}
|
||||||
{-
|
deriving stock (GHC.Generic, Eq, Show)
|
||||||
|
deriving anyclass (Generic)
|
||||||
1. Create a
|
|
||||||
|
-- | Check if a Haskell-level MultiSig signs this transaction.
|
||||||
Define a prop, as if it is the way a script can pass.
|
validatedByMultisig :: MultiSig -> Term s (PTxInfo :--> PBool)
|
||||||
1. keys signed exceeds `minSigs`
|
validatedByMultisig params =
|
||||||
2. `minSigs` is lte zero.
|
phoistAcyclic $
|
||||||
|
pvalidatedByMultisig # pconstant params
|
||||||
Props not passing:
|
|
||||||
1. No signatures present.
|
|
||||||
2. Signatures present is less than `minSigs`.
|
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
-- | apropos model for testing multisigs.
|
||||||
data MultiSigModel = MultiSigModel
|
data MultiSigModel = MultiSigModel
|
||||||
{ ms :: MultiSig
|
{ ms :: MultiSig
|
||||||
|
-- ^ `MultiSig` value to be tested.
|
||||||
, ctx :: ScriptContext
|
, ctx :: ScriptContext
|
||||||
|
-- ^ The `ScriptContext` of the transaction.
|
||||||
}
|
}
|
||||||
deriving stock (Eq, Show)
|
deriving stock (Eq, Show)
|
||||||
|
|
||||||
|
-- | Propositions that may hold true of a `MultiSigModel`.
|
||||||
data MultiSigProp
|
data MultiSigProp
|
||||||
= MeetsMinSigs
|
= -- | Sufficient number of signatories in the script context.
|
||||||
| DoesNotMeetMinSigs
|
MeetsMinSigs
|
||||||
|
| -- | Insufficient number of signatories in the script context.
|
||||||
|
DoesNotMeetMinSigs
|
||||||
deriving stock (Eq, Show, Ord)
|
deriving stock (Eq, Show, Ord)
|
||||||
|
|
||||||
instance Enumerable MultiSigProp where
|
instance Enumerable MultiSigProp where
|
||||||
enumerated = [MeetsMinSigs, DoesNotMeetMinSigs]
|
enumerated = [MeetsMinSigs, DoesNotMeetMinSigs]
|
||||||
|
|
||||||
instance LogicalModel MultiSigProp where
|
instance LogicalModel MultiSigProp where
|
||||||
|
-- Only logical relationship between the two propositions is
|
||||||
|
-- that exactly one of them holds for a given model.
|
||||||
logic = ExactlyOne [Var MeetsMinSigs, Var DoesNotMeetMinSigs]
|
logic = ExactlyOne [Var MeetsMinSigs, Var DoesNotMeetMinSigs]
|
||||||
|
|
||||||
instance HasLogicalModel MultiSigProp MultiSigModel where
|
instance HasLogicalModel MultiSigProp MultiSigModel where
|
||||||
|
|
@ -75,6 +99,9 @@ instance HasLogicalModel MultiSigProp MultiSigModel where
|
||||||
MeetsMinSigs -> length matchingSigs >= fromInteger minSigs
|
MeetsMinSigs -> length matchingSigs >= fromInteger minSigs
|
||||||
DoesNotMeetMinSigs -> length matchingSigs < fromInteger minSigs
|
DoesNotMeetMinSigs -> length matchingSigs < fromInteger minSigs
|
||||||
|
|
||||||
|
{- | Given a list of key hashes, returns a dummy `ScriptContext`,
|
||||||
|
with those hashes as signatories.
|
||||||
|
-}
|
||||||
contextWithSignatures :: [PubKeyHash] -> ScriptContext
|
contextWithSignatures :: [PubKeyHash] -> ScriptContext
|
||||||
contextWithSignatures sigs =
|
contextWithSignatures sigs =
|
||||||
ScriptContext
|
ScriptContext
|
||||||
|
|
@ -94,6 +121,7 @@ contextWithSignatures sigs =
|
||||||
, scriptContextPurpose = Spending (TxOutRef "" 0)
|
, scriptContextPurpose = Spending (TxOutRef "" 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | Generator returning one of four dummy public key hashes.
|
||||||
genPK :: Gen PubKeyHash
|
genPK :: Gen PubKeyHash
|
||||||
genPK =
|
genPK =
|
||||||
choice
|
choice
|
||||||
|
|
@ -105,23 +133,37 @@ genPK =
|
||||||
|
|
||||||
instance HasParameterisedGenerator MultiSigProp MultiSigModel where
|
instance HasParameterisedGenerator MultiSigProp MultiSigModel where
|
||||||
parameterisedGenerator s = do
|
parameterisedGenerator s = do
|
||||||
|
-- Gen between one and four signatures for the `MultiSig`.
|
||||||
expectedSignatures <- list (linear 1 4) genPK
|
expectedSignatures <- list (linear 1 4) genPK
|
||||||
|
|
||||||
|
-- Gen the value of `MultiSig.minSigs`.
|
||||||
minSigs <- toInteger <$> int (linear 1 (length expectedSignatures))
|
minSigs <- toInteger <$> int (linear 1 (length expectedSignatures))
|
||||||
|
|
||||||
|
-- Assign values to msig.
|
||||||
let msig = MultiSig expectedSignatures minSigs
|
let msig = MultiSig expectedSignatures minSigs
|
||||||
|
|
||||||
actualSignaturesLength <-
|
actualSignaturesLength <-
|
||||||
|
-- If we would like to generate a MultiSig model which passes...
|
||||||
if MeetsMinSigs `elem` s
|
if MeetsMinSigs `elem` s
|
||||||
then int (linear (fromInteger minSigs) (length expectedSignatures))
|
then -- ... have a sufficient number of signatories.
|
||||||
else pure 0
|
int (linear (fromInteger minSigs) (length expectedSignatures))
|
||||||
|
else -- ... have zero signatories.
|
||||||
|
pure 0
|
||||||
|
|
||||||
|
-- Get a list of signatories for the script context.
|
||||||
let actualSignatures = take actualSignaturesLength expectedSignatures
|
let actualSignatures = take actualSignaturesLength expectedSignatures
|
||||||
|
|
||||||
let ctx = contextWithSignatures actualSignatures
|
let ctx = contextWithSignatures actualSignatures
|
||||||
|
|
||||||
|
-- Return the generated model.
|
||||||
pure (MultiSigModel msig ctx)
|
pure (MultiSigModel msig ctx)
|
||||||
|
|
||||||
instance HasScriptRunner MultiSigProp MultiSigModel where
|
instance HasScriptRunner MultiSigProp MultiSigModel where
|
||||||
|
-- When the script runs, we want the model to meet the minimum signatures.
|
||||||
expect :: (MultiSigModel :+ MultiSigProp) -> Formula MultiSigProp
|
expect :: (MultiSigModel :+ MultiSigProp) -> Formula MultiSigProp
|
||||||
expect Apropos = Var MeetsMinSigs
|
expect Apropos = Var MeetsMinSigs
|
||||||
|
|
||||||
|
-- Function making a valid script from the model and propositions.
|
||||||
script :: (MultiSigModel :+ MultiSigProp) -> MultiSigModel -> Script
|
script :: (MultiSigModel :+ MultiSigProp) -> MultiSigModel -> Script
|
||||||
script Apropos msm =
|
script Apropos msm =
|
||||||
compile $
|
compile $
|
||||||
|
|
@ -134,12 +176,18 @@ genTests :: TestTree
|
||||||
genTests =
|
genTests =
|
||||||
testGroup "genTests" $
|
testGroup "genTests" $
|
||||||
fromGroup
|
fromGroup
|
||||||
<$> [ runGeneratorTestsWhere (Apropos :: MultiSigModel :+ MultiSigProp) "Generator" Yes
|
<$> [ runGeneratorTestsWhere
|
||||||
|
(Apropos :: MultiSigModel :+ MultiSigProp)
|
||||||
|
"Generator"
|
||||||
|
Yes
|
||||||
]
|
]
|
||||||
|
|
||||||
plutarchTests :: TestTree
|
plutarchTests :: TestTree
|
||||||
plutarchTests =
|
plutarchTests =
|
||||||
testGroup "plutarchTests" $
|
testGroup "plutarchTests" $
|
||||||
fromGroup
|
fromGroup
|
||||||
<$> [ runScriptTestsWhere (Apropos :: MultiSigModel :+ MultiSigProp) "ScriptValid" Yes
|
<$> [ runScriptTestsWhere
|
||||||
|
(Apropos :: MultiSigModel :+ MultiSigProp)
|
||||||
|
"ScriptValid"
|
||||||
|
Yes
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue