Skip to content

Commit

Permalink
Note about unrolling types
Browse files Browse the repository at this point in the history
  • Loading branch information
Unisay committed Mar 11, 2024
1 parent 8af0543 commit c3b57a3
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
45 changes: 42 additions & 3 deletions plutus-tx/src/PlutusTx/Blueprint/Contract.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import PlutusTx.Blueprint.Validator (ValidatorBlueprint)

{- | A blueprint of a smart contract, as defined by the CIP-0057
The 'referencedTypes' phantom type parameter is used to track the types used in the contract
making sure their schemas are included in the blueprint and that they are referenced
in a type-safe way.
The 'referencedTypes' phantom type parameter is used to track the types used in the contract
making sure their schemas are included in the blueprint and that they are referenced
in a type-safe way.
-}
data ContractBlueprint (referencedTypes :: [Type]) = MkContractBlueprint
{ contractId :: Maybe Text
Expand All @@ -41,6 +41,45 @@ data ContractBlueprint (referencedTypes :: [Type]) = MkContractBlueprint
}
deriving stock (Show)

{- Note ["Unrolling" types]
ContractBlueprint needs to be parameterized by a list of types used in
a contract's type signature (including nested types) in order to:
a) produce a JSON-schema definition for every type used.
b) ensure that the schema definitions are referenced in a type-safe way.
Given the following contract validator's type signature:
typedValidator :: Redeemer -> Datum -> ScriptContext -> Bool
and the following data type definitions:
data Redeemer = MkRedeemer MyStruct
data MyStruct = MkMyStruct { field1 :: Integer, field2 :: Bool }
type Datum = ()
The ContractBlueprint type should be:
ContractBlueprint '[Redeemer, MyStruct, Integer, Bool, ()]
However, for contract blurprints authors specifying all the nested types manually is
cumbersome and error-prone. To make it easier to work with, we provide the Unroll type family
that can be used to traverse a type accumulating all types nested within it:
Unroll Redeemer ~ '[Redeemer, MyStruct, Integer, Bool]
UnrollAll '[Redeemer, Datum] ~ '[Redeemer, MyStruct, Integer, Bool, ()]
This way blueprint authors can specify the top-level types used in a contract and the UnrollAll
type family will take care of discovering all the nested types:
Blueprint '[Redeemer, Datum]
is equivalent to
ContractBlueprint '[Redeemer, MyStruct, Integer, Bool, ()]
-}

-- | A contract blueprint with all (nested) types discovered from a list of top-level types.
type Blueprint topTypes = ContractBlueprint (UnrollAll topTypes)

Expand Down
2 changes: 2 additions & 0 deletions plutus-tx/src/PlutusTx/Blueprint/Definition.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import PlutusTx.Blueprint.Schema (Schema (..))
import PlutusTx.Builtins.Internal (BuiltinByteString, BuiltinData, BuiltinList, BuiltinString,
BuiltinUnit)

-- For more context see the note ["Unrolling" types]

type family UnrollAll xs :: [Type] where
UnrollAll '[] = '[]
UnrollAll (x ': xs) = Unroll x ++ UnrollAll xs
Expand Down

0 comments on commit c3b57a3

Please sign in to comment.