diff --git a/bench/Main.hs b/bench/Main.hs index c2fb603..d10619b 100644 --- a/bench/Main.hs +++ b/bench/Main.hs @@ -16,10 +16,6 @@ import Agora.AuthorityToken ( AuthorityToken (AuthorityToken), authorityTokenPolicy, ) -import Agora.MultiSig ( - MultiSig (..), - multiSigValidator, - ) import Agora.SafeMoney (LQ) import Agora.Stake ( Stake (Stake), @@ -38,16 +34,9 @@ benchmarks = benchGroup "full_scripts" [ bench "authorityTokenPolicy" $ authorityTokenPolicy authorityToken - , bench "multiSigValidator" $ multiSigValidator multiSig , bench "stakePolicy" $ stakePolicy (Stake @LQ) , bench "stakeValidator" $ stakeValidator (Stake @LQ) ] authorityToken :: AuthorityToken -authorityToken = AuthorityToken (Value.assetClass "" "") - -multiSig :: MultiSig (s :: S) -multiSig = MultiSig - { keys = PSNil - , minSigs = 0 - } \ No newline at end of file +authorityToken = AuthorityToken (Value.assetClass "" "") \ No newline at end of file diff --git a/src/Agora/MultiSig.hs b/src/Agora/MultiSig.hs index bb570bd..a56bfe5 100644 --- a/src/Agora/MultiSig.hs +++ b/src/Agora/MultiSig.hs @@ -1,10 +1,11 @@ {- | Module : Agora.MultiSig Maintainer : riley_kilgore@outlook.com -Description: A basic N of M multisignature validator. +Description: A basic N of M multisignature validation function. -} module Agora.MultiSig ( - multiSigValidator, + validatedByMultisig, + pvalidatedByMultisig, MultiSig (..), ) where @@ -12,16 +13,18 @@ import Plutarch.Api.V1 ( PPubKeyHash, PScriptContext (..), ) +import Plutarch.DataRepr ( + PDataFields, + PIsDataReprInstances (PIsDataReprInstances), + ) import Plutarch.Monadic qualified as P --------------------------------------------------------------------------------- - -import Agora.Utils (passert) +import Plutus.V1.Ledger.Crypto (PubKeyHash) -------------------------------------------------------------------------------- import GHC.Generics qualified as GHC -import Generics.SOP (Generic) +import Generics.SOP (Generic, I (I)) import Prelude -------------------------------------------------------------------------------- @@ -29,24 +32,58 @@ import Prelude {- | A MultiSig represents a proof that a particular set of signatures are present on a transaction. -} -data MultiSig (s :: S) = MultiSig - { keys :: PList PPubKeyHash s +data MultiSig = MultiSig + { keys :: [PubKeyHash] -- ^ List of PubKeyHashes that must be present in the list of signatories. , minSigs :: Integer } deriving stock (GHC.Generic) deriving anyclass (Generic) --------------------------------------------------------------------------------- +newtype PMultiSig (s :: S) = PMultiSig + { getMultiSig :: + Term s (PDataRecord '[ "pkeys" ':= PBuiltinList (PAsData PPubKeyHash) + , "pminSigs" ':= PInteger]) + } + deriving stock (GHC.Generic) + deriving anyclass (Generic) + deriving anyclass (PIsDataRepr) + deriving + (PlutusType, PIsData, PDataFields) + via (PIsDataReprInstances PMultiSig) --- | Validator given 'MultiSig' params. -multiSigValidator :: MultiSig s -> Term s (PData :--> PData :--> PScriptContext :--> PUnit) -multiSigValidator params = - plam $ \_datum _redeemer ctx' -> P.do +-------------------------------------------------------------------------------- +pubKeysToPPubKeys :: + forall s. [PubKeyHash] -> PBuiltinList (PAsData PPubKeyHash) s +pubKeysToPPubKeys xs = case xs of + x:xs' -> + let x' :: Term s (PAsData PPubKeyHash) + x' = pconstantData x + in + PCons x' (pcon $ pubKeysToPPubKeys xs') + [] -> + PNil + +multisigToPMultisig :: forall s. MultiSig -> Term s PMultiSig +multisigToPMultisig m = + pcon $ PMultiSig (pdcons @"pkeys" @(PBuiltinList (PAsData PPubKeyHash)) + # (pdata $ pcon (pubKeysToPPubKeys m.keys)) + #$ pdcons @"pminSigs" @PInteger # (pdata $ fromInteger m.minSigs) # pdnil) + +validatedByMultisig :: MultiSig -> Term s (PScriptContext :--> PBool) +validatedByMultisig params = + plam $ \ctx' -> P.do + pvalidatedByMultisig # (multisigToPMultisig params) # ctx' + +pvalidatedByMultisig :: Term s (PMultiSig :--> PScriptContext :--> PBool) +pvalidatedByMultisig = + plam $ \multi' ctx' -> P.do ctx <- pletFields @'["txInfo", "purpose"] ctx' + multi <- pletFields @'["pkeys", "pminSigs"] multi' let signatories = pfield @"signatories" # ctx.txInfo - passert "The amount of required signatures is not met." - ((fromInteger params.minSigs) #<= (plength #$ pfilter + pif + ((pfromData multi.pminSigs) #<= (plength #$ pfilter # (plam $ \a -> - (pelem # pdata a # pfromData signatories)) - # pcon params.keys)) - (pconstant ()) \ No newline at end of file + (pelem # a # pfromData signatories)) + # multi.pkeys)) + (pcon PTrue) + perror \ No newline at end of file