trustless-sidechain-8.0.0: Smart contract code used by the partner-chains project.
Safe HaskellSafe-Inferred
LanguageHaskell2010

TrustlessSidechain.EncodeHelpers

Synopsis

Helpers for Data encoding

ToData

productToData2 :: forall (a :: Type) (b :: Type). (ToData a, ToData b) => a -> b -> BuiltinData #

Helper to write toBuiltinData for 2-products (something isomorphic to a pair).

Notes

This is necessary because, by default, the TH-driven Plutus derivation for a type such as this:

data Foo = Foo Integer Integer

Will encode as Constr 0. This is inefficient: we only have one 'arm', and the tag will always be the same for any valid value, but we have to carry it around anyway. This function instead encodes it as a list.

It is essential that this only be used together with productFromData2 (or its ticked equivalent) and productUnsafeFromData2; otherwise, the encodings may not roundtrip.

productFromData2 will verify that:

  • It is given a Plutus list;
  • That this list has exactly two elements; and
  • Each element of this list decodes to the correct type.

productUnsafeFromData2 will instead decode without error when:

  • It is given a Plutus list;
  • That this list has at least two elements; and
  • Each element of this list decodes to the correct type.

More precisely, productFromData2 verifies that it is given exactly the right amount of data, whereas productUnsafeFromData2 works when it is given /at least/ the right amount of data (but can be given more). This implies that if productFromData2 f dat = Just x, then productUnsafeFromData2 f dat = x, but that the converse does not necessarily hold. This (arguably unusual) behaviour matches the definitions generated by the Plutus-provided TH.

How to use this

data Foo = Foo Integer Integer

instance ToData Foo where
  {-# INLINEABLE toBuiltinData #-}
  toBuiltinData (Foo x y) = productToData2 x y

instance FromData Foo where
  {-# INLINEABLE fromBuiltinData #-}
  fromBuiltinData = productFromData2 Foo

instance UnsafeFromData Foo where
  {-# INLINEABLE unsafeFromBuiltinData #-}
  unsafeFromBuiltinData = productUnsafeFromData2 Foo

productToData3 :: forall (a :: Type) (b :: Type) (c :: Type). (ToData a, ToData b, ToData c) => a -> b -> c -> BuiltinData #

As productToData2, but for 3-products.

FromData

productFromData2 :: forall (a :: Type) (b :: Type) (c :: Type). (FromData a, FromData b) => (a -> b -> c) -> BuiltinData -> Maybe c #

Helper to write fromBuiltinData for 2-products (something isomorphic to a pair).

Note

See productToData2 for examples of use and why this is necessary.

Use this function if you don't need any verification beyond the components of the product decoding successfully.

productFromData2' :: forall (a :: Type) (b :: Type) (c :: Type). (FromData a, FromData b) => (a -> b -> Maybe c) -> BuiltinData -> Maybe c #

As productFromData2, but allows additional checks beyond the components successfully decoding.

productFromData3 :: forall (a :: Type) (b :: Type) (c :: Type) (d :: Type). (FromData a, FromData b, FromData c) => (a -> b -> c -> d) -> BuiltinData -> Maybe d #

As productFromData2, but for 3-products.

productFromData3' :: forall (a :: Type) (b :: Type) (c :: Type) (d :: Type). (FromData a, FromData b, FromData c) => (a -> b -> c -> Maybe d) -> BuiltinData -> Maybe d #

As productFromData3, but allows additional checks beyond the components successfully decoding.

UnsafeFromData

productUnsafeFromData2 :: forall (a :: Type) (b :: Type) (c :: Type). (UnsafeFromData a, UnsafeFromData b) => (a -> b -> c) -> BuiltinData -> c #

Helper to write unsafeFromBuiltinData for 2-products (something isomorphic to a pair).

Note

See productToData2 for examples of use, and why this is necessary.

productUnsafeFromData3 :: forall (a :: Type) (b :: Type) (c :: Type) (d :: Type). (UnsafeFromData a, UnsafeFromData b, UnsafeFromData c) => (a -> b -> c -> d) -> BuiltinData -> d #

As productUnsafeFromData2, but for 3-products.