From b67a992278eab31fb25174fa27da607efdbabe3e Mon Sep 17 00:00:00 2001 From: Riley Kilgore Date: Sat, 5 Mar 2022 05:31:11 -0800 Subject: [PATCH] Added a multi-sig validator at Agora.MultiSig --- agora.cabal | 1 + bench/Main.hs | 11 +++++++++ src/Agora/MultiSig.hs | 52 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/Agora/MultiSig.hs diff --git a/agora.cabal b/agora.cabal index 1a68b80..4e3240f 100644 --- a/agora.cabal +++ b/agora.cabal @@ -116,6 +116,7 @@ library import: lang, deps exposed-modules: Agora.AuthorityToken + Agora.MultiSig Agora.SafeMoney Agora.SafeMoney.QQ Agora.Stake diff --git a/bench/Main.hs b/bench/Main.hs index 150f528..c2fb603 100644 --- a/bench/Main.hs +++ b/bench/Main.hs @@ -16,6 +16,10 @@ import Agora.AuthorityToken ( AuthorityToken (AuthorityToken), authorityTokenPolicy, ) +import Agora.MultiSig ( + MultiSig (..), + multiSigValidator, + ) import Agora.SafeMoney (LQ) import Agora.Stake ( Stake (Stake), @@ -34,9 +38,16 @@ 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 diff --git a/src/Agora/MultiSig.hs b/src/Agora/MultiSig.hs new file mode 100644 index 0000000..bb570bd --- /dev/null +++ b/src/Agora/MultiSig.hs @@ -0,0 +1,52 @@ +{- | +Module : Agora.MultiSig +Maintainer : riley_kilgore@outlook.com +Description: A basic N of M multisignature validator. +-} +module Agora.MultiSig ( + multiSigValidator, + MultiSig (..), +) where + +import Plutarch.Api.V1 ( + PPubKeyHash, + PScriptContext (..), + ) +import Plutarch.Monadic qualified as P + +-------------------------------------------------------------------------------- + +import Agora.Utils (passert) + +-------------------------------------------------------------------------------- + +import GHC.Generics qualified as GHC +import Generics.SOP (Generic) +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 + -- ^ List of PubKeyHashes that must be present in the list of signatories. + , minSigs :: Integer + } deriving stock (GHC.Generic) + deriving anyclass (Generic) + +-------------------------------------------------------------------------------- + +-- | Validator given 'MultiSig' params. +multiSigValidator :: MultiSig s -> Term s (PData :--> PData :--> PScriptContext :--> PUnit) +multiSigValidator params = + plam $ \_datum _redeemer ctx' -> P.do + ctx <- pletFields @'["txInfo", "purpose"] ctx' + let signatories = pfield @"signatories" # ctx.txInfo + passert "The amount of required signatures is not met." + ((fromInteger params.minSigs) #<= (plength #$ pfilter + # (plam $ \a -> + (pelem # pdata a # pfromData signatories)) + # pcon params.keys)) + (pconstant ()) \ No newline at end of file