From 346c08afc98c00c96ed5a818abe27ce0e38b9692 Mon Sep 17 00:00:00 2001 From: Jack Hodgkinson <30505104+jhodgdev@users.noreply.github.com> Date: Thu, 3 Mar 2022 17:00:14 +0000 Subject: [PATCH] Added Utils.Value --- agora.cabal | 6 ++- src/Agora/Treasury.hs | 3 +- src/Agora/Utils.hs | 93 ++++++++++++++++----------------- src/Agora/Utils/Value.hs | 107 ++++++++++++++++++++++++++++++++++++++ src/Plutarch/Extra/Map.hs | 2 + 5 files changed, 161 insertions(+), 50 deletions(-) create mode 100644 src/Agora/Utils/Value.hs create mode 100644 src/Plutarch/Extra/Map.hs diff --git a/agora.cabal b/agora.cabal index 103c47a..a7b4703 100644 --- a/agora.cabal +++ b/agora.cabal @@ -122,7 +122,11 @@ library Agora.Treasury Agora.Voting - other-modules: Agora.Utils + other-modules: + Agora.Utils + Agora.Utils.Value + Plutarch.Extra.Map + hs-source-dirs: src library pprelude diff --git a/src/Agora/Treasury.hs b/src/Agora/Treasury.hs index 2948008..61ae19d 100644 --- a/src/Agora/Treasury.hs +++ b/src/Agora/Treasury.hs @@ -30,7 +30,6 @@ import Plutarch.DataRepr ( PIsDataReprInstances (PIsDataReprInstances), ) import Plutarch.Monadic qualified as P -import Agora.Utils (pisValueSubset) {- | Validator ensuring that transactions consuming the treasury do so in a valid manner. @@ -59,7 +58,7 @@ treasuryV = plam $ \d r ctx' -> P.do -- Amount of value treasury has after transaction. let valueTrOut = undefined - let vOutExceedsVIn = pisValueSubset # valueTrIn # valueTrOut + let vOutExceedsVIn = undefined pif (vOutExceedsVIn) diff --git a/src/Agora/Utils.hs b/src/Agora/Utils.hs index e3de254..d70e9f1 100644 --- a/src/Agora/Utils.hs +++ b/src/Agora/Utils.hs @@ -24,7 +24,6 @@ module Agora.Utils ( pfindTxInByTxOutRef, psingletonValue, pfindMap, - pisValueSubset, -- * Functions which should (probably) not be upstreamed anyOutput, @@ -260,58 +259,58 @@ pfindTxInByTxOutRef = phoistAcyclic $ ) #$ (pfield @"inputs" # txInfo) --- | Determines if a value is a subset of another. -pisValueSubset :: Term s (PValue :--> PValue :--> PBool) -pisValueSubset = plam $ \v0 _v1 -> P.do - -- v0Map :: Term s (PMap PCurrencySymbol (PMap PTokenName PInteger)) - PValue v0Map <- pmatch v0 +-- -- | Determines if a value is a subset of another. +-- pisValueSubset :: Term s (PValue :--> PValue :--> PBool) +-- pisValueSubset = plam $ \v0 _v1 -> P.do +-- -- v0Map :: Term s (PMap PCurrencySymbol (PMap PTokenName PInteger)) +-- PValue v0Map <- pmatch v0 - -- v0BuiltinMap :: Term s (PBuiltinMap k v) - PMap v0BuiltinMap <- pmatch v0Map +-- -- v0BuiltinMap :: Term s (PBuiltinMap k v) +-- PMap v0BuiltinMap <- pmatch v0Map - -- ks0 :: Term s (PBuiltinList PCurrencySymbol) - let ks0 = pmap # pfstBuiltin # v0BuiltinMap - pconstant True +-- -- ks0 :: Term s (PBuiltinList PCurrencySymbol) +-- let ks0 = pmap # pfstBuiltin # v0BuiltinMap +-- pconstant True --- | Determines if a PTokenName/PInteger pmap is a subset of another. -pisTnISubset :: - Term - s - ( PMap PTokenName PInteger - :--> PMap PTokenName PInteger - :--> PBool - ) -pisTnISubset = plam $ \m0 m1 -> P.do - -- m0BuiltinMap :: Term s (PBuiltinMap PTokenName PInteger) - PMap m0BuiltinMap <- pmatch m0 +-- -- | Determines if a PTokenName/PInteger pmap is a subset of another. +-- pisTnISubset :: +-- Term +-- s +-- ( PMap PTokenName PInteger +-- :--> PMap PTokenName PInteger +-- :--> PBool +-- ) +-- pisTnISubset = plam $ \m0 m1 -> P.do +-- -- m0BuiltinMap :: Term s (PBuiltinMap PTokenName PInteger) +-- PMap m0BuiltinMap <- pmatch m0 - -- ks0 :: Term s (PBuiltinList PTokenName) - let ks0 = pmap # pfstBuiltin # m0BuiltinMap - pconstant True +-- -- ks0 :: Term s (PBuiltinList PTokenName) +-- let ks0 = pmap # pfstBuiltin # m0BuiltinMap +-- pconstant True -pcompareKeysForEq :: - Term - s - ( PBuiltinList k - :--> PMap k v - :--> PMap k v - :--> PBool - ) -pcompareKeysForEq = plam $ \ks m0' m1' -> P.do - PMap m0 <- m0' - PMap m1 <- m1' - bs <- pmatch $ pmap # f # ks - pcon PTrue +-- pcompareKeys :: +-- Term +-- s +-- ( PBuiltinList k +-- :--> PMap k v +-- :--> PMap k v +-- :--> PBool +-- ) +-- pcompareKeys = plam $ \ks m0' m1' -> P.do +-- PMap m0 <- m0' +-- PMap m1 <- m1' +-- bs <- pmatch $ pmap # f # ks +-- pconstant True -f :: Term s (k :--> PMap k v :--> PMap k v) -f = plam $ \k m0' m1' -> P.do - PMap m0 <- m0' - PMap m1 <- m1' - pmatch (plookup # k # m1) $ \case - PNothing -> pconstant False - PJust n1 -> P.do - PJust n0 <- pmatch $ plookup # k # m0 - n0 #<= n1 +-- f :: Term s (k :--> PMap k v :--> PMap k v :--> PBool) +-- f = plam $ \k m0' m1' -> P.do +-- PMap m0 <- m0' +-- PMap m1 <- m1' +-- pmatch (plookup # k # m1) $ \case +-- PNothing -> pconstant False +-- PJust n1 -> P.do +-- PJust n0 <- pmatch $ plookup # k # m0 +-- n0 #<= n1 -------------------------------------------------------------------------------- -- Functions which should (probably) not be upstreamed diff --git a/src/Agora/Utils/Value.hs b/src/Agora/Utils/Value.hs new file mode 100644 index 0000000..b27d569 --- /dev/null +++ b/src/Agora/Utils/Value.hs @@ -0,0 +1,107 @@ +{-# OPTIONS_GHC -Wwarn #-} + +module Agora.Utils.Value where + +import GHC.Generics qualified as GHC +import Generics.SOP +import Plutarch.Api.V1.AssocMap (PMap (PMap)) +import Plutarch.Api.V1.Tuple (PTuple, ptupleFromBuiltin) +import Plutarch.Api.V1.Value (PCurrencySymbol, PTokenName, PValue) +import Plutarch.DataRepr (PIsDataReprInstances (PIsDataReprInstances)) +import Plutarch.Lift (PLifted, PUnsafeLiftDecl) +import Plutarch.Monadic qualified as P +import Plutus.V1.Ledger.Api qualified as Plutus +import PlutusTx.These qualified as PlutusThese + +-- data PThese (a :: PType) (b :: PType) (s :: S) +-- = PThis (Term s a) +-- | PThat (Term s b) +-- | PThese (Term s a) (Term s b) +-- deriving stock (GHC.Generic) +-- deriving anyclass (Generic, PlutusType) + +data PTheseData (a :: PType) (b :: PType) (s :: S) + = PDThis (Term s (PDataRecord '["_0" ':= a])) + | PDThat (Term s (PDataRecord '["_0" ':= b])) + | PDThese (Term s (PDataRecord '["_0" ':= a, "_1" ':= b])) + deriving stock (GHC.Generic) + deriving anyclass (Generic, PIsDataRepr) + deriving + (PlutusType, PIsData) + via PIsDataReprInstances (PTheseData a b) + +instance + ( Plutus.ToData (PLifted a) + , Plutus.ToData (PLifted b) + , Plutus.FromData (PLifted a) + , Plutus.FromData (PLifted b) + , PLift a + , PLift b + ) => + PUnsafeLiftDecl (PTheseData a b) + where + type PLifted (PTheseData a b) = PlutusThese.These (PLifted a) (PLifted b) + +punionVal :: + Term + s + ( PValue + :--> PValue + :--> PMap + PCurrencySymbol + (PMap PTokenName (PTheseData PInteger PInteger)) + ) +punionVal = undefined + +-- | Determines if a condition is true for all values in a map. +pmapAll :: + (PUnsafeLiftDecl v, PIsData v) => + Term s ((v :--> PBool) :--> PMap k v :--> PBool) +pmapAll = plam $ \f m -> P.do + PMap builtinMap <- pmatch $ m + + let getV :: PIsData v => Term s (PBuiltinPair (PAsData k) (PAsData v) :--> v) + getV = plam $ \bip -> P.do + let tuple = pfromData $ ptupleFromBuiltin (pdata bip) + pfield @"_1" # tuple + + let vs = pmap # getV # builtinMap + pall # f # vs + +pcheckPred :: + forall {s :: S}. + Term + s + ( (PTheseData PInteger PInteger :--> PBool) + :--> PValue + :--> PValue + :--> PBool + ) +pcheckPred = plam $ \f l r -> P.do + let inner :: Term s (PMap PTokenName (PTheseData PInteger PInteger) :--> PBool) + inner = pmapAll # f + pmapAll # inner # (punionVal # l # r) + +pcheckBinRel :: + forall {s :: S}. + Term + s + ( (PInteger :--> PInteger :--> PBool) + :--> PValue + :--> PValue + :--> PBool + ) +pcheckBinRel = plam $ \f l r -> P.do + let unThese :: Term s (PTheseData PInteger PInteger :--> PBool) + unThese = plam $ \k' -> + pmatch k' $ \case + PDThis r -> f # (pfield @"_0" # r) # 0 + PDThat r -> f # 0 # (pfield @"_0" # r) + PDThese r -> f # (pfield @"_0" # r) # (pfield @"_1" # r) + pcheckPred # unThese # l # r + +pleq :: Term s (PValue :--> PValue :--> PBool) +pleq = plam $ \v0 v1 -> (pcheckBinRel # pleq') # v0 # v1 + +pleq' :: Term s (PInteger :--> PInteger :--> PBool) +pleq' = plam $ \m n -> m #<= n diff --git a/src/Plutarch/Extra/Map.hs b/src/Plutarch/Extra/Map.hs new file mode 100644 index 0000000..ba05359 --- /dev/null +++ b/src/Plutarch/Extra/Map.hs @@ -0,0 +1,2 @@ +module Plutarch.Extra.Map () where +