From 781d2221b3253cb259db11eee16b6294d66910c5 Mon Sep 17 00:00:00 2001 From: euonymos Date: Fri, 23 Dec 2022 19:36:37 -0600 Subject: [PATCH 1/2] add readTypedScriptWith --- ply-core/cabal.project | 1 + ply-core/src/Ply.hs | 3 ++- ply-core/src/Ply/Core/TypedReader.hs | 34 ++++++++++++++++++++++------ ply-core/src/Ply/Core/Typename.hs | 2 +- ply-core/src/Ply/Core/Types.hs | 4 ++-- ply-plutarch/cabal.project | 1 + 6 files changed, 34 insertions(+), 11 deletions(-) create mode 120000 ply-core/cabal.project create mode 120000 ply-plutarch/cabal.project diff --git a/ply-core/cabal.project b/ply-core/cabal.project new file mode 120000 index 0000000..d4ffa9a --- /dev/null +++ b/ply-core/cabal.project @@ -0,0 +1 @@ +cabal.project.core \ No newline at end of file diff --git a/ply-core/src/Ply.hs b/ply-core/src/Ply.hs index d74622e..5e452e6 100644 --- a/ply-core/src/Ply.hs +++ b/ply-core/src/Ply.hs @@ -8,6 +8,7 @@ module Ply ( typeName, PlyArg, readTypedScript, + readTypedScriptWith, getPlutusVersion, (#), (#$), @@ -17,7 +18,7 @@ module Ply ( import Ply.Core.Apply ((#), (#!), (#$), (#$!)) import Ply.Core.Class (PlyArg) -import Ply.Core.TypedReader (readTypedScript) +import Ply.Core.TypedReader (readTypedScript, readTypedScriptWith) import Ply.Core.Typename (typeName) import Ply.Core.Types ( ScriptReaderException (..), diff --git a/ply-core/src/Ply/Core/TypedReader.hs b/ply-core/src/Ply/Core/TypedReader.hs index ab2f7e8..1686ad8 100644 --- a/ply-core/src/Ply/Core/TypedReader.hs +++ b/ply-core/src/Ply/Core/TypedReader.hs @@ -1,10 +1,18 @@ {-# LANGUAGE UndecidableInstances #-} -module Ply.Core.TypedReader (TypedReader, readTypedScript, mkTypedScript) where +module Ply.Core.TypedReader ( + TypedReader, + readTypedScript, + readTypedScriptWith, + -- mkTypedScript, + -- mkTypedScriptWith, +) where import Control.Exception (throwIO) import Control.Monad (unless) +import Data.Coerce (coerce) import Data.Proxy (Proxy (Proxy)) +import Data.Text (Text) import Ply.Core.Deserialize (readEnvelope) import Ply.Core.Internal.Reify @@ -12,7 +20,7 @@ import Ply.Core.Types ( ScriptReaderException (ScriptRoleError, ScriptTypeError), ScriptRole (ValidatorRole), TypedScript (TypedScriptConstr), - TypedScriptEnvelope (TypedScriptEnvelope), + TypedScriptEnvelope (TypedScriptEnvelope), Typename(Typename), ) {- | Class of 'TypedScript' parameters that are supported and can be read. @@ -24,16 +32,17 @@ type TypedReader rl params = , ReifyTypenames params ) --- | Pure function to parse a 'TypedScript' from a 'TypedScriptEnvelope'. -mkTypedScript :: +mkTypedScriptWith :: forall rl params. TypedReader rl params => + (Text -> Text) -> TypedScriptEnvelope -> Either ScriptReaderException (TypedScript rl params) -mkTypedScript (TypedScriptEnvelope ver rol params _ prog) = do +mkTypedScriptWith mapping (TypedScriptEnvelope ver rol params _ prog) = do unless (rol == reifyRole (Proxy @rl)) . Left $ ScriptRoleError ValidatorRole rol let expectedParams = reifyTypenames $ Proxy @params - unless (expectedParams == params) . Left $ ScriptTypeError expectedParams params + let actualParams = coerce mapping <$> params + unless (expectedParams == actualParams) . Left $ ScriptTypeError expectedParams actualParams pure $ TypedScriptConstr ver prog {- | Read and verify a 'TypedScript' from given filepath. @@ -47,4 +56,15 @@ readTypedScript :: -- | File path where the typed script file is located. FilePath -> IO (TypedScript r params) -readTypedScript p = readEnvelope p >>= either throwIO pure . mkTypedScript +readTypedScript = readTypedScriptWith id + +readTypedScriptWith :: + TypedReader r params => + -- | Mapping for type named of script parameters. Useful if your script were serialized with + -- older version of ply, which would write type constructor name, or using old-style ledger types. + -- Mapping applies to Typename's coming in the envelop. + (Text -> Text) -> + -- | File path where the typed script file is located. + FilePath -> + IO (TypedScript r params) +readTypedScriptWith mapping p = readEnvelope p >>= either throwIO pure . mkTypedScriptWith mapping diff --git a/ply-core/src/Ply/Core/Typename.hs b/ply-core/src/Ply/Core/Typename.hs index 2f42b08..5d9045c 100644 --- a/ply-core/src/Ply/Core/Typename.hs +++ b/ply-core/src/Ply/Core/Typename.hs @@ -1,7 +1,7 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE BangPatterns #-} -module Ply.Core.Typename (Typename, typeName) where +module Ply.Core.Typename (Typename (Typename), typeName) where import Control.Monad (when) import Data.Aeson (FromJSON (parseJSON), ToJSON, Value (String)) diff --git a/ply-core/src/Ply/Core/Types.hs b/ply-core/src/Ply/Core/Types.hs index 489b044..7110621 100644 --- a/ply-core/src/Ply/Core/Types.hs +++ b/ply-core/src/Ply/Core/Types.hs @@ -6,7 +6,7 @@ module Ply.Core.Types ( ScriptRole (..), ScriptReaderException (..), TypedScriptEnvelope (..), - Typename, + Typename (Typename), UPLCProgram, ) where @@ -36,7 +36,7 @@ import PlutusLedgerApi.Common (deserialiseUPLC, serialiseUPLC) import UntypedPlutusCore (DeBruijn, DefaultFun, DefaultUni, Program) import Ply.Core.Serialize.Script (serializeScriptCbor) -import Ply.Core.Typename (Typename) +import Ply.Core.Typename (Typename (Typename)) type UPLCProgram = Program DeBruijn DefaultUni DefaultFun () diff --git a/ply-plutarch/cabal.project b/ply-plutarch/cabal.project new file mode 120000 index 0000000..4422513 --- /dev/null +++ b/ply-plutarch/cabal.project @@ -0,0 +1 @@ +cabal.project.plutarch \ No newline at end of file From 1346546f93ba9b5bead50dbe5f74583afbbba3ff Mon Sep 17 00:00:00 2001 From: euonymos Date: Mon, 23 Jan 2023 11:19:28 -0600 Subject: [PATCH 2/2] Update docs, code cosmetics --- CHANGELOG.md | 5 +++++ README.md | 19 +++++++++++++++++++ ply-core/cabal.project | 1 - ply-core/src/Ply/Core/TypedReader.hs | 17 ++++++++++------- ply-plutarch/cabal.project | 1 - 5 files changed, 34 insertions(+), 9 deletions(-) delete mode 120000 ply-core/cabal.project delete mode 120000 ply-plutarch/cabal.project diff --git a/CHANGELOG.md b/CHANGELOG.md index 201d346..6f8c1cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.4.1 - Mapping for Typename on loading + +`readTypedScriptWith` allows one to load scripts, which have been serialized with an older version of `ply` +to be loaded, see README.md for example. + # 0.3.0 - Plutus update, Plutarch 1.3, API changes There is no `Script` type in upstream Plutus anymore. As a result, `TypedScript` holds the UPLC program itself. diff --git a/README.md b/README.md index 7ce81cf..1d670ba 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,25 @@ main = do > Aside: Notice how I didn't use type applications, it got inferred from the surrounding context! +### Mapping for Typename + +The way `ply` stores scipts parameters type names has changed. Previously `Typename` was stored without +package qualifiers, so if you need to load scripts serialized quite a while ago, you might need a away +to convert type names. Use `readTypedScriptWith`, which takes an additional mapping. A sample mapping +to use with newer Plutus types might be as following: + +```haskell +paramMapping :: Text -> Text +paramMapping = \case + "Address" -> "PlutusLedgerApi.V1.Address:Address" + "Credential" -> "PlutusLedgerApi.V1.Credential:Credential" + "CurrencySymbol" -> "PlutusLedgerApi.V1.Value:CurrencySymbol" + "ValidatorHash" -> "PlutusLedgerApi.V1.Scripts:ScriptHash" + "TokenName" -> "PlutusLedgerApi.V1.Value:TokenName" + "Integer" -> "GHC.Num.Integer:Integer" + others -> others +``` + # Custom Types as Script Parameters By default, Ply supports most `plutus-ledger-api` types and you can use any of them as your script parameters. diff --git a/ply-core/cabal.project b/ply-core/cabal.project deleted file mode 120000 index d4ffa9a..0000000 --- a/ply-core/cabal.project +++ /dev/null @@ -1 +0,0 @@ -cabal.project.core \ No newline at end of file diff --git a/ply-core/src/Ply/Core/TypedReader.hs b/ply-core/src/Ply/Core/TypedReader.hs index 1686ad8..17f77e9 100644 --- a/ply-core/src/Ply/Core/TypedReader.hs +++ b/ply-core/src/Ply/Core/TypedReader.hs @@ -4,8 +4,6 @@ module Ply.Core.TypedReader ( TypedReader, readTypedScript, readTypedScriptWith, - -- mkTypedScript, - -- mkTypedScriptWith, ) where import Control.Exception (throwIO) @@ -20,7 +18,8 @@ import Ply.Core.Types ( ScriptReaderException (ScriptRoleError, ScriptTypeError), ScriptRole (ValidatorRole), TypedScript (TypedScriptConstr), - TypedScriptEnvelope (TypedScriptEnvelope), Typename(Typename), + TypedScriptEnvelope (TypedScriptEnvelope), + Typename (Typename), ) {- | Class of 'TypedScript' parameters that are supported and can be read. @@ -45,7 +44,8 @@ mkTypedScriptWith mapping (TypedScriptEnvelope ver rol params _ prog) = do unless (expectedParams == actualParams) . Left $ ScriptTypeError expectedParams actualParams pure $ TypedScriptConstr ver prog -{- | Read and verify a 'TypedScript' from given filepath. +{- | Read and verify a 'TypedScript' from given filepath. If you need to adjust type names use +'readTypedScriptWith' instead. The user is responsible for choosing the "correct" 'ScriptRole' and script parameters, probably with type applications. The reader will then use this information to parse the file and verify @@ -58,11 +58,14 @@ readTypedScript :: IO (TypedScript r params) readTypedScript = readTypedScriptWith id +{- | Like 'readTypedScript', but takes a mapper @(Text -> Text) @ for type names of a script +parameters. It might be useful if your script have been serialized with an older version of +@ply@, which would write type constructor name, or using old-style ledger types. Mapping +applies to @Typename@'s coming in the envelop. +-} readTypedScriptWith :: TypedReader r params => - -- | Mapping for type named of script parameters. Useful if your script were serialized with - -- older version of ply, which would write type constructor name, or using old-style ledger types. - -- Mapping applies to Typename's coming in the envelop. + -- | Mapping for type names of script parameters. (Text -> Text) -> -- | File path where the typed script file is located. FilePath -> diff --git a/ply-plutarch/cabal.project b/ply-plutarch/cabal.project deleted file mode 120000 index 4422513..0000000 --- a/ply-plutarch/cabal.project +++ /dev/null @@ -1 +0,0 @@ -cabal.project.plutarch \ No newline at end of file