Skip to content

Commit

Permalink
Add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelpj committed Oct 14, 2021
1 parent 8ca8ba2 commit 698c1e4
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 29 deletions.
2 changes: 2 additions & 0 deletions doc/plutus-doc.cabal
Expand Up @@ -60,9 +60,11 @@ executable doc-doctests
template-haskell >=2.13.0.0,
bytestring -any,
cardano-api -any,
flat -any,
plutus-core -any,
plutus-tx -any,
plutus-ledger -any,
plutus-ledger-api -any,
plutus-contract -any,
playground-common -any,
plutus-use-cases -any,
Expand Down
34 changes: 29 additions & 5 deletions doc/plutus/howtos/exporting-a-script.rst
@@ -1,20 +1,44 @@
.. highlight:: haskell
.. _exporting_a_script:

How to export scripts, datums and redemmers
How to export scripts, datums and redeemers
===========================================

.. note::
This guide uses the scripts from the :ref:`basic validators tutorial <basic_validators_tutorial>`.

While most :term:`Plutus Application` s use scripts by directly submitting them as part of transactions from the application itself, it can be useful to be able to export a serialized script.
For example, you might want to submit it as part of a manually created transaction with the Cardano node CLI, send it to another party for them to use, or maybe just back it up.
Since scripts must match their on-chain hashes exactly, it is important that the scripts which an application uses do not accidentally change.
For example, changing the source code or updating dependencies or tooling may lead to small changes in the script - but since the hashes must match exactly, even small changes can be problematic.

For this reason, once you expect that you will not modify the on-chain part of your application more, it is sensible to *freeze* it by saving the final Plutus Core to a file.

Additionally, while most :term:`Plutus Application` s use scripts by directly submitting them as part of transactions from the application itself, it can be useful to be able to export a serialized script.
For example, you might want to submit it as part of a manually created transaction with the Cardano node CLI, or send it to another party for them to use.

Fortunately, it is quite simple to do this.
You can either translate directly into CBOR using the `Serialise` typeclass from the `serialise` package, or you can create an envelope of the sort used by the Cardano node CLI.
Most of the types have typeclass instances for ``Serialise`` which allows translating directly into CBOR.
This applies to ``Validator``, ``Redeemer``, and ``Datum`` types.
If you want to create values that you can pass to the Cardano CLI, you will need to convert them to the appropriate types from ``cardano-api`` and use ``serialiseToTextEnvelope``.

The same can also be done with `Datum` and `Redeemer` datatypes.

.. literalinclude:: ../tutorials/BasicValidators.hs
:start-after: BLOCK8
:end-before: BLOCK9

``CompiledCode`` has a different serialization method, ``Flat``, but the principle is the same.

The serialized form of ``CompiledCode`` can also be dumped using a plugin option:

.. code-block:: haskell
{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:dump-uplc #-}
This will dump the output to a temporary file with a name based on the module name.
The filename will be printed to the console when compiling the source file.
You can then move it to a more permanent location.

It can be read in conveniently with ``loadFromFile`` as an alternative to ``compile``.

.. literalinclude:: ../tutorials/BasicValidators.hs
:start-after: BLOCK9
:end-before: BLOCK10
2 changes: 1 addition & 1 deletion doc/plutus/howtos/index.rst
Expand Up @@ -11,4 +11,4 @@ How-to guides
exporting-a-script
writing-a-scalable-app
handling-blockchain-events
analysing-scripts
analysing-scripts
Empty file added doc/plutus/howtos/myscript.uplc
Empty file.
45 changes: 22 additions & 23 deletions doc/plutus/tutorials/BasicValidators.hs
Expand Up @@ -17,11 +17,11 @@ import Ledger.Ada
import Ledger.Typed.Scripts
import Ledger.Value

import Cardano.Api (HasTextEnvelope, TextEnvelope, TextEnvelopeDescr, serialiseToTextEnvelope)

import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL

import Codec.Serialise
import qualified Flat as Flat

import Prelude (IO, print, show)
import qualified Prelude as Haskell
Expand Down Expand Up @@ -111,28 +111,27 @@ dateValidatorHash = validatorHash dateInstance
dateValidator :: Validator
dateValidator = validatorScript dateInstance
-- BLOCK8
-- We can serialize a 'Validator's, 'Datum's, and 'Redeemer's directly to CBOR
serializedDateValidator :: BSL.ByteString
serializedDateValidator = serialise dateValidator

-- The module 'Ledger.Scripts' includes instances related to typeclass
-- 'Cardano.Api.HasTextEnvelope'

-- Envelope of the PLC 'Script'.
envelopeDateValidator :: TextEnvelope
envelopeDateValidator = serialiseToTextEnvelope Nothing (getValidator dateValidator)

-- Envelope of the 'Datum' representing the 'Date' datatype.
envelopeDate :: Date -> TextEnvelope
envelopeDate d = serialiseToTextEnvelope Nothing (Datum $ toBuiltinData d)

-- Envelope of the 'Redeemer' representing the 'EndDate' datatype.
envelopeEndDate :: EndDate -> TextEnvelope
envelopeEndDate d = serialiseToTextEnvelope Nothing (Redeemer $ toBuiltinData d)

main :: IO ()
main = do
serializedDate :: Date -> BSL.ByteString
serializedDate d = serialise (Datum $ toBuiltinData d)
serializedEndDate :: EndDate -> BSL.ByteString
serializedEndDate d = serialise (Redeemer $ toBuiltinData d)

-- The serialized forms can be written or read using normal Haskell IO functionality.
showSerialised :: IO ()
showSerialised = do
print serializedDateValidator
print envelopeDateValidator
print $ envelopeDate (Date 0)
print $ envelopeEndDate Never
print $ serializedDate (Date 0)
print $ serializedEndDate Never
-- BLOCK9
-- We can serialize 'CompiledCode' also
serializedCompiledCode :: BS.ByteString
serializedCompiledCode = Flat.flat $ $$(compile [|| validateDateTyped ||])

-- The 'loadFromFile' function is a drop-in replacement for 'compile', but
-- takes the file path instead of the code to compile.
validatorCodeFromFile :: CompiledCode (() -> () -> ScriptContext -> Bool)
validatorCodeFromFile = $$(loadFromFile "plutus/howtos/myscript.uplc")
-- BLOCK10

0 comments on commit 698c1e4

Please sign in to comment.