Merge pull request #67 from Liqwid-Labs/seungheonoh/effect-ptryfrom

Now `makeEffect` boilerplate requires datum to implemt `PTryFrom`
This commit is contained in:
Emily 2022-04-25 15:12:35 +02:00 committed by GitHub
commit cecbb683fc
4 changed files with 78 additions and 45 deletions

View file

@ -123,6 +123,7 @@ library
exposed-modules: exposed-modules:
Agora.AuthorityToken Agora.AuthorityToken
Agora.Effect Agora.Effect
Agora.Effect.NoOp
Agora.Governor Agora.Governor
Agora.MultiSig Agora.MultiSig
Agora.Proposal Agora.Proposal
@ -151,11 +152,11 @@ test-suite agora-test
main-is: Spec.hs main-is: Spec.hs
hs-source-dirs: agora-test hs-source-dirs: agora-test
other-modules: other-modules:
Spec.AuthorityToken
Spec.Model.MultiSig Spec.Model.MultiSig
Spec.Sample.Stake Spec.Sample.Stake
Spec.Stake Spec.Stake
Spec.Util Spec.Util
Spec.AuthorityToken
build-depends: agora build-depends: agora

View file

@ -5,17 +5,13 @@ Description: Helpers for constructing effects
Helpers for constructing effects. Helpers for constructing effects.
-} -}
module Agora.Effect ( module Agora.Effect (makeEffect) where
makeEffect,
noopEffect,
) where
import Agora.AuthorityToken (singleAuthorityTokenBurned) import Agora.AuthorityToken (singleAuthorityTokenBurned)
import Agora.Utils (passert) import Agora.Utils (passert)
import Plutarch (popaque)
import Plutarch.Api.V1 (PCurrencySymbol, PScriptPurpose (PSpending), PTxInfo, PTxOutRef, PValidator, PValue) import Plutarch.Api.V1 (PCurrencySymbol, PScriptPurpose (PSpending), PTxInfo, PTxOutRef, PValidator, PValue)
import Plutarch.Internal (punsafeCoerce)
import Plutarch.Monadic qualified as P import Plutarch.Monadic qualified as P
import Plutarch.TryFrom (PTryFrom, ptryFrom)
import Plutus.V1.Ledger.Value (CurrencySymbol) import Plutus.V1.Ledger.Value (CurrencySymbol)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -28,7 +24,7 @@ import Plutus.V1.Ledger.Value (CurrencySymbol)
-} -}
makeEffect :: makeEffect ::
forall (datum :: PType). forall (datum :: PType).
PIsData datum => (PIsData datum, PTryFrom PData datum) =>
CurrencySymbol -> CurrencySymbol ->
(forall (s :: S). Term s PCurrencySymbol -> Term s datum -> Term s PTxOutRef -> Term s (PAsData PTxInfo) -> Term s POpaque) -> (forall (s :: S). Term s PCurrencySymbol -> Term s datum -> Term s PTxOutRef -> Term s (PAsData PTxInfo) -> Term s POpaque) ->
ClosedTerm PValidator ClosedTerm PValidator
@ -37,29 +33,24 @@ makeEffect gatCs' f =
ctx <- pletFields @'["txInfo", "purpose"] ctx' ctx <- pletFields @'["txInfo", "purpose"] ctx'
txInfo' <- plet ctx.txInfo txInfo' <- plet ctx.txInfo
-- TODO: Use PTryFrom -- convert input datum, PData, into desierable type
let datum' :: Term _ datum -- the way this conversion is performed should be defined
datum' = pfromData $ punsafeCoerce datum -- by PTryFrom for each datum in effect script.
(datum', _) <- ptryFrom @datum datum
-- ensure purpose is Spending.
PSpending txOutRef <- pmatch $ pfromData ctx.purpose PSpending txOutRef <- pmatch $ pfromData ctx.purpose
txOutRef' <- plet (pfield @"_0" # txOutRef) txOutRef' <- plet (pfield @"_0" # txOutRef)
-- fetch minted values to ensure single GAT is burned
txInfo <- pletFields @'["mint"] txInfo' txInfo <- pletFields @'["mint"] txInfo'
let mint :: Term _ PValue let mint :: Term _ PValue
mint = txInfo.mint mint = txInfo.mint
-- fetch script context
gatCs <- plet $ pconstant gatCs' gatCs <- plet $ pconstant gatCs'
passert "A single authority token has been burned" $ singleAuthorityTokenBurned gatCs txInfo' mint passert "A single authority token has been burned" $ singleAuthorityTokenBurned gatCs txInfo' mint
-- run effect function
f gatCs datum' txOutRef' txInfo' f gatCs datum' txOutRef' txInfo'
--------------------------------------------------------------------------------
-- | Dummy effect which can only burn its GAT.
noopEffect :: CurrencySymbol -> ClosedTerm PValidator
noopEffect =
( `makeEffect`
\_gatCs (_datum :: Term _ PUnit) _txOutRef _txInfo -> P.do
popaque (pconstant ())
)

View file

@ -0,0 +1,33 @@
{- |
Module : Agora.Effect.NoOp
Maintainer : seungheon.ooh@gmail.com
Description: Dummy dumb dumb effect.
A dumb effect that only burns its GAT.
-}
module Agora.Effect.NoOp (noOpValidator, PNoOp) where
import Control.Applicative (Const)
import Agora.Effect (makeEffect)
import Plutarch (popaque)
import Plutarch.Api.V1 (PValidator)
import Plutarch.TryFrom (PTryFrom (..))
import Plutus.V1.Ledger.Value (CurrencySymbol)
newtype PNoOp (s :: S) = PNoOp (Term s PUnit)
deriving (PlutusType, PIsData) via (DerivePNewtype PNoOp PUnit)
instance PTryFrom PData PNoOp where
type PTryFromExcess PData PNoOp = Const ()
ptryFrom' _ cont =
-- JUSTIFICATION:
-- We don't care anything about data.
-- It should always be reduced to Unit.
cont (pcon $ PNoOp (pconstant ()), ())
-- | Dummy effect which can only burn its GAT.
noOpValidator :: CurrencySymbol -> ClosedTerm PValidator
noOpValidator curr = makeEffect curr $
\_ (_datum :: Term s PNoOp) _ _ -> P.do
popaque (pconstant ())

View file

@ -50,8 +50,10 @@
projectFor = system: projectFor = system:
let pkgs = nixpkgsFor system; let pkgs = nixpkgsFor system;
in let pkgs' = nixpkgsFor' system; in
in (nixpkgsFor system).haskell-nix.cabalProject' { let pkgs' = nixpkgsFor' system;
in
(nixpkgsFor system).haskell-nix.cabalProject' {
src = ./.; src = ./.;
compiler-nix-name = ghcVersion; compiler-nix-name = ghcVersion;
inherit (plutarch) cabalProjectLocal; inherit (plutarch) cabalProjectLocal;
@ -120,16 +122,18 @@
inherit (plutarch.tools) fourmolu; inherit (plutarch.tools) fourmolu;
}) })
fourmolu; fourmolu;
in pkgs.runCommand "format-check" { in
nativeBuildInputs = [ pkgs.runCommand "format-check"
pkgs'.git {
pkgs'.fd nativeBuildInputs = [
pkgs'.haskellPackages.cabal-fmt pkgs'.git
pkgs'.nixpkgs-fmt pkgs'.fd
fourmolu pkgs'.haskellPackages.cabal-fmt
pkgs'.haskell.packages."${ghcVersion}".hlint pkgs'.nixpkgs-fmt
]; fourmolu
} '' pkgs'.haskell.packages."${ghcVersion}".hlint
];
} ''
export LC_CTYPE=C.UTF-8 export LC_CTYPE=C.UTF-8
export LC_ALL=C.UTF-8 export LC_ALL=C.UTF-8
export LANG=C.UTF-8 export LANG=C.UTF-8
@ -139,20 +143,23 @@
mkdir $out mkdir $out
''; '';
in { in
{
project = perSystem projectFor; project = perSystem projectFor;
flake = perSystem (system: (projectFor system).flake { }); flake = perSystem (system: (projectFor system).flake { });
packages = perSystem (system: packages = perSystem (system:
self.flake.${system}.packages // { self.flake.${system}.packages // {
haddock = let haddock =
agora-doc = self.flake.${system}.packages."agora:lib:agora".doc; let
pkgs = nixpkgsFor system; agora-doc = self.flake.${system}.packages."agora:lib:agora".doc;
in pkgs.runCommand "haddock-merge" { } '' pkgs = nixpkgsFor system;
cd ${self} in
mkdir $out pkgs.runCommand "haddock-merge" { } ''
cp -r ${agora-doc}/share/doc/* $out cd ${self}
''; mkdir $out
cp -r ${agora-doc}/share/doc/* $out
'';
}); });
# Define what we want to test # Define what we want to test
@ -163,9 +170,10 @@
agora-test = self.flake.${system}.packages."agora:test:agora-test"; agora-test = self.flake.${system}.packages."agora:test:agora-test";
}); });
check = perSystem (system: check = perSystem (system:
(nixpkgsFor system).runCommand "combined-test" { (nixpkgsFor system).runCommand "combined-test"
checksss = builtins.attrValues self.checks.${system}; {
} '' checksss = builtins.attrValues self.checks.${system};
} ''
echo $checksss echo $checksss
touch $out touch $out
''); '');