Now makeEffect boilerplate requires datum to implemt PTryFrom

It will free `makeEffect` from using `unsafeCoerce` and force each
effect datums to implement their own "parsers".
This commit is contained in:
Seungheon Oh 2022-04-22 23:34:33 -05:00
parent 0ace0406d8
commit 9394b2f70b
4 changed files with 71 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,9 +33,7 @@ makeEffect gatCs' f =
ctx <- pletFields @'["txInfo", "purpose"] ctx' ctx <- pletFields @'["txInfo", "purpose"] ctx'
txInfo' <- plet ctx.txInfo txInfo' <- plet ctx.txInfo
-- TODO: Use PTryFrom (datum', _) <- ptryFrom @datum datum
let datum' :: Term _ datum
datum' = pfromData $ punsafeCoerce datum
PSpending txOutRef <- pmatch $ pfromData ctx.purpose PSpending txOutRef <- pmatch $ pfromData ctx.purpose
txOutRef' <- plet (pfield @"_0" # txOutRef) txOutRef' <- plet (pfield @"_0" # txOutRef)
@ -53,13 +47,3 @@ makeEffect gatCs' f =
passert "A single authority token has been burned" $ singleAuthorityTokenBurned gatCs txInfo' mint passert "A single authority token has been burned" $ singleAuthorityTokenBurned gatCs txInfo' mint
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
''); '');