began reworking treasury

This commit is contained in:
Jack Hodgkinson 2022-03-03 11:59:23 +00:00
parent fbf87a9165
commit ade66fdbd0
2 changed files with 80 additions and 84 deletions

View file

@ -1,3 +1,5 @@
{-# OPTIONS_GHC -Wwarn #-}
{- | {- |
Module: Agora.Treasury Module: Agora.Treasury
Maintainer: jack@mlabs.city Maintainer: jack@mlabs.city
@ -28,6 +30,7 @@ import Plutarch.DataRepr (
PIsDataReprInstances (PIsDataReprInstances), PIsDataReprInstances (PIsDataReprInstances),
) )
import Plutarch.Monadic qualified as P import Plutarch.Monadic qualified as P
import Agora.Utils (pisValueSubset)
{- | Validator ensuring that transactions consuming the treasury {- | Validator ensuring that transactions consuming the treasury
do so in a valid manner. do so in a valid manner.
@ -41,92 +44,27 @@ treasuryV ::
:--> PUnit :--> PUnit
) )
treasuryV = plam $ \d r ctx' -> P.do treasuryV = plam $ \d r ctx' -> P.do
-- Load txInfo and purpose fields from script context.
ctx <- pletFields @["txInfo", "purpose"] ctx'
-- Extract txInfo.
PTxInfo txInfo' <- pmatch $ pfromData ctx.txInfo
-- Pattern match on type of treasury redeemer.
pmatch (pfromData r) $ \case pmatch (pfromData r) $ \case
-- Treasury is merely being witnessed. It's datum and value -- Redeemer seeking to alter treasury parameters. Must ensure
-- must be unchanged. -- a valid GAT is burned in the transaction.
PWitnessTreasury _ -> P.do PAlterTrParams _ ->
txInfo <- pletFields @'["inputs", "outputs", "data"] txInfo' ptraceError "Altering treasury parameters is not currently supported."
-- Redeemer for all other treasury actions. Must ensure datum
-- is unchanged and no value has been removed from the
-- treasury.
PRedeemTreasury _ -> P.do
-- Amount of value treasury has before transaction.
let valueTrIn = undefined
-- Get datum hash of datum supplied to validator. -- Amount of value treasury has after transaction.
let dat = pfield @"data" # txInfo' let valueTrOut = undefined
dH = getTrDatumHash # d # dat
-- Get inputs in TxOut form. let vOutExceedsVIn = pisValueSubset # valueTrIn # valueTrOut
let inputs = txInfo.inputs
rs = pmap # toResolved # inputs
-- Find the value the treasury had before being spent.
let valueIn = getValAtDHash # dH # rs
-- Find the value the treasury has after being spent.
let outputs = txInfo.outputs
valueOut = getValAtDHash # dH # outputs
-- If the value in equals the value out, validate the
-- transaction. Otherwise, fail.
pif pif
(valueIn #== valueOut) (vOutExceedsVIn)
(pconstant ()) (pconstant ())
$ ptraceError "Treasury is altered when witnessing transaction" (ptraceError "Value has been illegally deducted from treasury.")
-- Treasury is receiving amount of funds specified in the
-- redeemer. It's datum must be unchanged but it's value
-- must be increased by the specified amount.
PReceiveFunds _ -> P.do
pconstant ()
{- | Plutarch level function that, given a treasury datum and a
list of the transaction's data, will find its hash.
-}
getTrDatumHash ::
Term
s
( PAsData PTreasuryDatum
:--> PBuiltinList (PAsData (PTuple PDatumHash PDatum))
:--> PDatumHash
)
getTrDatumHash = plam $ \d l -> P.do
let t = phead #$ pfilter # (matchDatums # d) # l
pfield @"_0" # t
where
matchDatums ::
Term
s
( PAsData PTreasuryDatum
:--> PAsData (PTuple PDatumHash PDatum)
:--> PBool
)
matchDatums = plam $ \d t' ->
let t = pfield @"_1" # t'
in pforgetData d #== pforgetData t
-- | Get the "resolved" field of a TxInInfo.
toResolved :: Term s (PAsData PTxInInfo :--> PAsData PTxOut)
toResolved = plam $ \txIn -> pfield @"resolved" # txIn
-- | Gets the value kept at a given datum hash.
getValAtDHash ::
Term
s
( PDatumHash
:--> PBuiltinList (PAsData PTxOut)
:--> PAsData PValue
)
getValAtDHash = plam $ \dh outs -> P.do
let matchingOut = phead #$ pfilter # (matchHashes # dh) # outs
pfield @"value" # matchingOut
where
matchHashes :: Term s (PDatumHash :--> PAsData PTxOut :--> PBool)
matchHashes = plam $ \dh out' -> P.do
PDJust dh' <- pmatch $ pfield @"datumHash" # pfromData out'
dh #== pfield @"_0" # dh'
{- | Plutarch level type representing datum of the treasury. {- | Plutarch level type representing datum of the treasury.
Contains: Contains:
@ -153,10 +91,10 @@ newtype PTreasuryDatum (s :: S)
treasury. treasury.
-} -}
data PTreasuryRedeemer (s :: S) data PTreasuryRedeemer (s :: S)
= -- | Receive funds and place them in the treasury. = -- | TODO: will allow the burning of GATs to alter Treasury params.
PReceiveFunds (Term s (PDataRecord '["_0" ':= PValue])) PAlterTrParams (Term s (PDataRecord '[]))
| -- | Serve as a witness for any transaction. Must remain unaltered. | -- | All other treasury actions. Value must not decrease.
PWitnessTreasury (Term s (PDataRecord '[])) PRedeemTreasury (Term s (PDataRecord '[]))
deriving stock (GHC.Generic) deriving stock (GHC.Generic)
deriving anyclass (Generic, PIsDataRepr) deriving anyclass (Generic, PIsDataRepr)
deriving deriving

View file

@ -1,3 +1,5 @@
{-# OPTIONS_GHC -Wwarn #-}
{- | {- |
Module : Agora.Utils Module : Agora.Utils
Maintainer : emi@haskell.fyi Maintainer : emi@haskell.fyi
@ -22,6 +24,7 @@ module Agora.Utils (
pfindTxInByTxOutRef, pfindTxInByTxOutRef,
psingletonValue, psingletonValue,
pfindMap, pfindMap,
pisValueSubset,
-- * Functions which should (probably) not be upstreamed -- * Functions which should (probably) not be upstreamed
anyOutput, anyOutput,
@ -50,6 +53,8 @@ import Plutarch.Api.V1 (
PTxOutRef, PTxOutRef,
PValue (PValue), PValue (PValue),
) )
import Plutarch.Api.V1.Tuple (ptupleFromBuiltin)
import Plutarch.Bool (pand)
import Plutarch.Builtin (ppairDataBuiltin) import Plutarch.Builtin (ppairDataBuiltin)
import Plutarch.Internal (punsafeCoerce) import Plutarch.Internal (punsafeCoerce)
import Plutarch.Monadic qualified as P import Plutarch.Monadic qualified as P
@ -255,6 +260,59 @@ pfindTxInByTxOutRef = phoistAcyclic $
) )
#$ (pfield @"inputs" # txInfo) #$ (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
-- v0BuiltinMap :: Term s (PBuiltinMap k v)
PMap v0BuiltinMap <- pmatch v0Map
-- 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
-- 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
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
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Functions which should (probably) not be upstreamed -- Functions which should (probably) not be upstreamed