-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Developer tools for the Michelson Language -- -- A library to make writing smart contracts in Michelson — the smart -- contract language of the Tezos blockchain — pleasant and effective. @package morley @version 0.4.0 -- | Commonly used parts of regular Prelude. module Lorentz.Prelude -- | Application operator. This operator is redundant, since ordinary -- application (f x) means the same as (f $ x). -- However, $ has low, right-associative binding precedence, so it -- sometimes allows parentheses to be omitted; for example: -- --
--   f $ g $ h x  =  f (g (h x))
--   
-- -- It is also useful in higher-order situations, such as map -- ($ 0) xs, or zipWith ($) fs xs. -- -- Note that ($) is levity-polymorphic in its result type, so -- that foo $ True where foo :: Bool -> Int# is well-typed ($) :: () => (a -> b) -> a -> b infixr 0 $ -- | Function composition. (.) :: () => (b -> c) -> (a -> b) -> a -> c infixr 9 . -- | Infix application. -- --
--   f :: Either String $ Maybe Int
--   =
--   f :: Either String (Maybe Int)
--   
type ($) (f :: k -> k1) (a :: k) = f a infixr 2 $ -- | The Eq class defines equality (==) and inequality -- (/=). All the basic datatypes exported by the Prelude -- are instances of Eq, and Eq may be derived for any -- datatype whose constituents are also instances of Eq. -- -- The Haskell Report defines no laws for Eq. However, == -- is customarily expected to implement an equivalence relationship where -- two values comparing equal are indistinguishable by "public" -- functions, with a "public" function being one not allowing to see -- implementation details. For example, for a type representing -- non-normalised natural numbers modulo 100, a "public" function doesn't -- make the difference between 1 and 201. It is expected to have the -- following properties: -- -- -- -- Minimal complete definition: either == or /=. class Eq a -- | The Ord class is used for totally ordered datatypes. -- -- Instances of Ord can be derived for any user-defined datatype -- whose constituent types are in Ord. The declared order of the -- constructors in the data declaration determines the ordering in -- derived Ord instances. The Ordering datatype allows a -- single comparison to determine the precise ordering of two objects. -- -- The Haskell Report defines no laws for Ord. However, -- <= is customarily expected to implement a non-strict partial -- order and have the following properties: -- -- -- -- Note that the following operator interactions are expected to hold: -- --
    --
  1. x >= y = y <= x
  2. --
  3. x < y = x <= y && x /= y
  4. --
  5. x > y = y < x
  6. --
  7. x < y = compare x y == LT
  8. --
  9. x > y = compare x y == GT
  10. --
  11. x == y = compare x y == EQ
  12. --
  13. min x y == if x <= y then x else y = True
  14. --
  15. max x y == if x >= y then x else y = True
  16. --
-- -- Minimal complete definition: either compare or <=. -- Using compare can be more efficient for complex types. class Eq a => Ord a -- | The Bounded class is used to name the upper and lower limits of -- a type. Ord is not a superclass of Bounded since types -- that are not totally ordered may also have upper and lower bounds. -- -- The Bounded class may be derived for any enumeration type; -- minBound is the first constructor listed in the data -- declaration and maxBound is the last. Bounded may also -- be derived for single-constructor datatypes whose constituent types -- are in Bounded. class Bounded a minBound :: Bounded a => a maxBound :: Bounded a => a -- | The class of semigroups (types with an associative binary operation). -- -- Instances should satisfy the associativity law: -- -- class Semigroup a -- | An associative operation. (<>) :: Semigroup a => a -> a -> a -- | Reduce a non-empty list with <> -- -- The default definition should be sufficient, but this can be -- overridden for efficiency. sconcat :: Semigroup a => NonEmpty a -> a -- | Repeat a value n times. -- -- Given that this works on a Semigroup it is allowed to fail if -- you request 0 or fewer repetitions, and the default definition will do -- so. -- -- By making this a member of the class, idempotent semigroups and -- monoids can upgrade this to execute in O(1) by picking -- stimes = stimesIdempotent or stimes = -- stimesIdempotentMonoid respectively. stimes :: (Semigroup a, Integral b) => b -> a -> a infixr 6 <> -- | The class of monoids (types with an associative binary operation that -- has an identity). Instances should satisfy the following laws: -- -- -- -- The method names refer to the monoid of lists under concatenation, but -- there are many other instances. -- -- Some types can be viewed as a monoid in more than one way, e.g. both -- addition and multiplication on numbers. In such cases we often define -- newtypes and make those instances of Monoid, e.g. -- Sum and Product. -- -- NOTE: Semigroup is a superclass of Monoid since -- base-4.11.0.0. class Semigroup a => Monoid a -- | Identity of mappend mempty :: Monoid a => a -- | An associative operation -- -- NOTE: This method is redundant and has the default -- implementation mappend = '(<>)' since -- base-4.11.0.0. mappend :: Monoid a => a -> a -> a -- | Fold a list using the monoid. -- -- For most types, the default definition for mconcat will be -- used, but the function is included in the class definition so that an -- optimized version can be provided for specific types. mconcat :: Monoid a => [a] -> a -- | Representable types of kind *. This class is derivable in GHC -- with the DeriveGeneric flag on. -- -- A Generic instance must satisfy the following laws: -- --
--   from . toid
--   to . fromid
--   
class Generic a -- | A space efficient, packed, unboxed Unicode text type. data Text -- | The Either type represents values with two possibilities: a -- value of type Either a b is either Left -- a or Right b. -- -- The Either type is sometimes used to represent a value which is -- either correct or an error; by convention, the Left constructor -- is used to hold an error value and the Right constructor is -- used to hold a correct value (mnemonic: "right" also means "correct"). -- --

Examples

-- -- The type Either String Int is the type -- of values which can be either a String or an Int. The -- Left constructor can be used only on Strings, and the -- Right constructor can be used only on Ints: -- --
--   >>> let s = Left "foo" :: Either String Int
--   
--   >>> s
--   Left "foo"
--   
--   >>> let n = Right 3 :: Either String Int
--   
--   >>> n
--   Right 3
--   
--   >>> :type s
--   s :: Either String Int
--   
--   >>> :type n
--   n :: Either String Int
--   
-- -- The fmap from our Functor instance will ignore -- Left values, but will apply the supplied function to values -- contained in a Right: -- --
--   >>> let s = Left "foo" :: Either String Int
--   
--   >>> let n = Right 3 :: Either String Int
--   
--   >>> fmap (*2) s
--   Left "foo"
--   
--   >>> fmap (*2) n
--   Right 6
--   
-- -- The Monad instance for Either allows us to chain -- together multiple actions which may fail, and fail overall if any of -- the individual steps failed. First we'll write a function that can -- either parse an Int from a Char, or fail. -- --
--   >>> import Data.Char ( digitToInt, isDigit )
--   
--   >>> :{
--       let parseEither :: Char -> Either String Int
--           parseEither c
--             | isDigit c = Right (digitToInt c)
--             | otherwise = Left "parse error"
--   
--   >>> :}
--   
-- -- The following should work, since both '1' and '2' -- can be parsed as Ints. -- --
--   >>> :{
--       let parseMultiple :: Either String Int
--           parseMultiple = do
--             x <- parseEither '1'
--             y <- parseEither '2'
--             return (x + y)
--   
--   >>> :}
--   
-- --
--   >>> parseMultiple
--   Right 3
--   
-- -- But the following should fail overall, since the first operation where -- we attempt to parse 'm' as an Int will fail: -- --
--   >>> :{
--       let parseMultiple :: Either String Int
--           parseMultiple = do
--             x <- parseEither 'm'
--             y <- parseEither '2'
--             return (x + y)
--   
--   >>> :}
--   
-- --
--   >>> parseMultiple
--   Left "parse error"
--   
data Either a b Left :: a -> Either a b Right :: b -> Either a b -- | The Maybe type encapsulates an optional value. A value of type -- Maybe a either contains a value of type a -- (represented as Just a), or it is empty (represented -- as Nothing). Using Maybe is a good way to deal with -- errors or exceptional cases without resorting to drastic measures such -- as error. -- -- The Maybe type is also a monad. It is a simple kind of error -- monad, where all errors are represented by Nothing. A richer -- error monad can be built using the Either type. data Maybe a Nothing :: Maybe a Just :: a -> Maybe a -- | Proxy is a type that holds no data, but has a phantom parameter -- of arbitrary type (or even kind). Its use is to provide type -- information, even though there is no value available of that type (or -- it may be too costly to create one). -- -- Historically, Proxy :: Proxy a is a safer -- alternative to the 'undefined :: a' idiom. -- --
--   >>> Proxy :: Proxy (Void, Int -> Int)
--   Proxy
--   
-- -- Proxy can even hold types of higher kinds, -- --
--   >>> Proxy :: Proxy Either
--   Proxy
--   
-- --
--   >>> Proxy :: Proxy Functor
--   Proxy
--   
-- --
--   >>> Proxy :: Proxy complicatedStructure
--   Proxy
--   
data Proxy (t :: k) :: forall k. () => k -> Type Proxy :: Proxy fromString :: IsString a => String -> a -- | undefined that leaves a warning in code on every usage. undefined :: HasCallStack => a -- | error that takes Text as an argument. error :: HasCallStack => Text -> a module Michelson.ErrorPos mkPos :: Int -> Pos newtype Pos Pos :: Word -> Pos data SrcPos SrcPos :: Pos -> Pos -> SrcPos srcPos :: Word -> Word -> SrcPos data InstrCallStack InstrCallStack :: LetCallStack -> SrcPos -> InstrCallStack [icsCallStack] :: InstrCallStack -> LetCallStack [icsSrcPos] :: InstrCallStack -> SrcPos type LetCallStack = [LetName] newtype LetName LetName :: Text -> LetName instance Data.Data.Data Michelson.ErrorPos.InstrCallStack instance GHC.Generics.Generic Michelson.ErrorPos.InstrCallStack instance GHC.Show.Show Michelson.ErrorPos.InstrCallStack instance GHC.Classes.Ord Michelson.ErrorPos.InstrCallStack instance GHC.Classes.Eq Michelson.ErrorPos.InstrCallStack instance GHC.Generics.Generic Michelson.ErrorPos.LetName instance Data.Data.Data Michelson.ErrorPos.LetName instance GHC.Show.Show Michelson.ErrorPos.LetName instance GHC.Classes.Ord Michelson.ErrorPos.LetName instance GHC.Classes.Eq Michelson.ErrorPos.LetName instance Data.Data.Data Michelson.ErrorPos.SrcPos instance GHC.Generics.Generic Michelson.ErrorPos.SrcPos instance GHC.Show.Show Michelson.ErrorPos.SrcPos instance GHC.Classes.Ord Michelson.ErrorPos.SrcPos instance GHC.Classes.Eq Michelson.ErrorPos.SrcPos instance Data.Data.Data Michelson.ErrorPos.Pos instance GHC.Generics.Generic Michelson.ErrorPos.Pos instance GHC.Show.Show Michelson.ErrorPos.Pos instance GHC.Classes.Ord Michelson.ErrorPos.Pos instance GHC.Classes.Eq Michelson.ErrorPos.Pos instance Data.Default.Class.Default Michelson.ErrorPos.InstrCallStack instance Data.Aeson.Types.ToJSON.ToJSON Michelson.ErrorPos.InstrCallStack instance Data.Aeson.Types.FromJSON.FromJSON Michelson.ErrorPos.InstrCallStack instance Data.Aeson.Types.ToJSON.ToJSON Michelson.ErrorPos.LetName instance Data.Aeson.Types.FromJSON.FromJSON Michelson.ErrorPos.LetName instance Data.Default.Class.Default Michelson.ErrorPos.SrcPos instance Data.Aeson.Types.ToJSON.ToJSON Michelson.ErrorPos.SrcPos instance Data.Aeson.Types.FromJSON.FromJSON Michelson.ErrorPos.SrcPos instance Data.Default.Class.Default Michelson.ErrorPos.Pos instance Data.Aeson.Types.ToJSON.ToJSON Michelson.ErrorPos.Pos instance Data.Aeson.Types.FromJSON.FromJSON Michelson.ErrorPos.Pos module Michelson.Printer.Util -- | Generalize converting a type into a Text.PrettyPrint.Leijen.Text.Doc. -- Used to pretty print Michelson code and define Fmt.Buildable -- instances. class RenderDoc a renderDoc :: RenderDoc a => RenderContext -> a -> Doc -- | Whether a value can be represented in Michelson code. Normally either -- all values of some type are renderable or not renderable. However, in -- case of instructions we have extra instructions which should not be -- rendered. Note: it's not suficcient to just return mempty for -- such instructions, because sometimes we want to print lists of -- instructions and we need to ignore them complete (to avoid putting -- redundant separators). isRenderable :: RenderDoc a => a -> Bool -- | A new type that can wrap values so that the RenderDoc instances of the -- combined value can have a different behavior for the pretty printer. newtype Prettier a Prettier :: a -> Prettier a -- | Convert Doc to Text with a line width of 80. printDoc :: Bool -> Doc -> Text -- | Generic way to render the different op types that get passed to a -- contract. renderOps :: RenderDoc op => Bool -> NonEmpty op -> Doc renderOpsList :: RenderDoc op => Bool -> [op] -> Doc -- | Create a specific number of spaces. spaces :: Int -> Doc -- | Wrap documents in parentheses if there are two or more in the list. wrapInParens :: RenderContext -> NonEmpty Doc -> Doc -- | Turn something that is instance of RenderDoc into a -- Builder. It's formatted the same way as printDoc formats -- docs. buildRenderDoc :: RenderDoc a => a -> Builder -- | Environment carried during recursive rendering. data RenderContext -- | ParensNeeded constant. needsParens :: RenderContext -- | ParensNeeded constant. doesntNeedParens :: RenderContext -- | Add parentheses if needed. addParens :: RenderContext -> Doc -> Doc -- | Ensure parentheses are not required, for case when you cannot sensibly -- wrap your expression into them. assertParensNotNeeded :: HasCallStack => RenderContext -> a -> a -- | Testing utility functions used by testing framework itself or intended -- to be used by test writers. module Michelson.Test.Util leftToShowPanic :: (Show e, HasCallStack) => Either e a -> a leftToPrettyPanic :: (Buildable e, HasCallStack) => Either e a -> a -- | A Property that always failes with given message. failedProp :: Text -> Property -- | A Property that always succeeds. succeededProp :: Property -- | The Property holds on `Left a`. qcIsLeft :: Show b => Either a b -> Property -- | The Property holds on `Right b`. qcIsRight :: Show a => Either a b -> Property module Michelson.Typed.Haskell.Instr.Helpers -- | Which branch to choose in generic tree representation: left, straight -- or right. S is used when there is one constructor with one -- field (something newtype-like). -- -- The reason why we need S can be explained by this example: data -- A = A1 B | A2 Integer data B = B Bool Now we may search for A1 -- constructor or B constructor. Without S in both cases path will -- be the same ([L]). data Branch L :: Branch S :: Branch R :: Branch -- | Path to a leaf (some field or constructor) in generic tree -- representation. type Path = [Branch] -- | Michelson annotations in untyped model. module Michelson.Untyped.Annotation newtype Annotation tag Annotation :: Text -> Annotation tag pattern WithAnn :: Annotation tag -> Annotation tag type TypeAnn = Annotation TypeTag type FieldAnn = Annotation FieldTag type VarAnn = Annotation VarTag type SomeAnn = Annotation SomeTag noAnn :: Annotation a ann :: Text -> Annotation a renderAnn :: forall tag. KnownAnnTag tag => Annotation tag -> Doc -- | Prints empty prefix in case of noAnn. -- -- Such functionality is required in case when instruction has two -- annotations of the same type, former is empty and the latter is not. -- So that `PAIR noAnn noAnn noAnn %kek` is printed as `PAIR % %kek` renderWEAnn :: forall tag. KnownAnnTag tag => Annotation tag -> Doc unifyAnn :: Annotation tag -> Annotation tag -> Maybe (Annotation tag) ifAnnUnified :: Annotation tag -> Annotation tag -> Bool disjoinVn :: VarAnn -> (VarAnn, VarAnn) convAnn :: Annotation tag1 -> Annotation tag2 instance forall k (tag :: k). Data.Aeson.Types.ToJSON.ToJSON (Michelson.Untyped.Annotation.Annotation tag) instance forall k (tag :: k). Data.Aeson.Types.FromJSON.FromJSON (Michelson.Untyped.Annotation.Annotation tag) instance forall k (tag :: k). Data.String.IsString (Michelson.Untyped.Annotation.Annotation tag) instance forall k (tag :: k). GHC.Generics.Generic (Michelson.Untyped.Annotation.Annotation tag) instance GHC.Base.Functor Michelson.Untyped.Annotation.Annotation instance forall k (tag :: k). (Data.Typeable.Internal.Typeable tag, Data.Typeable.Internal.Typeable k) => Data.Data.Data (Michelson.Untyped.Annotation.Annotation tag) instance forall k (tag :: k). GHC.Classes.Eq (Michelson.Untyped.Annotation.Annotation tag) instance GHC.Base.Semigroup Michelson.Untyped.Annotation.VarAnn instance GHC.Base.Monoid Michelson.Untyped.Annotation.VarAnn instance Michelson.Untyped.Annotation.KnownAnnTag Michelson.Untyped.Annotation.VarTag instance Michelson.Untyped.Annotation.KnownAnnTag Michelson.Untyped.Annotation.FieldTag instance Michelson.Untyped.Annotation.KnownAnnTag Michelson.Untyped.Annotation.TypeTag instance forall k (tag :: k). Michelson.Untyped.Annotation.KnownAnnTag tag => GHC.Show.Show (Michelson.Untyped.Annotation.Annotation tag) instance forall k (tag :: k). Michelson.Untyped.Annotation.KnownAnnTag tag => Michelson.Printer.Util.RenderDoc (Michelson.Untyped.Annotation.Annotation tag) instance forall k (tag :: k). Michelson.Untyped.Annotation.KnownAnnTag tag => Formatting.Buildable.Buildable (Michelson.Untyped.Annotation.Annotation tag) instance forall k (tag :: k). Data.Default.Class.Default (Michelson.Untyped.Annotation.Annotation tag) -- | Michelson types represented in untyped model. module Michelson.Untyped.Type data Type Type :: T -> TypeAnn -> Type data Comparable Comparable :: CT -> TypeAnn -> Comparable compToType :: Comparable -> Type typeToComp :: Type -> Maybe Comparable data T Tc :: CT -> T TKey :: T TUnit :: T TSignature :: T TChainId :: T TOption :: Type -> T TList :: Type -> T TSet :: Comparable -> T TOperation :: T TContract :: Type -> T TPair :: FieldAnn -> FieldAnn -> Type -> Type -> T TOr :: FieldAnn -> FieldAnn -> Type -> Type -> T TLambda :: Type -> Type -> T TMap :: Comparable -> Type -> T TBigMap :: Comparable -> Type -> T data CT CInt :: CT CNat :: CT CString :: CT CBytes :: CT CMutez :: CT CBool :: CT CKeyHash :: CT CTimestamp :: CT CAddress :: CT pattern Tint :: T pattern Tnat :: T pattern Tstring :: T pattern Tbytes :: T pattern Tmutez :: T pattern Tbool :: T pattern Tkey_hash :: T pattern Ttimestamp :: T pattern Taddress :: T tint :: T tnat :: T tstring :: T tbytes :: T tmutez :: T tbool :: T tkeyHash :: T ttimestamp :: T taddress :: T toption :: Type -> T tpair :: Type -> Type -> T tor :: Type -> Type -> T tyint :: Type tynat :: Type tyunit :: Type tybool :: Type typair :: Type -> Type -> Type tyor :: Type -> Type -> Type -- | For implicit account, which type its parameter seems to have from -- outside. tyImplicitAccountParam :: Type isAtomicType :: Type -> Bool isKey :: Type -> Bool isSignature :: Type -> Bool isComparable :: Type -> Bool isMutez :: Type -> Bool isKeyHash :: Type -> Bool isBool :: Type -> Bool isString :: Type -> Bool isInteger :: Type -> Bool isTimestamp :: Type -> Bool isNat :: Type -> Bool isInt :: Type -> Bool isBytes :: Type -> Bool instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Type.CT instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Type.CT instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Type.T instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Type.T instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Type.Comparable instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Type.Comparable instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Type.Type instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Type.Type instance GHC.Generics.Generic Michelson.Untyped.Type.Type instance Data.Data.Data Michelson.Untyped.Type.Type instance GHC.Show.Show Michelson.Untyped.Type.Type instance GHC.Classes.Eq Michelson.Untyped.Type.Type instance GHC.Generics.Generic Michelson.Untyped.Type.T instance Data.Data.Data Michelson.Untyped.Type.T instance GHC.Show.Show Michelson.Untyped.Type.T instance GHC.Classes.Eq Michelson.Untyped.Type.T instance GHC.Generics.Generic Michelson.Untyped.Type.Comparable instance Data.Data.Data Michelson.Untyped.Type.Comparable instance GHC.Show.Show Michelson.Untyped.Type.Comparable instance GHC.Classes.Eq Michelson.Untyped.Type.Comparable instance GHC.Generics.Generic Michelson.Untyped.Type.CT instance GHC.Enum.Bounded Michelson.Untyped.Type.CT instance GHC.Enum.Enum Michelson.Untyped.Type.CT instance Data.Data.Data Michelson.Untyped.Type.CT instance GHC.Show.Show Michelson.Untyped.Type.CT instance GHC.Classes.Ord Michelson.Untyped.Type.CT instance GHC.Classes.Eq Michelson.Untyped.Type.CT instance Michelson.Printer.Util.RenderDoc (Michelson.Printer.Util.Prettier Michelson.Untyped.Type.Type) instance Michelson.Printer.Util.RenderDoc Michelson.Untyped.Type.Type instance Michelson.Printer.Util.RenderDoc Michelson.Untyped.Type.T instance Formatting.Buildable.Buildable Michelson.Untyped.Type.Type instance Formatting.Buildable.Buildable Michelson.Untyped.Type.T instance Michelson.Printer.Util.RenderDoc Michelson.Untyped.Type.Comparable instance Formatting.Buildable.Buildable Michelson.Untyped.Type.Comparable instance Michelson.Printer.Util.RenderDoc Michelson.Untyped.Type.CT instance Formatting.Buildable.Buildable Michelson.Untyped.Type.CT module Michelson.Untyped.Ext -- | Implementation-specific instructions embedded in a NOP -- primitive, which mark a specific point during a contract's -- typechecking or execution. -- -- These instructions are not allowed to modify the contract's stack, but -- may impose additional constraints that can cause a contract to report -- errors in type-checking or testing. -- -- Additionaly, some implementation-specific language features such as -- type-checking of LetMacros are implemented using this -- mechanism (specifically FN and FN_END). data ExtInstrAbstract op -- | Matches current stack against a type-pattern STACKTYPE :: StackTypePattern -> ExtInstrAbstract op -- | A typed stack function (push and pop a TcExtFrame) FN :: Text -> StackFn -> [op] -> ExtInstrAbstract op -- | Copy the current stack and run an inline assertion on it UTEST_ASSERT :: TestAssert op -> ExtInstrAbstract op -- | Print a comment with optional embedded StackRefs UPRINT :: PrintComment -> ExtInstrAbstract op -- | A reference into the stack. newtype StackRef StackRef :: Natural -> StackRef newtype PrintComment PrintComment :: [Either Text StackRef] -> PrintComment [unUPrintComment] :: PrintComment -> [Either Text StackRef] data TestAssert op TestAssert :: Text -> PrintComment -> [op] -> TestAssert op [tassName] :: TestAssert op -> Text [tassComment] :: TestAssert op -> PrintComment [tassInstrs] :: TestAssert op -> [op] newtype Var Var :: Text -> Var -- | A type-variable or a type-constant data TyVar VarID :: Var -> TyVar TyCon :: Type -> TyVar -- | A stack pattern-match data StackTypePattern StkEmpty :: StackTypePattern StkRest :: StackTypePattern StkCons :: TyVar -> StackTypePattern -> StackTypePattern -- | A stack function that expresses the type signature of a -- LetMacro data StackFn StackFn :: Maybe (Set Var) -> StackTypePattern -> StackTypePattern -> StackFn [quantifiedVars] :: StackFn -> Maybe (Set Var) [inPattern] :: StackFn -> StackTypePattern [outPattern] :: StackFn -> StackTypePattern -- | Get the set of variables in a stack pattern varSet :: StackTypePattern -> Set Var -- | Convert StackTypePattern to a list of types. Also returns -- Bool which is True if the pattern is a fixed list of -- types and False if it's a pattern match on the head of the -- stack. stackTypePatternToList :: StackTypePattern -> ([TyVar], Bool) instance Data.Aeson.Types.ToJSON.ToJSON op => Data.Aeson.Types.ToJSON.ToJSON (Michelson.Untyped.Ext.TestAssert op) instance Data.Aeson.Types.FromJSON.FromJSON op => Data.Aeson.Types.FromJSON.FromJSON (Michelson.Untyped.Ext.TestAssert op) instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Ext.TyVar instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Ext.TyVar instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Ext.Var instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Ext.Var instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Ext.StackFn instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Ext.StackFn instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Ext.StackRef instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Ext.StackRef instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Ext.StackTypePattern instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Ext.StackTypePattern instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Ext.PrintComment instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Ext.PrintComment instance Data.Aeson.Types.ToJSON.ToJSON op => Data.Aeson.Types.ToJSON.ToJSON (Michelson.Untyped.Ext.ExtInstrAbstract op) instance Data.Aeson.Types.FromJSON.FromJSON op => Data.Aeson.Types.FromJSON.FromJSON (Michelson.Untyped.Ext.ExtInstrAbstract op) instance GHC.Base.Functor Michelson.Untyped.Ext.ExtInstrAbstract instance GHC.Generics.Generic (Michelson.Untyped.Ext.ExtInstrAbstract op) instance Data.Data.Data op => Data.Data.Data (Michelson.Untyped.Ext.ExtInstrAbstract op) instance GHC.Show.Show op => GHC.Show.Show (Michelson.Untyped.Ext.ExtInstrAbstract op) instance GHC.Classes.Eq op => GHC.Classes.Eq (Michelson.Untyped.Ext.ExtInstrAbstract op) instance GHC.Generics.Generic (Michelson.Untyped.Ext.TestAssert op) instance Data.Data.Data op => Data.Data.Data (Michelson.Untyped.Ext.TestAssert op) instance GHC.Base.Functor Michelson.Untyped.Ext.TestAssert instance GHC.Show.Show op => GHC.Show.Show (Michelson.Untyped.Ext.TestAssert op) instance GHC.Classes.Eq op => GHC.Classes.Eq (Michelson.Untyped.Ext.TestAssert op) instance GHC.Generics.Generic Michelson.Untyped.Ext.PrintComment instance Data.Data.Data Michelson.Untyped.Ext.PrintComment instance GHC.Show.Show Michelson.Untyped.Ext.PrintComment instance GHC.Classes.Eq Michelson.Untyped.Ext.PrintComment instance GHC.Generics.Generic Michelson.Untyped.Ext.StackFn instance Data.Data.Data Michelson.Untyped.Ext.StackFn instance GHC.Show.Show Michelson.Untyped.Ext.StackFn instance GHC.Classes.Eq Michelson.Untyped.Ext.StackFn instance GHC.Generics.Generic Michelson.Untyped.Ext.StackTypePattern instance Data.Data.Data Michelson.Untyped.Ext.StackTypePattern instance GHC.Show.Show Michelson.Untyped.Ext.StackTypePattern instance GHC.Classes.Eq Michelson.Untyped.Ext.StackTypePattern instance GHC.Generics.Generic Michelson.Untyped.Ext.TyVar instance Data.Data.Data Michelson.Untyped.Ext.TyVar instance GHC.Show.Show Michelson.Untyped.Ext.TyVar instance GHC.Classes.Eq Michelson.Untyped.Ext.TyVar instance GHC.Generics.Generic Michelson.Untyped.Ext.Var instance Data.Data.Data Michelson.Untyped.Ext.Var instance GHC.Classes.Ord Michelson.Untyped.Ext.Var instance GHC.Show.Show Michelson.Untyped.Ext.Var instance GHC.Classes.Eq Michelson.Untyped.Ext.Var instance GHC.Generics.Generic Michelson.Untyped.Ext.StackRef instance Data.Data.Data Michelson.Untyped.Ext.StackRef instance GHC.Show.Show Michelson.Untyped.Ext.StackRef instance GHC.Classes.Eq Michelson.Untyped.Ext.StackRef instance Michelson.Printer.Util.RenderDoc op => Michelson.Printer.Util.RenderDoc (Michelson.Untyped.Ext.ExtInstrAbstract op) instance Formatting.Buildable.Buildable op => Formatting.Buildable.Buildable (Michelson.Untyped.Ext.ExtInstrAbstract op) instance Formatting.Buildable.Buildable code => Formatting.Buildable.Buildable (Michelson.Untyped.Ext.TestAssert code) instance Formatting.Buildable.Buildable Michelson.Untyped.Ext.PrintComment instance Formatting.Buildable.Buildable Michelson.Untyped.Ext.StackFn instance Formatting.Buildable.Buildable Michelson.Untyped.Ext.StackTypePattern instance Formatting.Buildable.Buildable Michelson.Untyped.Ext.TyVar instance Formatting.Buildable.Buildable Michelson.Untyped.Ext.Var instance Formatting.Buildable.Buildable Michelson.Untyped.Ext.StackRef -- | Michelson contract in untyped model. module Michelson.Untyped.Contract type Parameter = Type type Storage = Type data Contract' op Contract :: Parameter -> Storage -> [op] -> Contract' op [para] :: Contract' op -> Parameter [stor] :: Contract' op -> Storage [code] :: Contract' op -> [op] instance Data.Aeson.Types.ToJSON.ToJSON op => Data.Aeson.Types.ToJSON.ToJSON (Michelson.Untyped.Contract.Contract' op) instance Data.Aeson.Types.FromJSON.FromJSON op => Data.Aeson.Types.FromJSON.FromJSON (Michelson.Untyped.Contract.Contract' op) instance GHC.Generics.Generic (Michelson.Untyped.Contract.Contract' op) instance Data.Data.Data op => Data.Data.Data (Michelson.Untyped.Contract.Contract' op) instance GHC.Base.Functor Michelson.Untyped.Contract.Contract' instance GHC.Show.Show op => GHC.Show.Show (Michelson.Untyped.Contract.Contract' op) instance GHC.Classes.Eq op => GHC.Classes.Eq (Michelson.Untyped.Contract.Contract' op) instance Michelson.Printer.Util.RenderDoc op => Michelson.Printer.Util.RenderDoc (Michelson.Untyped.Contract.Contract' op) instance Michelson.Printer.Util.RenderDoc op => Formatting.Buildable.Buildable (Michelson.Untyped.Contract.Contract' op) -- | Module, providing CT and T data types, representing -- Michelson language types without annotations. module Michelson.Typed.T data CT CInt :: CT CNat :: CT CString :: CT CBytes :: CT CMutez :: CT CBool :: CT CKeyHash :: CT CTimestamp :: CT CAddress :: CT -- | Michelson language type with annotations stripped off. data T Tc :: CT -> T TKey :: T TUnit :: T TSignature :: T TChainId :: T TOption :: T -> T TList :: T -> T TSet :: CT -> T TOperation :: T TContract :: T -> T TPair :: T -> T -> T TOr :: T -> T -> T TLambda :: T -> T -> T TMap :: CT -> T -> T TBigMap :: CT -> T -> T -- | Converts from T to Type. toUType :: T -> Type -- | Format type stack in a pretty way. buildStack :: [T] -> Builder instance GHC.Show.Show Michelson.Typed.T.T instance GHC.Classes.Eq Michelson.Typed.T.T instance Formatting.Buildable.Buildable Michelson.Typed.T.T -- | Module, providing singleton boilerplate for T and CT -- data types. -- -- Some functions from Data.Singletons are provided alternative version -- here. Some instances which are usually generated with TH are manually -- implemented as they require some specific constraints, namely -- Typeable and/or Converge, not provided in instances -- generated by TH. module Michelson.Typed.Sing -- | The singleton kind-indexed data family. data family Sing (a :: k) :: Type -- | Version of withSomeSing with Typeable constraint -- provided to processing function. -- -- Required for not to erase these useful constraints when doing -- conversion from value of type T to its singleton -- representation. withSomeSingT :: T -> (forall (a :: T). (Typeable a, SingI a) => Sing a -> r) -> r -- | Version of withSomeSing with Typeable constraint -- provided to processing function. -- -- Required for not to erase this useful constraint when doing conversion -- from value of type CT to its singleton representation. withSomeSingCT :: CT -> (forall (a :: CT). (SingI a, Typeable a) => Sing a -> r) -> r -- | Version of fromSing specialized for use with data instance -- Sing :: T -> Type which requires Typeable constraint -- for some of its constructors fromSingT :: Sing (a :: T) -> T fromSingCT :: Sing (a :: CT) -> CT instance Data.Singletons.Internal.SingKind Michelson.Typed.T.T instance Data.Singletons.Internal.SingKind Michelson.Untyped.Type.CT instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CInt instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CNat instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CString instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CBytes instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CMutez instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CBool instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CKeyHash instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CTimestamp instance Data.Singletons.Internal.SingI 'Michelson.Untyped.Type.CAddress instance (Data.Singletons.Internal.SingI t, Data.Typeable.Internal.Typeable t) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.Tc t) instance Data.Singletons.Internal.SingI 'Michelson.Typed.T.TKey instance Data.Singletons.Internal.SingI 'Michelson.Typed.T.TUnit instance Data.Singletons.Internal.SingI 'Michelson.Typed.T.TSignature instance Data.Singletons.Internal.SingI 'Michelson.Typed.T.TChainId instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TOption a) instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TList a) instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TSet a) instance Data.Singletons.Internal.SingI 'Michelson.Typed.T.TOperation instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TContract a) instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable b, Data.Singletons.Internal.SingI b) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TPair a b) instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable b, Data.Singletons.Internal.SingI b) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TOr a b) instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable b, Data.Singletons.Internal.SingI b) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TLambda a b) instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable b, Data.Singletons.Internal.SingI b) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TMap a b) instance (Data.Singletons.Internal.SingI a, Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable b, Data.Singletons.Internal.SingI b) => Data.Singletons.Internal.SingI ('Michelson.Typed.T.TBigMap a b) -- | Module, containing restrictions imposed by instruction or value scope. -- -- Michelson have multiple restrictions on values, examples: * -- operation type cannot appear in parameter. * big_map -- type cannot appear in PUSH-able constants. * -- contract type cannot appear in type we UNPACK to. -- -- Thus we declare multiple "scopes" - constraints applied in -- corresponding situations, for instance * ParameterScope; * -- StorageScope; * ConstantScope. -- -- Also we separate multiple "classes" of scope-related constraints. -- -- module Michelson.Typed.Scope -- | Alias for constraints which Michelson applies to parameter. type ParameterScope t = (Typeable t, SingI t, HasNoOp t, HasNoNestedBigMaps t) -- | Alias for constraints which Michelson applies to contract storage. type StorageScope t = (Typeable t, SingI t, HasNoOp t, HasNoNestedBigMaps t, HasNoContract t) -- | Alias for constraints which Michelson applies to pushed constants. type ConstantScope t = (SingI t, HasNoOp t, HasNoBigMap t, HasNoContract t) -- | Alias for constraints which Michelson applies to packed values. type PackedValScope t = (SingI t, HasNoOp t, HasNoBigMap t) -- | Alias for constraints which Michelson applies to unpacked values. -- -- It is different from PackedValScope, e.g. contract -- type cannot appear in a value we unpack to. type UnpackedValScope t = (PackedValScope t, ConstantScope t) -- | Alias for constraints which are required for printing. type PrintedValScope t = (SingI t, HasNoOp t) type ProperParameterBetterErrors t = (Typeable t, SingI t, ForbidOp t, ForbidNestedBigMaps t) type ProperStorageBetterErrors t = (Typeable t, SingI t, ForbidOp t, ForbidNestedBigMaps t, ForbidContract t) type ProperConstantBetterErrors t = (SingI t, ForbidOp t, ForbidBigMap t, ForbidContract t) type ProperPackedValBetterErrors t = (SingI t, ForbidOp t, ForbidBigMap t) type ProperUnpackedValBetterErrors t = (ProperPackedValBetterErrors t, ProperConstantBetterErrors t) type ProperPrintedValBetterErrors t = (SingI t, ForbidOp t) properParameterEvi :: forall t. ProperParameterBetterErrors t :- ParameterScope t properStorageEvi :: forall t. ProperStorageBetterErrors t :- StorageScope t properConstantEvi :: forall t. ProperConstantBetterErrors t :- ConstantScope t properPackedValEvi :: forall t. ProperPackedValBetterErrors t :- PackedValScope t properUnpackedValEvi :: forall t. ProperUnpackedValBetterErrors t :- UnpackedValScope t properPrintedValEvi :: forall t. ProperPrintedValBetterErrors t :- PrintedValScope t -- | This is the type of entailment. -- -- a :- b is read as a "entails" b. -- -- With this we can actually build a category for Constraint -- resolution. -- -- e.g. -- -- Because Eq a is a superclass of Ord a, -- we can show that Ord a entails Eq a. -- -- Because instance Ord a => Ord [a] exists, we -- can show that Ord a entails Ord [a] as -- well. -- -- This relationship is captured in the :- entailment type here. -- -- Since p :- p and entailment composes, :- forms -- the arrows of a Category of constraints. However, -- Category only became sufficiently general to support this -- instance in GHC 7.8, so prior to 7.8 this instance is unavailable. -- -- But due to the coherence of instance resolution in Haskell, this -- Category has some very interesting properties. Notably, in the -- absence of IncoherentInstances, this category is "thin", -- which is to say that between any two objects (constraints) there is at -- most one distinguishable arrow. -- -- This means that for instance, even though there are two ways to derive -- Ord a :- Eq [a], the answers from these -- two paths _must_ by construction be equal. This is a property that -- Haskell offers that is pretty much unique in the space of languages -- with things they call "type classes". -- -- What are the two ways? -- -- Well, we can go from Ord a :- Eq a via -- the superclass relationship, and then from Eq a :- -- Eq [a] via the instance, or we can go from Ord -- a :- Ord [a] via the instance then from -- Ord [a] :- Eq [a] through the superclass -- relationship and this diagram by definition must "commute". -- -- Diagrammatically, -- --
--          Ord a
--      ins /     \ cls
--         v       v
--   Ord [a]     Eq a
--      cls \     / ins
--           v   v
--          Eq [a]
--   
-- -- This safety net ensures that pretty much anything you can write with -- this library is sensible and can't break any assumptions on the behalf -- of library authors. newtype (:-) a b Sub :: (a -> Dict b) -> (:-) a b infixr 9 :- -- | Constraint which ensures that bigmap does not appear in a given type. class (ContainsBigMap t ~ 'False) => HasNoBigMap t -- | Constraint which ensures that there are no nested bigmaps class (ContainsNestedBigMaps t ~ 'False) => HasNoNestedBigMaps t -- | Constraint which ensures that operation type does not appear in a -- given type. -- -- Not just a type alias in order to be able to partially apply it (e.g. -- in Each). class (ContainsOp t ~ 'False) => HasNoOp t -- | Constraint which ensures that contract type does not appear in a given -- type. class (ContainsContract t ~ 'False) => HasNoContract t -- | Whether this type contains TBigMap type. type family ContainsBigMap (t :: T) :: Bool -- | Whether this type contains a type with nested TBigMaps . -- -- Nested big_maps (i.e. big_map which contains another big_map inside of -- it's value type). Are prohibited in all contexts. Some context such as -- PUSH, APPLY, PACK/UNPACK instructions are more strict because they -- doesn't work with big_map at all. type family ContainsNestedBigMaps (t :: T) :: Bool -- | This is like HasNoOp, it raises a more human-readable error -- when t type is concrete, but GHC cannot make any conclusions -- from such constraint as it can for 'HasNoOp. -- -- Use it in our eDSL. type ForbidOp t = FailOnOperationFound (ContainsOp t) type ForbidContract t = FailOnContractFound (ContainsContract t) type ForbidBigMap t = FailOnBigMapFound (ContainsBigMap t) type ForbidNestedBigMaps t = FailOnNestedBigMapsFound (ContainsNestedBigMaps t) -- | Report a human-readable error about TBigMap at a wrong place. type family FailOnBigMapFound (enabled :: Bool) :: Constraint -- | Report a human-readable error that TBigMap contains another -- TBigMap type family FailOnNestedBigMapsFound (enabled :: Bool) :: Constraint -- | Report a human-readable error about TOperation at a wrong -- place. type family FailOnOperationFound (enabled :: Bool) :: Constraint -- | Whether the type contains TOperation, with proof. data OpPresence (t :: T) OpPresent :: OpPresence OpAbsent :: OpPresence data ContractPresence (t :: T) ContractPresent :: ContractPresence ContractAbsent :: ContractPresence data BigMapPresence (t :: T) BigMapPresent :: BigMapPresence BigMapAbsent :: BigMapPresence data NestedBigMapsPresence (t :: T) NestedBigMapsPresent :: NestedBigMapsPresence NestedBigMapsAbsent :: NestedBigMapsPresence -- | Check at runtime whether the given type contains TOperation. checkOpPresence :: Sing (ty :: T) -> OpPresence ty -- | Check at runtime whether the given type contains TContract. checkContractTypePresence :: Sing (ty :: T) -> ContractPresence ty -- | Check at runtime whether the given type contains TBigMap. checkBigMapPresence :: Sing (ty :: T) -> BigMapPresence ty -- | Check at runtime whether the given type contains TBigMap. checkNestedBigMapsPresence :: Sing (ty :: T) -> NestedBigMapsPresence ty -- | Check at runtime that the given type does not contain -- TOperation. opAbsense :: Sing (t :: T) -> Maybe (Dict $ HasNoOp t) -- | Check at runtime that the given type does not contain -- TContract. contractTypeAbsense :: Sing (t :: T) -> Maybe (Dict $ HasNoContract t) -- | Check at runtime that the given type does not containt TBigMap bigMapAbsense :: Sing (t :: T) -> Maybe (Dict $ HasNoBigMap t) -- | Check at runtime that the given type does not contain nested -- TBigMap nestedBigMapsAbsense :: Sing (t :: T) -> Maybe (Dict $ HasNoNestedBigMaps t) -- | Reify HasNoOp contraint from ForbidOp. -- -- Left for backward compatibility. forbiddenOp :: forall t a. (SingI t, ForbidOp t) => (HasNoOp t => a) -> a -- | Reify HasNoContract contraint from ForbidContract. forbiddenContractType :: forall t a. (SingI t, ForbidContract t) => (HasNoContract t => a) -> a forbiddenBigMap :: forall t a. (SingI t, ForbidBigMap t) => (HasNoBigMap t => a) -> a forbiddenNestedBigMaps :: forall t a. (SingI t, ForbidNestedBigMaps t) => (HasNoNestedBigMaps t => a) -> a -- | From a Dict, takes a value in an environment where the instance -- witnessed by the Dict is in scope, and evaluates it. -- -- Essentially a deconstruction of a Dict into its -- continuation-style form. -- -- Can also be used to deconstruct an entailment, a :- b, -- using a context a. -- --
--   withDict :: Dict c -> (c => r) -> r
--   withDict :: a => (a :- c) -> (c => r) -> r
--   
withDict :: HasDict c e => e -> (c -> r) -> r instance (Michelson.Typed.Scope.ContainsNestedBigMaps t Data.Type.Equality.~ 'GHC.Types.False) => Michelson.Typed.Scope.HasNoNestedBigMaps t instance (Michelson.Typed.Scope.ContainsBigMap t Data.Type.Equality.~ 'GHC.Types.False) => Michelson.Typed.Scope.HasNoBigMap t instance (Michelson.Typed.Scope.ContainsContract t Data.Type.Equality.~ 'GHC.Types.False) => Michelson.Typed.Scope.HasNoContract t instance (Michelson.Typed.Scope.ContainsOp t Data.Type.Equality.~ 'GHC.Types.False) => Michelson.Typed.Scope.HasNoOp t -- | Cryptographic primitives related to hashing. module Tezos.Crypto.Hash -- | Compute a cryptographic hash of a bytestring using the Blake2b_256 -- cryptographic hash function. It's used by the BLAKE2B instruction in -- Michelson. blake2b :: ByteString -> ByteString -- | Compute a cryptographic hash of a bytestring using the Blake2b_160 -- cryptographic hash function. blake2b160 :: ByteString -> ByteString -- | Compute a cryptographic hash of a bytestring using the Sha256 -- cryptographic hash function. sha256 :: ByteString -> ByteString -- | Compute a cryptographic hash of a bytestring using the Sha512 -- cryptographic hash function. sha512 :: ByteString -> ByteString -- | Utilities shared by multiple cryptographic primitives. module Tezos.Crypto.Util -- | Error that can happen during parsing of cryptographic primitive types. data CryptoParseError CryptoParseWrongBase58Check :: CryptoParseError CryptoParseWrongTag :: !ByteString -> CryptoParseError CryptoParseCryptoError :: !CryptoError -> CryptoParseError CryptoParseUnexpectedLength :: !Builder -> !Int -> CryptoParseError -- | Encode a bytestring in Base58Check format. encodeBase58Check :: ByteString -> Text -- | Decode a bytestring from Base58Check format. decodeBase58Check :: Text -> Maybe ByteString data B58CheckWithPrefixError B58CheckWithPrefixWrongPrefix :: ByteString -> B58CheckWithPrefixError B58CheckWithPrefixWrongEncoding :: B58CheckWithPrefixError -- | Parse a base58check encoded value expecting some prefix. If the actual -- prefix matches the expected one, it's stripped of and the resulting -- payload is returned. decodeBase58CheckWithPrefix :: ByteString -> Text -> Either B58CheckWithPrefixError ByteString -- | Template for 'format*' functions. formatImpl :: ByteArrayAccess x => ByteString -> x -> Text -- | Template for 'parse*' functions. parseImpl :: ByteString -> (ByteString -> Either CryptoParseError res) -> Text -> Either CryptoParseError res -- | Returns first encountered Right in a list. If there are none, -- returns arbitrary Left. It is useful to implement parsing. firstRight :: NonEmpty (Either e a) -> Either e a -- | Do randomized action using specified seed. deterministic :: ByteString -> MonadPseudoRandom ChaChaDRG a -> a instance GHC.Show.Show Tezos.Crypto.Util.B58CheckWithPrefixError instance GHC.Classes.Eq Tezos.Crypto.Util.CryptoParseError instance GHC.Show.Show Tezos.Crypto.Util.CryptoParseError instance Formatting.Buildable.Buildable Tezos.Crypto.Util.CryptoParseError -- | Utilities related to Alternative. module Util.Alternative -- | This function is the same as some except that it returns -- NonEmpty, because some is guaranteed to return non-empty -- list, but it's not captured in types. someNE :: Alternative f => f a -> f (NonEmpty a) module Util.Default permute2Def :: (Default a, Default b, Monad f, Alternative f) => f a -> f b -> f (a, b) permute3Def :: (Default a, Default b, Default c, Monad f, Alternative f) => f a -> f b -> f c -> f (a, b, c) -- | A class for types with a default value. class Default a -- | The default value for this type. def :: Default a => a -- | Generic-related utils. module Util.Generic -- | Rebuild a list into a binary tree of exactly the same form which -- Generic uses to represent datatypes. -- -- Along with the original list you have to provide constructor for -- intermediate nodes - it accepts zero-based index of the leftmost -- element of the right tree and merged trees themselves. mkGenericTree :: (Natural -> a -> a -> a) -> NonEmpty a -> a mkGenericTreeVec :: HasCallStack => (a -> b) -> (Natural -> b -> b -> b) -> Vector a -> b -- | Extract datatype name via its Generic representation. -- -- For polymorphic types this throws away all type arguments. type GenericTypeName a = GTypeName (Rep a) module Util.IO readFileUtf8 :: FilePath -> IO Text writeFileUtf8 :: Print text => FilePath -> text -> IO () appendFileUtf8 :: Print text => FilePath -> text -> IO () withEncoding :: Handle -> TextEncoding -> IO () -> IO () -- | Change the character encoding of the given Handle to transliterate on -- unsupported characters instead of throwing an exception. hSetTranslit :: Handle -> IO () -- | Missing instances from libraries. module Util.Instances instance Data.Default.Class.Default GHC.Natural.Natural instance Formatting.Buildable.Buildable GHC.Natural.Natural instance Formatting.Buildable.Buildable a => Formatting.Buildable.Buildable (Data.Functor.Identity.Identity a) module Util.Lens -- | For datatype with "myNyan" field it will create "myNyanL" lens. postfixLFields :: LensRules -- | Build lenses with a custom configuration. makeLensesWith :: LensRules -> Name -> DecsQ unwrappedP :: Wrapped a => Proxy a -> Proxy (Unwrapped a) -- | A small Markdown eDSL. module Util.Markdown -- | A piece of markdown document. -- -- This is opposed to Text type, which in turn is not supposed to -- contain markup elements. type Markdown = Builder -- | Level of header, starting from 1. newtype HeaderLevel HeaderLevel :: Int -> HeaderLevel nextHeaderLevel :: HeaderLevel -> HeaderLevel mdHeader :: HeaderLevel -> Markdown -> Markdown mdSubsection :: Markdown -> Markdown -> Markdown mdSubsectionTitle :: Markdown -> Markdown mdBold :: Markdown -> Markdown mdItalic :: Markdown -> Markdown mdTicked :: Markdown -> Markdown mdRef :: Markdown -> Markdown -> Markdown mdLocalRef :: Markdown -> Text -> Markdown mdAnchor :: Text -> Markdown mdSeparator :: Markdown -- | Text which is hidden until clicked. mdSpoiler :: Markdown -> Markdown -> Markdown mdComment :: Builder -> Builder -- | Quasi quoter for Markdown. md :: QuasiQuoter -- | Additional functionality for named package. module Util.Named -- | Infix notation for the type of a named parameter. type (:!) (name :: Symbol) a = NamedF Identity a name -- | Infix notation for the type of an optional named parameter. type (:?) (name :: Symbol) a = NamedF Maybe a name (.!) :: Name name -> a -> NamedF Identity a name (.?) :: Name name -> Maybe a -> NamedF Maybe a name (<.!>) :: Functor m => Name name -> m a -> m (NamedF Identity a name) (<.?>) :: Functor m => Name name -> m (Maybe a) -> m (NamedF Maybe a name) type family ApplyNamedFunctor (f :: Type -> Type) (a :: Type) type family NamedInner (n :: Type) instance GHC.Classes.Eq (f a) => GHC.Classes.Eq (Named.Internal.NamedF f a name) instance GHC.Classes.Ord (f a) => GHC.Classes.Ord (Named.Internal.NamedF f a name) instance (Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a, GHC.TypeLits.KnownSymbol name, Data.Data.Data (f a)) => Data.Data.Data (Named.Internal.NamedF f a name) instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Named.Internal.NamedF Data.Functor.Identity.Identity a name) instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Named.Internal.NamedF GHC.Maybe.Maybe a name) instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Named.Internal.NamedF Data.Functor.Identity.Identity a name) instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Named.Internal.NamedF GHC.Maybe.Maybe a name) instance Control.Lens.Wrapped.Wrapped (Named.Internal.NamedF Data.Functor.Identity.Identity a name) instance Control.Lens.Wrapped.Wrapped (Named.Internal.NamedF GHC.Maybe.Maybe a name) instance (GHC.Show.Show a, GHC.TypeLits.KnownSymbol name) => GHC.Show.Show (Named.Internal.NamedF Data.Functor.Identity.Identity a name) instance (GHC.TypeLits.KnownSymbol name, Formatting.Buildable.Buildable (f a)) => Formatting.Buildable.Buildable (Named.Internal.NamedF f a name) -- | Type-nat utilities. -- -- We take Peano numbers as base for operations because they make it much -- easer to prove things to compiler. Their performance does not seem to -- introduce a problem, because we use nats primarily along with stack -- which is a linked list with similar performance characteristics. -- -- Many of things we introduce here are covered in type-natural -- package, but unfortunatelly it does not work with GHC 8.6 at the -- moment of writing this module. We use Vinyl as source of Peano -- Nat for now. module Util.Peano -- | A convenient alias. -- -- We are going to use Peano numbers for type-dependent logic and -- normal Nats in user API, need to distinguish them somehow. type Peano = Nat -- | A mere approximation of the natural numbers. And their image as lifted -- by -XDataKinds corresponds to the actual natural numbers. data Nat Z :: Nat S :: !Nat -> Nat type family ToPeano (n :: Nat) :: Peano type family FromPeano (n :: Peano) :: Nat class KnownPeano (n :: Peano) peanoVal :: KnownPeano n => proxy n -> Natural -- | The singleton kind-indexed data family. data family Sing (a :: k) :: Type peanoVal' :: forall n. KnownPeano n => Natural -- | Get runtime value from singleton. peanoValSing :: forall n. KnownPeano n => Sing n -> Natural type family Length l :: Peano type family At (n :: Peano) s type family Drop (n :: Peano) (s :: [k]) :: [k] type family Take (n :: Peano) (s :: [k]) :: [k] -- | Comparison of type-level naturals, as a function. -- -- It is as lazy on the list argument as possible - there is no need to -- know the whole list if the natural argument is small enough. This -- property is important if we want to be able to extract reusable parts -- of code which are aware only of relevant part of stack. type family IsLongerThan (l :: [k]) (a :: Peano) :: Bool -- | Comparison of type-level naturals, as a constraint. type LongerThan l a = IsLongerThan l a ~ 'True class (RequireLongerThan' l a, LongerThan l a) => RequireLongerThan (l :: [k]) (a :: Peano) -- | Similar to IsLongerThan, but returns True when list -- length equals to the passed number. type family IsLongerOrSameLength (l :: [k]) (a :: Peano) :: Bool -- | IsLongerOrSameLength in form of constraint that gives most -- information to GHC. type LongerOrSameLength l a = IsLongerOrSameLength l a ~ 'True -- | We can have `RequireLongerOrSameLength = (RequireLongerOrSameLength' l -- a, LongerOrSameLength l a)`, but apparently the printed error message -- can be caused by LongerOrSameLength rather than -- RequireLongerOrSameLength'. We do not know for sure how it all -- works, but we think that if we require constraint X before Y (using -- multiple `=>`s) then X will always be evaluated first. class (RequireLongerOrSameLength' l a, LongerOrSameLength l a) => RequireLongerOrSameLength (l :: [k]) (a :: Peano) instance GHC.Show.Show (Data.Singletons.Internal.Sing n) instance GHC.Classes.Eq (Data.Singletons.Internal.Sing n) instance forall k (l :: [k]) (a :: Util.Peano.Peano). (Util.Peano.RequireLongerOrSameLength' l a, Util.Peano.LongerOrSameLength l a) => Util.Peano.RequireLongerOrSameLength l a instance forall k (l :: [k]) (a :: Data.Vinyl.TypeLevel.Nat). (Util.Peano.RequireLongerThan' l a, Util.Peano.LongerThan l a) => Util.Peano.RequireLongerThan l a instance Util.Peano.KnownPeano 'Data.Vinyl.TypeLevel.Z instance Util.Peano.KnownPeano a => Util.Peano.KnownPeano ('Data.Vinyl.TypeLevel.S a) instance (Data.Singletons.Internal.SingI n, Util.Peano.KnownPeano n) => Data.Singletons.Internal.SingI ('Data.Vinyl.TypeLevel.S n) instance Data.Singletons.Internal.SingI 'Data.Vinyl.TypeLevel.Z -- | Definition of Positive type and related utilities. module Util.Positive -- | Integer values starting from 1. -- -- We define our own datatype in order to have Data instance for -- it, which can not be derived for third-party types without exported -- constructor. newtype Positive PositiveUnsafe :: Natural -> Positive [unPositive] :: Positive -> Natural mkPositive :: (Integral i, Buildable i) => i -> Either Text Positive -- | Count length of non-empty list. lengthNE :: NonEmpty a -> Positive -- | Produce a non empty list consisting of the given value. replicateNE :: Positive -> a -> NonEmpty a instance Data.Aeson.Types.FromJSON.FromJSON Util.Positive.Positive instance Data.Aeson.Types.ToJSON.ToJSON Util.Positive.Positive instance Formatting.Buildable.Buildable Util.Positive.Positive instance GHC.Show.Show Util.Positive.Positive instance Data.Data.Data Util.Positive.Positive instance GHC.Classes.Ord Util.Positive.Positive instance GHC.Classes.Eq Util.Positive.Positive -- | Custom exceptions that can happen during parsing. module Michelson.Parser.Error data CustomParserException UnknownTypeException :: CustomParserException StringLiteralException :: StringLiteralParserException -> CustomParserException OddNumberBytesException :: CustomParserException WrongTagArgs :: Natural -> Positive -> CustomParserException WrongAccessArgs :: Natural -> Positive -> CustomParserException WrongSetArgs :: Natural -> Positive -> CustomParserException data StringLiteralParserException InvalidEscapeSequence :: Char -> StringLiteralParserException InvalidChar :: Char -> StringLiteralParserException -- | A non-empty collection of ParseErrors equipped with -- PosState that allows to pretty-print the errors efficiently and -- correctly. data ParseErrorBundle s e data ParserException ParserException :: ParseErrorBundle Text CustomParserException -> ParserException instance GHC.Classes.Eq Michelson.Parser.Error.ParserException instance GHC.Show.Show Michelson.Parser.Error.CustomParserException instance GHC.Classes.Ord Michelson.Parser.Error.CustomParserException instance Data.Data.Data Michelson.Parser.Error.CustomParserException instance GHC.Classes.Eq Michelson.Parser.Error.CustomParserException instance GHC.Show.Show Michelson.Parser.Error.StringLiteralParserException instance GHC.Classes.Ord Michelson.Parser.Error.StringLiteralParserException instance Data.Data.Data Michelson.Parser.Error.StringLiteralParserException instance GHC.Classes.Eq Michelson.Parser.Error.StringLiteralParserException instance GHC.Show.Show Michelson.Parser.Error.ParserException instance GHC.Exception.Type.Exception Michelson.Parser.Error.ParserException instance Formatting.Buildable.Buildable Michelson.Parser.Error.ParserException instance Text.Megaparsec.Error.ShowErrorComponent Michelson.Parser.Error.CustomParserException instance Text.Megaparsec.Error.ShowErrorComponent Michelson.Parser.Error.StringLiteralParserException -- | Ingridients that we use in our test suite. module Util.Test.Ingredients -- | This is the default set of ingredients extended with the -- antXMLRunner which is used to generate xml reports for CI. ourIngredients :: [Ingredient] module Util.Text -- | Leads first character of text to lower case. -- -- For empty text this will throw an error. headToLower :: HasCallStack => Text -> Text -- | General type utilities. module Util.Type -- | A type family to compute Boolean equality. type family (==) (a :: k) (b :: k) :: Bool infix 4 == -- | Type-level If. If True a b ==> a; If -- False a b ==> b type family If (cond :: Bool) (tru :: k) (fls :: k) :: k -- | Append for type-level lists. type family (++) (as :: [k]) (bs :: [k]) :: [k] type family IsElem (a :: k) (l :: [k]) :: Bool -- | Remove all occurences of the given element. type family (l :: [k]) / (a :: k) -- | Difference between two lists. type family (l1 :: [k]) // (l2 :: [k]) :: [k] type family Guard (cond :: Bool) (a :: k) :: Maybe k type family AllUnique (l :: [k]) :: Bool type family RequireAllUnique (desc :: Symbol) (l :: [k]) :: Constraint -- | Bring type-level list at term-level using given function to demote its -- individual elements. class ReifyList (c :: k -> Constraint) (l :: [k]) reifyList :: ReifyList c l => (forall a. c a => Proxy a -> r) -> [r] -- | Make sure given type is evaluated. This type family fits only for -- types of Type kind. type family PatternMatch (a :: Type) :: Constraint type family PatternMatchL (l :: [k]) :: Constraint -- | Similar to SingI [], but does not require individual elements -- to be also instance of SingI. class KnownList l klist :: KnownList l => KList l -- | SList analogy for KnownList. data KList (l :: [k]) [KNil] :: KList '[] [KCons] :: KnownList xs => Proxy x -> Proxy xs -> KList (x : xs) type RSplit l r = KnownList l -- | Split a record into two pieces. rsplit :: forall k (l :: [k]) (r :: [k]) f. RSplit l r => Rec f (l ++ r) -> (Rec f l, Rec f r) -- | Reify type equality from boolean equality. reifyTypeEquality :: forall a b x. (a == b) ~ 'True => (a ~ b => x) -> x instance Util.Type.KnownList '[] instance forall k (xs :: [k]) (x :: k). Util.Type.KnownList xs => Util.Type.KnownList (x : xs) instance forall k (c :: k -> GHC.Types.Constraint). Util.Type.ReifyList c '[] instance forall a (c :: a -> GHC.Types.Constraint) (x :: a) (xs :: [a]). (c x, Util.Type.ReifyList c xs) => Util.Type.ReifyList c (x : xs) -- | Re-exports TypeLits, modifying it considering our practices. module Util.TypeLits -- | (Kind) This is the kind of type-level symbols. Declared here because -- class IP needs it data Symbol -- | This class gives the string associated with a type-level symbol. There -- are instances of the class for every concrete literal: "hello", etc. class KnownSymbol (n :: Symbol) -- | Concatenation of type-level symbols. type family AppendSymbol (a :: Symbol) (b :: Symbol) :: Symbol symbolValT :: forall s. KnownSymbol s => Proxy s -> Text symbolValT' :: forall s. KnownSymbol s => Text -- | The type-level equivalent of error. -- -- The polymorphic kind of this type allows it to be used in several -- settings. For instance, it can be used as a constraint, e.g. to -- provide a better error message for a non-existent instance, -- --
--   -- in a context
--   instance TypeError (Text "Cannot Show functions." :$$:
--                       Text "Perhaps there is a missing argument?")
--         => Show (a -> b) where
--       showsPrec = error "unreachable"
--   
-- -- It can also be placed on the right-hand side of a type-level function -- to provide an error for an invalid case, -- --
--   type family ByteSize x where
--      ByteSize Word16   = 2
--      ByteSize Word8    = 1
--      ByteSize a        = TypeError (Text "The type " :<>: ShowType a :<>:
--                                     Text " is not exportable.")
--   
type family TypeError (a :: ErrorMessage) :: b -- | A description of a custom type error. data ErrorMessage -- | Show the text as is. [Text] :: () => Symbol -> ErrorMessage -- | Pretty print the type. ShowType :: k -> ErrorMessage [ShowType] :: forall t. () => t -> ErrorMessage -- | Put two pieces of error message next to each other. [:<>:] :: () => ErrorMessage -> ErrorMessage -> ErrorMessage -- | Stack two pieces of error message on top of each other. [:$$:] :: () => ErrorMessage -> ErrorMessage -> ErrorMessage infixl 6 :<>: infixl 5 :$$: -- | Conditional type error. -- -- Note that TypeErrorUnless cond err is the same as If cond -- () (TypeError err), but does not produce type-level error when -- one of its arguments cannot be deduced. type family TypeErrorUnless (cond :: Bool) (err :: ErrorMessage) :: Constraint -- | Reify the fact that condition under TypeErrorUnless constraint -- can be assumed to always hold. inTypeErrorUnless :: forall cond err a. TypeErrorUnless cond err => (cond ~ 'True => a) -> a -- | Strings compliant with Michelson constraints. -- -- When writting a Michelson contract, you can only mention characters -- with codes from [32 .. 126] range in string literals. Same -- restriction applies to string literals passed to alphanet.sh. -- -- However, Michelson allows some control sequences: "n". You -- have to write it exactly in this form, and internally it will be -- transformed to line feed character (this behaviour can be observed -- when looking at Packed data). -- -- See tests for examples of good and bad strings. module Michelson.Text -- | Michelson string value. -- -- This is basically a mere text with limits imposed by the language: -- http://tezos.gitlab.io/zeronet/whitedoc/michelson.html#constants -- Although, this document seems to be not fully correct, and thus we -- applied constraints deduced empirically. -- -- You construct an item of this type using one of the following ways: -- -- -- --
--   >>> [mt|Some text|]
--   MTextUnsafe { unMText = "Some text" }
--   
-- -- newtype MText MTextUnsafe :: Text -> MText [unMText] :: MText -> Text -- | Wrap a Haskell text into MText, performing necessary checks. -- -- You can use e.g. '\n' character directly in supplied -- argument, but attempt to use other bad characters like '\r' -- will cause failure. mkMText :: Text -> Either Text MText -- | Contruct MText from a Haskell text, failing if provided Haskell -- text is invalid Michelson string. mkMTextUnsafe :: HasCallStack => Text -> MText -- | Construct MText from a Haskell text, eliminating all characters -- which should not appear in Michelson strings. Characters which can be -- displayed normally via escaping are preserved. mkMTextCut :: Text -> MText -- | Print MText for Michelson code, with all unusual characters -- escaped. writeMText :: MText -> Text takeMText :: Int -> MText -> MText dropMText :: Int -> MText -> MText -- | Constraint on literals appearing in Michelson contract code. isMChar :: Char -> Bool -- | Parser used in mt quasi quoter. qqMText :: String -> Either Text String -- | QuasyQuoter for constructing Michelson strings. -- -- Validity of result will be checked at compile time. Note: -- -- mt :: QuasiQuoter -- | A type error asking to use MText instead of -- ErrorMessage. type family DoNotUseTextError -- | Create a MText from type-level string. -- -- We assume that no unicode characters are used in plain Haskell code, -- so unless special tricky manipulations are used this should be safe. symbolToMText :: forall name. KnownSymbol name => MText -- | Create a MText from label. -- -- We assume that no unicode characters are used in plain Haskell code, -- so unless special tricky manipulations are used this should be safe. labelToMText :: KnownSymbol name => Label name -> MText -- | Leads first character of text to upper case. -- -- For empty text this will throw an error. mtextHeadToUpper :: HasCallStack => MText -> MText instance Data.Hashable.Class.Hashable Michelson.Text.MText instance Formatting.Buildable.Buildable Michelson.Text.MText instance Universum.Container.Class.Container Michelson.Text.MText instance GHC.Base.Monoid Michelson.Text.MText instance GHC.Base.Semigroup Michelson.Text.MText instance Data.Data.Data Michelson.Text.MText instance GHC.Classes.Ord Michelson.Text.MText instance GHC.Classes.Eq Michelson.Text.MText instance GHC.Show.Show Michelson.Text.MText instance Universum.String.Conversion.ToText Michelson.Text.MText instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Text.MText instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Text.MText instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Text.MText instance (TypeError ...) => Data.String.IsString Michelson.Text.MText -- | Secp256k1 cryptographic primitives. module Tezos.Crypto.Secp256k1 -- | Secp256k1 public cryptographic key. data PublicKey PublicKey :: PublicKey -> !Maybe ByteString -> PublicKey [unPublicKey] :: PublicKey -> PublicKey -- | This is the hack we use to make serialization correct. Decoding is -- currently not implemented, so when we have to decode bytes we remember -- these bytes and produce some random public key. -- -- TODO (#18) remove it. [pkBytes] :: PublicKey -> !Maybe ByteString -- | Secp256k1 secret cryptographic key. data SecretKey -- | Secp256k1 cryptographic signature. newtype Signature Signature :: Signature -> Signature [unSignature] :: Signature -> Signature -- | Deterministicaly generate a secret key from seed. detSecretKey :: ByteString -> SecretKey -- | Create a public key from a secret key. toPublic :: SecretKey -> PublicKey -- | Convert a PublicKey to raw bytes. -- -- TODO (#18): apparently it uses compressed SEC format as described in -- https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/ch04.html -- However, it is not tested yet. publicKeyToBytes :: forall ba. ByteArray ba => PublicKey -> ba -- | Make a PublicKey from raw bytes. -- -- TODO (#18): it should decode from compressed SEC format, but it's left -- for a future task, so for now we return a constant. mkPublicKey :: ByteArrayAccess ba => ba -> Either CryptoParseError PublicKey publicKeyLengthBytes :: Integral n => n -- | Convert a PublicKey to raw bytes. -- -- TODO (#18): apparently a signature always has 64 bytes, so this format -- might be correct, but it is not tested. signatureToBytes :: ByteArray ba => Signature -> ba -- | Make a Signature from raw bytes. -- -- TODO (#18): apparently a signature always has 64 bytes, so this format -- might be correct, but it is not tested. mkSignature :: ByteArray ba => ba -> Either CryptoParseError Signature signatureLengthBytes :: Integral n => n formatPublicKey :: PublicKey -> Text mformatPublicKey :: PublicKey -> MText parsePublicKey :: Text -> Either CryptoParseError PublicKey formatSignature :: Signature -> Text mformatSignature :: Signature -> MText parseSignature :: Text -> Either CryptoParseError Signature -- | Sign a message using the secret key. sign :: MonadRandom m => SecretKey -> ByteString -> m Signature -- | Check that a sequence of bytes has been signed with a given key. checkSignature :: PublicKey -> Signature -> ByteString -> Bool instance GHC.Classes.Eq Tezos.Crypto.Secp256k1.Signature instance GHC.Show.Show Tezos.Crypto.Secp256k1.Signature instance GHC.Classes.Eq Tezos.Crypto.Secp256k1.SecretKey instance GHC.Show.Show Tezos.Crypto.Secp256k1.SecretKey instance GHC.Show.Show Tezos.Crypto.Secp256k1.PublicKey instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.Secp256k1.Signature instance Formatting.Buildable.Buildable Tezos.Crypto.Secp256k1.Signature instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.Secp256k1.SecretKey instance GHC.Classes.Eq Tezos.Crypto.Secp256k1.PublicKey instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.Secp256k1.PublicKey instance Formatting.Buildable.Buildable Tezos.Crypto.Secp256k1.PublicKey -- | P256 cryptographic primitives. -- -- This module is mostly a stub, it doesn't implement actual crypto. TODO -- (#18) implement crypto properly. module Tezos.Crypto.P256 -- | P256 public cryptographic key. newtype PublicKey PublicKey :: ByteString -> PublicKey [unPublicKey] :: PublicKey -> ByteString -- | P256 secret cryptographic key. data SecretKey -- | P256 cryptographic signature. newtype Signature Signature :: ByteString -> Signature [unSignature] :: Signature -> ByteString -- | Deterministicaly generate a secret key from seed. detSecretKey :: ByteString -> SecretKey -- | Create a public key from a secret key. toPublic :: SecretKey -> PublicKey -- | Convert a PublicKey to raw bytes. -- -- TODO (#18): implement properly. publicKeyToBytes :: forall ba. ByteArray ba => PublicKey -> ba -- | Make a PublicKey from raw bytes. -- -- TODO (#18): implement properly. mkPublicKey :: ByteArrayAccess ba => ba -> Either CryptoParseError PublicKey publicKeyLengthBytes :: Integral n => n -- | Convert a PublicKey to raw bytes. -- -- TODO (#18): implement properly. signatureToBytes :: ByteArray ba => Signature -> ba -- | Make a Signature from raw bytes. -- -- TODO (#18): implement properly. mkSignature :: ByteArray ba => ba -> Either CryptoParseError Signature signatureLengthBytes :: Integral n => n formatPublicKey :: PublicKey -> Text mformatPublicKey :: PublicKey -> MText parsePublicKey :: Text -> Either CryptoParseError PublicKey formatSignature :: Signature -> Text mformatSignature :: Signature -> MText parseSignature :: Text -> Either CryptoParseError Signature -- | Check that a sequence of bytes has been signed with a given key. checkSignature :: PublicKey -> Signature -> ByteString -> Bool instance GHC.Classes.Eq Tezos.Crypto.P256.Signature instance GHC.Show.Show Tezos.Crypto.P256.Signature instance GHC.Classes.Eq Tezos.Crypto.P256.SecretKey instance GHC.Show.Show Tezos.Crypto.P256.SecretKey instance GHC.Classes.Eq Tezos.Crypto.P256.PublicKey instance GHC.Show.Show Tezos.Crypto.P256.PublicKey instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.P256.Signature instance Formatting.Buildable.Buildable Tezos.Crypto.P256.Signature instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.P256.SecretKey instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.P256.PublicKey instance Formatting.Buildable.Buildable Tezos.Crypto.P256.PublicKey -- | Ed25519 cryptographic primitives. module Tezos.Crypto.Ed25519 -- | ED25519 public cryptographic key. newtype PublicKey PublicKey :: PublicKey -> PublicKey [unPublicKey] :: PublicKey -> PublicKey -- | ED25519 secret cryptographic key. data SecretKey -- | ED25519 cryptographic signature. newtype Signature Signature :: Signature -> Signature [unSignature] :: Signature -> Signature -- | Deterministicaly generate a secret key from seed. detSecretKey :: ByteString -> SecretKey -- | Create a public key from a secret key. toPublic :: SecretKey -> PublicKey -- | Convert a PublicKey to raw bytes. publicKeyToBytes :: ByteArray ba => PublicKey -> ba -- | Make a PublicKey from raw bytes. mkPublicKey :: ByteArrayAccess ba => ba -> Either CryptoParseError PublicKey publicKeyLengthBytes :: Integral n => n -- | Convert a Signature to raw bytes. signatureToBytes :: ByteArray ba => Signature -> ba -- | Make a Signature from raw bytes. mkSignature :: ByteArrayAccess ba => ba -> Either CryptoParseError Signature signatureLengthBytes :: Integral n => n formatPublicKey :: PublicKey -> Text mformatPublicKey :: PublicKey -> MText parsePublicKey :: Text -> Either CryptoParseError PublicKey formatSecretKey :: SecretKey -> Text formatSignature :: Signature -> Text mformatSignature :: Signature -> MText parseSignature :: Text -> Either CryptoParseError Signature -- | Sign a message using the secret key. sign :: SecretKey -> ByteString -> Signature -- | Check that a sequence of bytes has been signed with a given key. checkSignature :: PublicKey -> Signature -> ByteString -> Bool instance GHC.Classes.Eq Tezos.Crypto.Ed25519.Signature instance GHC.Show.Show Tezos.Crypto.Ed25519.Signature instance GHC.Classes.Eq Tezos.Crypto.Ed25519.SecretKey instance GHC.Show.Show Tezos.Crypto.Ed25519.SecretKey instance GHC.Classes.Eq Tezos.Crypto.Ed25519.PublicKey instance GHC.Show.Show Tezos.Crypto.Ed25519.PublicKey instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.Ed25519.Signature instance Formatting.Buildable.Buildable Tezos.Crypto.Ed25519.Signature instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.Ed25519.SecretKey instance Formatting.Buildable.Buildable Tezos.Crypto.Ed25519.SecretKey instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.Ed25519.PublicKey instance Formatting.Buildable.Buildable Tezos.Crypto.Ed25519.PublicKey -- | Cryptographic primitives used in Tezos. -- -- WARNING: some functions may be vulnerable to timing attacks. Also, -- this code was not reviewed by cryptography/security experts. Do not -- use it with secret keys that have some value. We provide -- SecretKey type and (limited) signing functionality only for -- testing. If you need to sign something in production, use something -- else (e. g. `tezos-client`). -- -- Tezos supports 3 cryptographic curves that are denoted by the number -- after tz in the public key hash: tz1, tz2 or tz3. • tz1 — ed25519 • -- tz2 — secp256k1 • tz3 — P256 We have Tezos.Crypto.Curve module for -- each of these curves. They expose very similar functionality and their -- main purpose is to hide implementation details for each curve as well -- as some other specifics (e. g. prefixes that are used for -- human-readable representation). -- -- This module serves two purposes: 1. It is an umbrella module that -- re-exports some stuff from other modules. 2. Michelson types such as -- key and signature may store primitive of any curve, -- so we need "union" types in Haskell as well. -- -- During conversion to human-readable representation usually some -- magical prefix is used. They have been found in source code in some -- repos (e. g. -- https://gitlab.com/tezos/tezos/blob/c52ee69231c5ae4d9cec1f3c8aba0c3573922e2a/src/lib_crypto/base58.ml) -- and checked manually. Existing tests confirm they are correct. module Tezos.Crypto -- | Public cryptographic key used by Tezos. There are three cryptographic -- curves each represented by its own constructor. data PublicKey -- | Public key that uses the ed25519 cryptographic curve. PublicKeyEd25519 :: !PublicKey -> PublicKey -- | Public key that uses the secp256k1 cryptographic curve. PublicKeySecp256k1 :: !PublicKey -> PublicKey -- | Public key that uses the NIST P-256 cryptographic curve. PublicKeyP256 :: !PublicKey -> PublicKey -- | Secret cryptographic key used by Tezos. Constructors correspond to -- PublicKey constructors. data SecretKey -- | Cryptographic signatures used by Tezos. Constructors correspond to -- PublicKey constructors. -- -- Tezos distinguishes signatures for different curves. For instance, -- ed25519 signatures and secp256k1 signatures are printed differently -- (have different prefix). However, signatures are packed without -- information about the curve. For this purpose there is a generic -- signature which only stores bytes and doesn't carry information about -- the curve. Apparently unpacking from bytes always produces such -- signature. Unpacking from string produces a signature with curve -- information. data Signature -- | Signature that uses the ed25519 cryptographic curve. SignatureEd25519 :: !Signature -> Signature -- | Siganture that uses the secp256k1 cryptographic curve. SignatureSecp256k1 :: !Signature -> Signature -- | Signature that uses the NIST P-256 cryptographic curve. SignatureP256 :: Signature -> Signature -- | Generic signature for which curve is unknown. SignatureGeneric :: !ByteString -> Signature -- | Which curve was used for the hashed public key inside KeyHash. data KeyHashTag KeyHashEd25519 :: KeyHashTag KeyHashSecp256k1 :: KeyHashTag KeyHashP256 :: KeyHashTag -- | Blake2b_160 hash of a public key. data KeyHash KeyHash :: KeyHashTag -> ByteString -> KeyHash -- | We store which curve was used because it affects formatting. [khTag] :: KeyHash -> KeyHashTag -- | Hash itself. [khBytes] :: KeyHash -> ByteString -- | Deterministicaly generate a secret key from seed. Type of the key -- depends on seed length. detSecretKey :: HasCallStack => ByteString -> SecretKey -- | Create a public key from a secret key. toPublic :: SecretKey -> PublicKey -- | Convert a Signature to raw bytes. signatureToBytes :: ByteArray ba => Signature -> ba -- | Make a Signature from raw bytes. Can return only generic -- signature. mkSignature :: ByteArray ba => ba -> Maybe Signature signatureLengthBytes :: HasCallStack => Integral n => n -- | Check that a sequence of bytes has been signed with a given key. TODO -- (#18) consider generic signature here as well. checkSignature :: PublicKey -> Signature -> ByteString -> Bool -- | Error that can happen during parsing of cryptographic primitive types. data CryptoParseError CryptoParseWrongBase58Check :: CryptoParseError CryptoParseWrongTag :: !ByteString -> CryptoParseError CryptoParseCryptoError :: !CryptoError -> CryptoParseError CryptoParseUnexpectedLength :: !Builder -> !Int -> CryptoParseError formatPublicKey :: PublicKey -> Text mformatPublicKey :: PublicKey -> MText parsePublicKey :: Text -> Either CryptoParseError PublicKey formatSignature :: Signature -> Text mformatSignature :: Signature -> MText parseSignature :: Text -> Either CryptoParseError Signature formatKeyHash :: KeyHash -> Text mformatKeyHash :: KeyHash -> MText parseKeyHash :: Text -> Either CryptoParseError KeyHash -- | Length of key hash in bytes (only hash itself, no tags, checksums or -- anything). keyHashLengthBytes :: Integral n => n -- | Compute the b58check of a public key hash. hashKey :: PublicKey -> KeyHash -- | Compute a cryptographic hash of a bytestring using the Blake2b_256 -- cryptographic hash function. It's used by the BLAKE2B instruction in -- Michelson. blake2b :: ByteString -> ByteString -- | Compute a cryptographic hash of a bytestring using the Blake2b_160 -- cryptographic hash function. blake2b160 :: ByteString -> ByteString -- | Compute a cryptographic hash of a bytestring using the Sha256 -- cryptographic hash function. sha256 :: ByteString -> ByteString -- | Compute a cryptographic hash of a bytestring using the Sha512 -- cryptographic hash function. sha512 :: ByteString -> ByteString -- | Encode a bytestring in Base58Check format. encodeBase58Check :: ByteString -> Text -- | Decode a bytestring from Base58Check format. decodeBase58Check :: Text -> Maybe ByteString data B58CheckWithPrefixError B58CheckWithPrefixWrongPrefix :: ByteString -> B58CheckWithPrefixError B58CheckWithPrefixWrongEncoding :: B58CheckWithPrefixError -- | Parse a base58check encoded value expecting some prefix. If the actual -- prefix matches the expected one, it's stripped of and the resulting -- payload is returned. decodeBase58CheckWithPrefix :: ByteString -> Text -> Either B58CheckWithPrefixError ByteString instance GHC.Classes.Ord Tezos.Crypto.KeyHash instance GHC.Classes.Eq Tezos.Crypto.KeyHash instance GHC.Show.Show Tezos.Crypto.KeyHash instance GHC.Enum.Enum Tezos.Crypto.KeyHashTag instance GHC.Enum.Bounded Tezos.Crypto.KeyHashTag instance GHC.Classes.Ord Tezos.Crypto.KeyHashTag instance GHC.Classes.Eq Tezos.Crypto.KeyHashTag instance GHC.Show.Show Tezos.Crypto.KeyHashTag instance GHC.Show.Show Tezos.Crypto.Signature instance GHC.Classes.Eq Tezos.Crypto.SecretKey instance GHC.Show.Show Tezos.Crypto.SecretKey instance GHC.Classes.Eq Tezos.Crypto.PublicKey instance GHC.Show.Show Tezos.Crypto.PublicKey instance Data.Aeson.Types.ToJSON.ToJSON Tezos.Crypto.KeyHash instance Data.Aeson.Types.FromJSON.FromJSON Tezos.Crypto.KeyHash instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.KeyHash instance Formatting.Buildable.Buildable Tezos.Crypto.KeyHash instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.KeyHashTag instance GHC.Classes.Eq Tezos.Crypto.Signature instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.Signature instance Formatting.Buildable.Buildable Tezos.Crypto.Signature instance Data.Aeson.Types.ToJSON.ToJSON Tezos.Crypto.Signature instance Data.Aeson.Types.FromJSON.FromJSON Tezos.Crypto.Signature instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.SecretKey instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Crypto.PublicKey instance Formatting.Buildable.Buildable Tezos.Crypto.PublicKey instance Data.Aeson.Types.ToJSON.ToJSON Tezos.Crypto.PublicKey instance Data.Aeson.Types.FromJSON.FromJSON Tezos.Crypto.PublicKey -- | Core primitive Tezos types. module Tezos.Core -- | Mutez is a wrapper over integer data type. 1 mutez is 1 token (μTz). data Mutez -- | Safely create Mutez checking for overflow. mkMutez :: Word64 -> Maybe Mutez -- | Partial function for Mutez creation, it's pre-condition is that -- the argument must not exceed the maximal Mutez value. unsafeMkMutez :: HasCallStack => Word64 -> Mutez -- | Safely create Mutez. -- -- This is recommended way to create Mutez from a numeric -- literal; you can't construct all valid Mutez values using -- this function but for small values it works neat. -- -- Warnings displayed when trying to construct invalid Natural or -- Word literal are hardcoded for these types in GHC -- implementation, so we can only exploit these existing rules. toMutez :: Word32 -> Mutez -- | Addition of Mutez values. Returns Nothing in case of -- overflow. addMutez :: Mutez -> Mutez -> Maybe Mutez -- | Partial addition of Mutez, should be used only if you're sure -- there'll be no overflow. unsafeAddMutez :: HasCallStack => Mutez -> Mutez -> Mutez -- | Subtraction of Mutez values. Returns Nothing when the -- subtrahend is greater than the minuend, and Just otherwise. subMutez :: Mutez -> Mutez -> Maybe Mutez -- | Partial subtraction of Mutez, should be used only if you're -- sure there'll be no underflow. unsafeSubMutez :: HasCallStack => Mutez -> Mutez -> Mutez -- | Multiplication of Mutez and an integral number. Returns -- Nothing in case of overflow. mulMutez :: Integral a => Mutez -> a -> Maybe Mutez -- | Euclidian division of two Mutez values. divModMutez :: Mutez -> Mutez -> Maybe (Word64, Mutez) -- | Euclidian division of Mutez and a number. divModMutezInt :: Integral a => Mutez -> a -> Maybe (Mutez, Mutez) -- | Time in the real world. Use the functions below to convert it to/from -- Unix time in seconds. newtype Timestamp Timestamp :: POSIXTime -> Timestamp [unTimestamp] :: Timestamp -> POSIXTime timestampToSeconds :: Integral a => Timestamp -> a timestampFromSeconds :: Integer -> Timestamp timestampFromUTCTime :: UTCTime -> Timestamp -- | Add given amount of seconds to a Timestamp. timestampPlusSeconds :: Timestamp -> Integer -> Timestamp -- | Display timestamp in human-readable way as used by Michelson. Uses UTC -- timezone, though maybe we should take it as an argument. -- -- NB: this will render timestamp with up to seconds precision. formatTimestamp :: Timestamp -> Text -- | Parse textual representation of Timestamp. parseTimestamp :: Text -> Maybe Timestamp -- | Quote a value of type Timestamp in -- yyyy-mm-ddThh:mm:ss[.sss]Z format. -- --
--   >>> formatTimestamp [timestampQuote| 2019-02-21T16:54:12.2344523Z |]
--   "2019-02-21T16:54:12Z"
--   
-- -- Inspired by 'time-quote' library. timestampQuote :: QuasiQuoter -- | Return current time as Timestamp. getCurrentTime :: IO Timestamp -- | Timestamp which is always greater than result of -- getCurrentTime. farFuture :: Timestamp -- | Timestamp which is always less than result of getCurrentTime. farPast :: Timestamp -- | Identifier of a network (babylonnet, mainnet, test network or other). -- Evaluated as hash of the genesis block. -- -- The only operation supported for this type is packing. Use case: -- multisig contract, for instance, now includes chain ID into signed -- data "in order to add extra replay protection between the main chain -- and the test chain". newtype ChainId ChainIdUnsafe :: ByteString -> ChainId [unChainId] :: ChainId -> ByteString -- | Construct chain ID from raw bytes. mkChainId :: ByteString -> Maybe ChainId -- | Construct chain ID from raw bytes or fail otherwise. Expects exactly 4 -- bytes. mkChainIdUnsafe :: HasCallStack => ByteString -> ChainId -- | Identifier of a pseudo network. dummyChainId :: ChainId -- | Pretty print ChainId as it is displayed e.g. in -- ./babylonnet.sh head call. -- -- Example of produced value: NetXUdfLh6Gm88t. formatChainId :: ChainId -> Text mformatChainId :: ChainId -> MText parseChainId :: Text -> Either ParseChainIdError ChainId chainIdLength :: Int instance Data.Aeson.Types.ToJSON.ToJSON Tezos.Core.Timestamp instance Data.Aeson.Types.FromJSON.FromJSON Tezos.Core.Timestamp instance Data.Aeson.Types.ToJSON.ToJSON Tezos.Core.ChainId instance Data.Aeson.Types.FromJSON.FromJSON Tezos.Core.ChainId instance Data.Aeson.Types.ToJSON.ToJSON Tezos.Core.Mutez instance Data.Aeson.Types.FromJSON.FromJSON Tezos.Core.Mutez instance GHC.Classes.Eq Tezos.Core.ParseChainIdError instance GHC.Show.Show Tezos.Core.ParseChainIdError instance GHC.Classes.Eq Tezos.Core.ChainId instance GHC.Show.Show Tezos.Core.ChainId instance GHC.Generics.Generic Tezos.Core.Timestamp instance Data.Data.Data Tezos.Core.Timestamp instance GHC.Classes.Ord Tezos.Core.Timestamp instance GHC.Classes.Eq Tezos.Core.Timestamp instance GHC.Show.Show Tezos.Core.Timestamp instance Formatting.Buildable.Buildable Tezos.Core.Mutez instance GHC.Enum.Enum Tezos.Core.Mutez instance GHC.Generics.Generic Tezos.Core.Mutez instance Data.Data.Data Tezos.Core.Mutez instance GHC.Classes.Ord Tezos.Core.Mutez instance GHC.Classes.Eq Tezos.Core.Mutez instance GHC.Show.Show Tezos.Core.Mutez instance Formatting.Buildable.Buildable Tezos.Core.ParseChainIdError instance Formatting.Buildable.Buildable Tezos.Core.ChainId instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Core.ChainId instance Formatting.Buildable.Buildable Tezos.Core.Timestamp instance GHC.Enum.Bounded Tezos.Core.Mutez -- | Address in Tezos. module Tezos.Address -- | Hash of origination command for some contract. newtype ContractHash ContractHash :: ByteString -> ContractHash -- | Data type corresponding to address structure in Tezos. data Address -- | tz address which is a hash of a public key. KeyAddress :: !KeyHash -> Address -- | KT address which corresponds to a callable contract. ContractAddress :: !ContractHash -> Address -- | Smart constructor for KeyAddress. mkKeyAddress :: PublicKey -> Address -- | Deterministically generate a random KeyAddress and discard its -- secret key. detGenKeyAddress :: ByteString -> Address -- | Smart constructor for ContractAddress. Its argument is -- serialized origination operation. -- -- Note: it's quite unsafe to pass ByteString, because we can pass -- some garbage which is not a serialized origination operation, but this -- operation includes contract itself and necessary types are defined in -- *. So we have to serialize this data outside this module and -- pass it here as a ByteString. Alternatively we could add some -- constraint, but it would be almost as unsafe as passing a -- ByteString. For this reason we add Raw suffix to this -- function and provide a safer function in Instr. We may -- reconsider it later. mkContractAddressRaw :: ByteString -> Address -- | Create a dummy ContractHash value. mkContractHashRaw :: ByteString -> ContractHash -- | Errors that can happen during address parsing. data ParseAddressError -- | Address is not in Base58Check format. ParseAddressWrongBase58Check :: ParseAddressError -- | Both address parsers failed with some error. ParseAddressBothFailed :: !CryptoParseError -> !ParseContractAddressError -> ParseAddressError data ParseContractAddressError formatAddress :: Address -> Text mformatAddress :: Address -> MText -- | Parse an address from its human-readable textual representation used -- by Tezos (e. g. "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU"). Or fail if -- it's invalid. parseAddress :: Text -> Either ParseAddressError Address -- | Partial version of parseAddress which assumes that the address -- is correct. Can be used in tests. unsafeParseAddress :: HasCallStack => Text -> Address -- | Parse a TK contract address, fail if address does not match -- the expected format. unsafeParseContractHash :: HasCallStack => Text -> ContractHash instance GHC.Classes.Eq Tezos.Address.ParseAddressError instance GHC.Show.Show Tezos.Address.ParseAddressError instance GHC.Classes.Eq Tezos.Address.ParseContractAddressError instance GHC.Show.Show Tezos.Address.ParseContractAddressError instance GHC.Classes.Ord Tezos.Address.Address instance GHC.Classes.Eq Tezos.Address.Address instance GHC.Show.Show Tezos.Address.Address instance GHC.Classes.Ord Tezos.Address.ContractHash instance GHC.Classes.Eq Tezos.Address.ContractHash instance GHC.Show.Show Tezos.Address.ContractHash instance Formatting.Buildable.Buildable Tezos.Address.ParseAddressError instance Formatting.Buildable.Buildable Tezos.Address.ParseContractAddressError instance Formatting.Buildable.Buildable Tezos.Address.Address instance Data.Aeson.Types.ToJSON.ToJSON Tezos.Address.Address instance Data.Aeson.Types.ToJSON.ToJSONKey Tezos.Address.Address instance Data.Aeson.Types.FromJSON.FromJSON Tezos.Address.Address instance Data.Aeson.Types.FromJSON.FromJSONKey Tezos.Address.Address instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Address.Address instance Data.Aeson.Types.ToJSON.ToJSON Tezos.Address.ContractHash instance Data.Aeson.Types.ToJSON.ToJSONKey Tezos.Address.ContractHash instance Data.Aeson.Types.FromJSON.FromJSON Tezos.Address.ContractHash instance Data.Aeson.Types.FromJSON.FromJSONKey Tezos.Address.ContractHash -- | Untyped Michelson values (i. e. type of a value is not statically -- known). module Michelson.Untyped.Value data Value' op ValueInt :: Integer -> Value' op ValueString :: MText -> Value' op ValueBytes :: InternalByteString -> Value' op ValueUnit :: Value' op ValueTrue :: Value' op ValueFalse :: Value' op ValuePair :: Value' op -> Value' op -> Value' op ValueLeft :: Value' op -> Value' op ValueRight :: Value' op -> Value' op ValueSome :: Value' op -> Value' op ValueNone :: Value' op ValueNil :: Value' op -- | A sequence of elements: can be a list or a set. We can't distinguish -- lists and sets during parsing. ValueSeq :: (NonEmpty $ Value' op) -> Value' op ValueMap :: (NonEmpty $ Elt op) -> Value' op ValueLambda :: NonEmpty op -> Value' op data Elt op Elt :: Value' op -> Value' op -> Elt op -- | ByteString does not have an instance for ToJSON and FromJSON, to avoid -- orphan type class instances, make a new type wrapper around it. newtype InternalByteString InternalByteString :: ByteString -> InternalByteString unInternalByteString :: InternalByteString -> ByteString instance Data.Aeson.Types.ToJSON.ToJSON op => Data.Aeson.Types.ToJSON.ToJSON (Michelson.Untyped.Value.Elt op) instance Data.Aeson.Types.FromJSON.FromJSON op => Data.Aeson.Types.FromJSON.FromJSON (Michelson.Untyped.Value.Elt op) instance Data.Aeson.Types.ToJSON.ToJSON op => Data.Aeson.Types.ToJSON.ToJSON (Michelson.Untyped.Value.Value' op) instance Data.Aeson.Types.FromJSON.FromJSON op => Data.Aeson.Types.FromJSON.FromJSON (Michelson.Untyped.Value.Value' op) instance GHC.Generics.Generic (Michelson.Untyped.Value.Elt op) instance Data.Data.Data op => Data.Data.Data (Michelson.Untyped.Value.Elt op) instance GHC.Base.Functor Michelson.Untyped.Value.Elt instance GHC.Show.Show op => GHC.Show.Show (Michelson.Untyped.Value.Elt op) instance GHC.Classes.Eq op => GHC.Classes.Eq (Michelson.Untyped.Value.Elt op) instance GHC.Generics.Generic (Michelson.Untyped.Value.Value' op) instance Data.Data.Data op => Data.Data.Data (Michelson.Untyped.Value.Value' op) instance GHC.Base.Functor Michelson.Untyped.Value.Value' instance GHC.Show.Show op => GHC.Show.Show (Michelson.Untyped.Value.Value' op) instance GHC.Classes.Eq op => GHC.Classes.Eq (Michelson.Untyped.Value.Value' op) instance GHC.Show.Show Michelson.Untyped.Value.InternalByteString instance GHC.Classes.Eq Michelson.Untyped.Value.InternalByteString instance Data.Data.Data Michelson.Untyped.Value.InternalByteString instance Michelson.Printer.Util.RenderDoc op => Michelson.Printer.Util.RenderDoc (Michelson.Untyped.Value.Value' op) instance Michelson.Printer.Util.RenderDoc op => Michelson.Printer.Util.RenderDoc (Michelson.Untyped.Value.Elt op) instance Michelson.Printer.Util.RenderDoc op => Formatting.Buildable.Buildable (Michelson.Untyped.Value.Value' op) instance Michelson.Printer.Util.RenderDoc op => Formatting.Buildable.Buildable (Michelson.Untyped.Value.Elt op) instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Value.InternalByteString instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Value.InternalByteString -- | Michelson instructions in untyped model. module Michelson.Untyped.Instr -- | Michelson instruction with abstract parameter op. This -- parameter is necessary, because at different stages of our pipeline it -- will be different. Initially it can contain macros and non-flattened -- instructions, but then it contains only vanilla Michelson -- instructions. data InstrAbstract op EXT :: ExtInstrAbstract op -> InstrAbstract op -- | "DROP n" instruction. Note: reference implementation permits int16 -- here. Negative numbers are parsed successfully there, but rejected -- later. Morley is more permissive, so we use Word here, i. e. -- permit more positive numbers. We do not permit negative numbers at -- type level. In practice, probably nobody will ever have numbers -- greater than ≈1000 here, at least due to gas limits. Same reasoning -- applies to other instructions which have a numeric parameter -- representing number of elements on stack. DROPN :: Word -> InstrAbstract op -- | DROP is essentially as special case for DROPN, but we -- need both because they are packed differently. DROP :: InstrAbstract op DUP :: VarAnn -> InstrAbstract op SWAP :: InstrAbstract op DIG :: Word -> InstrAbstract op DUG :: Word -> InstrAbstract op PUSH :: VarAnn -> Type -> Value' op -> InstrAbstract op SOME :: TypeAnn -> VarAnn -> InstrAbstract op NONE :: TypeAnn -> VarAnn -> Type -> InstrAbstract op UNIT :: TypeAnn -> VarAnn -> InstrAbstract op IF_NONE :: [op] -> [op] -> InstrAbstract op PAIR :: TypeAnn -> VarAnn -> FieldAnn -> FieldAnn -> InstrAbstract op CAR :: VarAnn -> FieldAnn -> InstrAbstract op CDR :: VarAnn -> FieldAnn -> InstrAbstract op LEFT :: TypeAnn -> VarAnn -> FieldAnn -> FieldAnn -> Type -> InstrAbstract op RIGHT :: TypeAnn -> VarAnn -> FieldAnn -> FieldAnn -> Type -> InstrAbstract op IF_LEFT :: [op] -> [op] -> InstrAbstract op NIL :: TypeAnn -> VarAnn -> Type -> InstrAbstract op CONS :: VarAnn -> InstrAbstract op IF_CONS :: [op] -> [op] -> InstrAbstract op SIZE :: VarAnn -> InstrAbstract op EMPTY_SET :: TypeAnn -> VarAnn -> Comparable -> InstrAbstract op EMPTY_MAP :: TypeAnn -> VarAnn -> Comparable -> Type -> InstrAbstract op EMPTY_BIG_MAP :: TypeAnn -> VarAnn -> Comparable -> Type -> InstrAbstract op MAP :: VarAnn -> [op] -> InstrAbstract op ITER :: [op] -> InstrAbstract op MEM :: VarAnn -> InstrAbstract op GET :: VarAnn -> InstrAbstract op UPDATE :: VarAnn -> InstrAbstract op IF :: [op] -> [op] -> InstrAbstract op LOOP :: [op] -> InstrAbstract op LOOP_LEFT :: [op] -> InstrAbstract op LAMBDA :: VarAnn -> Type -> Type -> [op] -> InstrAbstract op EXEC :: VarAnn -> InstrAbstract op APPLY :: VarAnn -> InstrAbstract op DIP :: [op] -> InstrAbstract op DIPN :: Word -> [op] -> InstrAbstract op FAILWITH :: InstrAbstract op CAST :: VarAnn -> Type -> InstrAbstract op RENAME :: VarAnn -> InstrAbstract op PACK :: VarAnn -> InstrAbstract op UNPACK :: VarAnn -> Type -> InstrAbstract op CONCAT :: VarAnn -> InstrAbstract op SLICE :: VarAnn -> InstrAbstract op ISNAT :: VarAnn -> InstrAbstract op ADD :: VarAnn -> InstrAbstract op SUB :: VarAnn -> InstrAbstract op MUL :: VarAnn -> InstrAbstract op EDIV :: VarAnn -> InstrAbstract op ABS :: VarAnn -> InstrAbstract op NEG :: VarAnn -> InstrAbstract op LSL :: VarAnn -> InstrAbstract op LSR :: VarAnn -> InstrAbstract op OR :: VarAnn -> InstrAbstract op AND :: VarAnn -> InstrAbstract op XOR :: VarAnn -> InstrAbstract op NOT :: VarAnn -> InstrAbstract op COMPARE :: VarAnn -> InstrAbstract op EQ :: VarAnn -> InstrAbstract op NEQ :: VarAnn -> InstrAbstract op LT :: VarAnn -> InstrAbstract op GT :: VarAnn -> InstrAbstract op LE :: VarAnn -> InstrAbstract op GE :: VarAnn -> InstrAbstract op INT :: VarAnn -> InstrAbstract op SELF :: VarAnn -> InstrAbstract op CONTRACT :: VarAnn -> FieldAnn -> Type -> InstrAbstract op TRANSFER_TOKENS :: VarAnn -> InstrAbstract op SET_DELEGATE :: VarAnn -> InstrAbstract op CREATE_CONTRACT :: VarAnn -> VarAnn -> Contract' op -> InstrAbstract op IMPLICIT_ACCOUNT :: VarAnn -> InstrAbstract op NOW :: VarAnn -> InstrAbstract op AMOUNT :: VarAnn -> InstrAbstract op BALANCE :: VarAnn -> InstrAbstract op CHECK_SIGNATURE :: VarAnn -> InstrAbstract op SHA256 :: VarAnn -> InstrAbstract op SHA512 :: VarAnn -> InstrAbstract op BLAKE2B :: VarAnn -> InstrAbstract op HASH_KEY :: VarAnn -> InstrAbstract op STEPS_TO_QUOTA :: VarAnn -> InstrAbstract op SOURCE :: VarAnn -> InstrAbstract op SENDER :: VarAnn -> InstrAbstract op ADDRESS :: VarAnn -> InstrAbstract op CHAIN_ID :: VarAnn -> InstrAbstract op data ExpandedOp PrimEx :: ExpandedInstr -> ExpandedOp SeqEx :: [ExpandedOp] -> ExpandedOp WithSrcEx :: InstrCallStack -> ExpandedOp -> ExpandedOp type ExpandedInstr = InstrAbstract ExpandedOp -- | Flatten all SeqEx in ExpandedOp. This function is mostly -- for testing. It returns instructions with the same logic, but they are -- not strictly equivalent, because they are serialized differently -- (grouping instructions into sequences affects the way they are -- PACK'ed). flattenExpandedOp :: ExpandedOp -> [ExpandedInstr] -- | Data necessary to originate a contract. data OriginationOperation OriginationOperation :: !Address -> !Maybe KeyHash -> !Mutez -> !Value' ExpandedOp -> !Contract' ExpandedOp -> OriginationOperation -- | Originator of the contract. [ooOriginator] :: OriginationOperation -> !Address -- | Optional delegate. [ooDelegate] :: OriginationOperation -> !Maybe KeyHash -- | Initial balance of the contract. [ooBalance] :: OriginationOperation -> !Mutez -- | Initial storage value of the contract. [ooStorage] :: OriginationOperation -> !Value' ExpandedOp -- | The contract itself. [ooContract] :: OriginationOperation -> !Contract' ExpandedOp -- | Compute address of a contract from its origination operation. -- -- TODO [TM-62] It's certainly imprecise, real Tezos implementation -- doesn't use JSON, but we don't need precise format yet, so we just use -- some serialization format (JSON because we have necessary instances -- already). mkContractAddress :: OriginationOperation -> Address instance GHC.Generics.Generic Michelson.Untyped.Instr.OriginationOperation instance GHC.Show.Show Michelson.Untyped.Instr.OriginationOperation instance GHC.Generics.Generic Michelson.Untyped.Instr.ExpandedOp instance Data.Data.Data Michelson.Untyped.Instr.ExpandedOp instance GHC.Classes.Eq Michelson.Untyped.Instr.ExpandedOp instance GHC.Show.Show Michelson.Untyped.Instr.ExpandedOp instance GHC.Generics.Generic (Michelson.Untyped.Instr.InstrAbstract op) instance Data.Data.Data op => Data.Data.Data (Michelson.Untyped.Instr.InstrAbstract op) instance GHC.Base.Functor Michelson.Untyped.Instr.InstrAbstract instance GHC.Show.Show op => GHC.Show.Show (Michelson.Untyped.Instr.InstrAbstract op) instance GHC.Classes.Eq op => GHC.Classes.Eq (Michelson.Untyped.Instr.InstrAbstract op) instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Instr.OriginationOperation instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Instr.OriginationOperation instance Michelson.Printer.Util.RenderDoc Michelson.Untyped.Instr.ExpandedOp instance Formatting.Buildable.Buildable Michelson.Untyped.Instr.ExpandedOp instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Untyped.Instr.ExpandedOp instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Untyped.Instr.ExpandedOp instance Michelson.Printer.Util.RenderDoc op => Michelson.Printer.Util.RenderDoc (Michelson.Untyped.Instr.InstrAbstract op) instance (Michelson.Printer.Util.RenderDoc op, Formatting.Buildable.Buildable op) => Formatting.Buildable.Buildable (Michelson.Untyped.Instr.InstrAbstract op) instance Data.Aeson.Types.ToJSON.ToJSON op => Data.Aeson.Types.ToJSON.ToJSON (Michelson.Untyped.Instr.InstrAbstract op) instance Data.Aeson.Types.FromJSON.FromJSON op => Data.Aeson.Types.FromJSON.FromJSON (Michelson.Untyped.Instr.InstrAbstract op) -- | Some simple aliases for Michelson types. module Michelson.Untyped.Aliases type Contract = Contract' ExpandedOp type Value = Value' ExpandedOp type ExpandedExtInstr = ExtInstrAbstract ExpandedOp module Michelson.Untyped -- | TxData type and associated functionality. module Michelson.Runtime.TxData -- | Data associated with a particular transaction. data TxData TxData :: !Address -> !Value -> !Mutez -> TxData [tdSenderAddress] :: TxData -> !Address [tdParameter] :: TxData -> !Value [tdAmount] :: TxData -> !Mutez tdSenderAddressL :: Lens' TxData Address tdParameterL :: Lens' TxData Value tdAmountL :: Lens' TxData Mutez instance GHC.Classes.Eq Michelson.Runtime.TxData.TxData instance GHC.Show.Show Michelson.Runtime.TxData.TxData module Lorentz.UStore.Common fieldNameToMText :: forall field. KnownSymbol field => MText module Util.TypeTuple.Class -- | Building a record from tuple. -- -- It differs from similar typeclass in FromTuple module in that -- it allows type inference outside-in - knowing desired Rec you -- know which tuple should be provided - this improves error messages -- when constructing concrete Rec objects. class RecFromTuple r where { type family IsoRecTuple r :: Type; } recFromTuple :: RecFromTuple r => IsoRecTuple r -> r -- | Template haskell generator for RecFromTuple, in a separate -- module because of staging restrictions. module Util.TypeTuple.TH -- | Produce RecFromTuple instance for tuple of the given length. deriveRecFromTuple :: Word -> Q [Dec] module Util.TypeTuple.Instances instance forall u (f :: u -> *). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[]) instance forall u (f :: u -> *) (x :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u) (x18 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u) (x18 :: u) (x19 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u) (x18 :: u) (x19 :: u) (x20 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u) (x18 :: u) (x19 :: u) (x20 :: u) (x21 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u) (x18 :: u) (x19 :: u) (x20 :: u) (x21 :: u) (x22 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u) (x18 :: u) (x19 :: u) (x20 :: u) (x21 :: u) (x22 :: u) (x23 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u) (x18 :: u) (x19 :: u) (x20 :: u) (x21 :: u) (x22 :: u) (x23 :: u) (x24 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24]) instance forall u (f :: u -> *) (x1 :: u) (x2 :: u) (x3 :: u) (x4 :: u) (x5 :: u) (x6 :: u) (x7 :: u) (x8 :: u) (x9 :: u) (x10 :: u) (x11 :: u) (x12 :: u) (x13 :: u) (x14 :: u) (x15 :: u) (x16 :: u) (x17 :: u) (x18 :: u) (x19 :: u) (x20 :: u) (x21 :: u) (x22 :: u) (x23 :: u) (x24 :: u) (x25 :: u). Util.TypeTuple.Class.RecFromTuple (Data.Vinyl.Core.Rec f '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25]) -- | Conversions between tuples and list-like types. module Util.TypeTuple -- | Building a record from tuple. -- -- It differs from similar typeclass in FromTuple module in that -- it allows type inference outside-in - knowing desired Rec you -- know which tuple should be provided - this improves error messages -- when constructing concrete Rec objects. class RecFromTuple r where { type family IsoRecTuple r :: Type; } recFromTuple :: RecFromTuple r => IsoRecTuple r -> r -- | Utility for Typeable. module Util.Typeable -- | Like gcast, casts some container's elements, producing -- informative error on mismatch. gcastE :: forall a b t. (Typeable a, Typeable b) => t a -> Either Text (t b) -- | Proxy version of eqT. eqP :: (Typeable a, Typeable b) => Proxy a -> Proxy b -> Maybe (a :~: b) -- | Suppose you have a data type X with parameter a and -- you have two values: `x1 :: X a1` and `x2 :: X a2`. You can't compare -- them using ==, because they have different types. However, you -- can compare them using eqParam1 as long as both parameters are -- Typeable. eqParam1 :: forall a1 a2 t. (Typeable a1, Typeable a2, Eq (t a1)) => t a1 -> t a2 -> Bool -- | Version of eqParam1 for types with 2 parameters. eqParam2 :: forall a1 a2 b1 b2 t. (Typeable a1, Typeable a2, Typeable b1, Typeable b2, Eq (t a1 b2)) => t a1 b1 -> t a2 b2 -> Bool -- | Version of eqParam1 for types with 3 parameters. eqParam3 :: forall a1 a2 b1 b2 c1 c2 t. (Typeable a1, Typeable a2, Typeable b1, Typeable b2, Typeable c1, Typeable c2, Eq (t a1 b1 c1)) => t a1 b1 c1 -> t a2 b2 c2 -> Bool -- | Compare two entries of completely different types. eqExt :: forall a1 a2. (Typeable a1, Typeable a2, Eq a1) => a1 -> a2 -> Bool -- | Extension of eqExt to compare function. compareExt :: forall a1 a2. (Typeable a1, Typeable a2, Ord a1) => a1 -> a2 -> Ordering -- | Module, providing Notes t data type, which holds annotations -- for a given type t. -- -- Annotation type Notes t is a tree, each leaf is either a star -- (*) or a constructor holding some annotation data for a given -- type t. Star corresponds to the case when given Michelson -- type contains no annotations. -- -- This module also provides type class Converge along with some -- utility functions which are used to combine two annotations trees -- a and b into a new one c in such a way that -- c can be obtained from both a and b by -- replacing some * leafs with type or/and field annotations. module Michelson.Typed.Annotation -- | Data type, holding annotation data for a given Michelson type -- t. -- -- Each constructor corresponds to exactly one constructor of T -- and holds all type and field annotations that can be attributed to a -- Michelson type corrspoding to t. data Notes t [NTc] :: TypeAnn -> Notes ( 'Tc ct) [NTKey] :: TypeAnn -> Notes 'TKey [NTUnit] :: TypeAnn -> Notes 'TUnit [NTSignature] :: TypeAnn -> Notes 'TSignature [NTChainId] :: TypeAnn -> Notes 'TChainId [NTOption] :: TypeAnn -> Notes t -> Notes ( 'TOption t) [NTList] :: TypeAnn -> Notes t -> Notes ( 'TList t) [NTSet] :: TypeAnn -> TypeAnn -> Notes ( 'TSet ct) [NTOperation] :: TypeAnn -> Notes 'TOperation [NTContract] :: TypeAnn -> Notes t -> Notes ( 'TContract t) [NTPair] :: TypeAnn -> FieldAnn -> FieldAnn -> Notes p -> Notes q -> Notes ( 'TPair p q) [NTOr] :: TypeAnn -> FieldAnn -> FieldAnn -> Notes p -> Notes q -> Notes ( 'TOr p q) [NTLambda] :: TypeAnn -> Notes p -> Notes q -> Notes ( 'TLambda p q) [NTMap] :: TypeAnn -> TypeAnn -> Notes v -> Notes ( 'TMap k v) [NTBigMap] :: TypeAnn -> TypeAnn -> Notes v -> Notes ( 'TBigMap k v) data AnnConvergeError [AnnConvergeError] :: forall (tag :: Type). (Buildable (Annotation tag), Show (Annotation tag), Typeable tag) => Annotation tag -> Annotation tag -> AnnConvergeError -- | Combines two annotations trees a and b into a new -- one c in such a way that c can be obtained from both -- a and b by replacing some empty leaves with type -- or/and field annotations. converge :: Notes t -> Notes t -> Either AnnConvergeError (Notes t) -- | Converge two type or field notes (which may be wildcards). convergeAnns :: forall (tag :: Type). (Buildable (Annotation tag), Show (Annotation tag), Typeable tag) => Annotation tag -> Annotation tag -> Either AnnConvergeError (Annotation tag) orAnn :: Annotation t -> Annotation t -> Annotation t -- | Checks if no annotations are present. isStar :: SingI t => Notes t -> Bool -- | In memory of NStar constructor. Generates notes with no -- annotations. starNotes :: forall t. SingI t => Notes t instance GHC.Show.Show (Michelson.Typed.Annotation.Notes t) instance GHC.Classes.Eq (Michelson.Typed.Annotation.Notes t) instance GHC.Show.Show Michelson.Typed.Annotation.AnnConvergeError instance GHC.Classes.Eq Michelson.Typed.Annotation.AnnConvergeError instance Formatting.Buildable.Buildable Michelson.Typed.Annotation.AnnConvergeError -- | Module, containing functions to convert -- Michelson.Untyped.Type to Michelson.Typed.T.T -- Michelson type representation (type stripped off all annotations) and -- to Michelson.Typed.Annotation.Notes value (which contains -- field and type annotations for a given Michelson type). -- -- I.e. Michelson.Untyped.Type is split to value t :: T -- and value of type Notes t for which t is a type -- representation of value t. module Michelson.Typed.Extract fromUType :: Type -> T mkUType :: Sing x -> Notes x -> Type -- | Converts from T to Type. toUType :: T -> Type -- | Convert Type to the isomorphic set of information from typed -- world. withUType :: Type -> (forall t. (Typeable t, SingI t) => (Sing t, Notes t) -> r) -> r -- | Utilities for lightweight entrypoints support. module Michelson.Typed.EntryPoints -- | Entrypoint name. -- -- Empty if this entrypoint is default one. Cannot be equal to "default", -- the reference implementation forbids that. Also, set of allowed -- characters should be the same as in annotations. newtype EpName EpNameUnsafe :: Text -> EpName [unEpName] :: EpName -> Text pattern NoEpName :: EpName -- | Make up EpName from annotation in parameter type declaration. -- -- Returns Nothing if no entrypoint is assigned here. epNameFromParamAnn :: FieldAnn -> Maybe EpName -- | Turn entrypoint name into annotation for contract parameter -- declaration. epNameToParamAnn :: EpName -> FieldAnn -- | Make up EpName from annotation which is reference to an -- entrypoint (e.g. annotation in CONTRACT instruction). -- -- Fails if annotation is invalid. epNameFromRefAnn :: FieldAnn -> Either EpNameFromRefAnnError EpName -- | Turn entrypoint name into annotation used as reference to entrypoint. epNameToRefAnn :: EpName -> FieldAnn data EpNameFromRefAnnError InEpNameBadAnnotation :: FieldAnn -> EpNameFromRefAnnError -- | Address with optional entrypoint name attached to it. TODO: come up -- with better name? data EpAddress EpAddress :: Address -> EpName -> EpAddress -- | Address itself [eaAddress] :: EpAddress -> Address -- | Entrypoint name (might be empty) [eaEntryPoint] :: EpAddress -> EpName data ParseEpAddressError ParseEpAddressBadAddress :: ParseAddressError -> ParseEpAddressError ParseEpAddressRefAnnError :: EpNameFromRefAnnError -> ParseEpAddressError formatEpAddress :: EpAddress -> Text mformatEpAddress :: EpAddress -> MText -- | Parse an address which can be suffixed with entrypoint name (e.g. -- "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU%entrypoint"). parseEpAddress :: Text -> Either ParseEpAddressError EpAddress unsafeParseEpAddress :: HasCallStack => Text -> EpAddress -- | Annotations for contract parameter declaration. -- -- Following the Michelson specification, this type has the following -- invariants: 1. No entrypoint name is duplicated. 2. If -- default entrypoint is explicitly assigned, no "arm" remains -- uncallable. newtype ParamNotes (t :: T) ParamNotesUnsafe :: Notes t -> ParamNotes [unParamNotes] :: ParamNotes -> Notes t data ArmCoord AcLeft :: ArmCoord AcRight :: ArmCoord -- | Coordinates of "arm" in Or tree, used solely in error messages. type ArmCoords = [ArmCoord] -- | Errors specific to parameter type declaration (entrypoints). data ParamEpError ParamEpDuplicatedNames :: NonEmpty EpName -> ParamEpError ParamEpUncallableArm :: ArmCoords -> ParamEpError -- | Construct ParamNotes performing all necessary checks. mkParamNotes :: Notes t -> Either ParamEpError (ParamNotes t) -- | Describes how to construct full contract parameter from given -- entrypoint argument. -- -- This could be just wrapper over Value arg -> Value param, -- but we cannot use Value type in this module easily. data EpLiftSequence (arg :: T) (param :: T) [EplArgHere] :: EpLiftSequence arg arg [EplWrapLeft] :: EpLiftSequence arg subparam -> EpLiftSequence arg ( 'TOr subparam r) [EplWrapRight] :: EpLiftSequence arg subparam -> EpLiftSequence arg ( 'TOr l subparam) -- | Reference for calling a specific entrypoint of type arg. data EntryPointCallT (param :: T) (arg :: T) EntryPointCall :: EpName -> Proxy param -> EpLiftSequence arg param -> EntryPointCallT -- | Name of entrypoint. [epcName] :: EntryPointCallT -> EpName -- | Proxy of parameter, to make parameter type more easily fetchable. [epcParamProxy] :: EntryPointCallT -> Proxy param -- | How to call this entrypoint in the corresponding contract. [epcLiftSequence] :: EntryPointCallT -> EpLiftSequence arg param -- | EntryPointCallT with hidden parameter type. -- -- This requires argument to satisfy ParameterScope constraint. -- Strictly speaking, entrypoint argument may one day start having -- different set of constraints comparing to ones applied to parameter, -- but this seems unlikely. data SomeEntryPointCallT (arg :: T) SomeEpc :: EntryPointCallT param arg -> SomeEntryPointCallT sepcName :: SomeEntryPointCallT arg -> EpName -- | Build EntryPointCallT. -- -- Here we accept entrypoint name and type information for the parameter -- of target contract. -- -- Returns Nothing if entrypoint is not found. mkEntryPointCall :: ParameterScope param => EpName -> (Sing param, Notes param) -> (forall arg. ParameterScope arg => (Notes arg, EntryPointCallT param arg) -> r) -> Maybe r -- | For implicit account, which type its parameter seems to have from -- outside. tyImplicitAccountParam :: (Sing 'TUnit, Notes 'TUnit) instance GHC.Classes.Eq Michelson.Typed.EntryPoints.ParamEpError instance GHC.Show.Show Michelson.Typed.EntryPoints.ParamEpError instance GHC.Classes.Eq Michelson.Typed.EntryPoints.ArmCoord instance GHC.Show.Show Michelson.Typed.EntryPoints.ArmCoord instance GHC.Classes.Eq (Michelson.Typed.EntryPoints.ParamNotes t) instance GHC.Show.Show (Michelson.Typed.EntryPoints.ParamNotes t) instance GHC.Classes.Eq Michelson.Typed.EntryPoints.ParseEpAddressError instance GHC.Show.Show Michelson.Typed.EntryPoints.ParseEpAddressError instance GHC.Classes.Ord Michelson.Typed.EntryPoints.EpAddress instance GHC.Classes.Eq Michelson.Typed.EntryPoints.EpAddress instance GHC.Show.Show Michelson.Typed.EntryPoints.EpAddress instance GHC.Classes.Eq Michelson.Typed.EntryPoints.EpNameFromRefAnnError instance GHC.Show.Show Michelson.Typed.EntryPoints.EpNameFromRefAnnError instance GHC.Classes.Ord Michelson.Typed.EntryPoints.EpName instance GHC.Classes.Eq Michelson.Typed.EntryPoints.EpName instance GHC.Show.Show Michelson.Typed.EntryPoints.EpName instance GHC.Classes.Eq (Michelson.Typed.EntryPoints.EpLiftSequence arg param) instance GHC.Show.Show (Michelson.Typed.EntryPoints.EpLiftSequence arg param) instance GHC.Classes.Eq (Michelson.Typed.EntryPoints.EntryPointCallT param arg) instance GHC.Show.Show (Michelson.Typed.EntryPoints.EntryPointCallT param arg) instance GHC.Show.Show (Michelson.Typed.EntryPoints.SomeEntryPointCallT arg) instance GHC.Classes.Eq (Michelson.Typed.EntryPoints.SomeEntryPointCallT arg) instance Formatting.Buildable.Buildable (Michelson.Typed.EntryPoints.SomeEntryPointCallT arg) instance Michelson.Typed.Scope.ParameterScope arg => Data.Default.Class.Default (Michelson.Typed.EntryPoints.SomeEntryPointCallT arg) instance Formatting.Buildable.Buildable (Michelson.Typed.EntryPoints.EntryPointCallT param arg) instance (param Data.Type.Equality.~ arg) => Data.Default.Class.Default (Michelson.Typed.EntryPoints.EntryPointCallT param arg) instance Formatting.Buildable.Buildable (Michelson.Typed.EntryPoints.EpLiftSequence arg param) instance Formatting.Buildable.Buildable Michelson.Typed.EntryPoints.ParamEpError instance Formatting.Buildable.Buildable Michelson.Typed.EntryPoints.ArmCoord instance Formatting.Buildable.Buildable Michelson.Typed.EntryPoints.ParseEpAddressError instance Formatting.Buildable.Buildable Michelson.Typed.EntryPoints.EpAddress instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Annotation.FieldAnn => Test.QuickCheck.Arbitrary.Arbitrary Michelson.Typed.EntryPoints.EpAddress instance Formatting.Buildable.Buildable Michelson.Typed.EntryPoints.EpNameFromRefAnnError instance Formatting.Buildable.Buildable Michelson.Typed.EntryPoints.EpName instance Data.Default.Class.Default Michelson.Typed.EntryPoints.EpName instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Annotation.FieldAnn => Test.QuickCheck.Arbitrary.Arbitrary Michelson.Typed.EntryPoints.EpName -- | Module, containing CValue data type which represents Michelson -- comparable values. module Michelson.Typed.CValue -- | Representation of comparable value in Michelson language. -- -- By specification, we're allowed to compare only following types: int, -- nat, string, bytes, mutez, bool, key_hash, timestamp, address. -- -- Only these values can be used as map keys or set elements. data CValue t [CvInt] :: Integer -> CValue 'CInt [CvNat] :: Natural -> CValue 'CNat [CvString] :: MText -> CValue 'CString [CvBytes] :: ByteString -> CValue 'CBytes [CvMutez] :: Mutez -> CValue 'CMutez [CvBool] :: Bool -> CValue 'CBool [CvKeyHash] :: KeyHash -> CValue 'CKeyHash [CvTimestamp] :: Timestamp -> CValue 'CTimestamp [CvAddress] :: EpAddress -> CValue 'CAddress instance GHC.Show.Show (Michelson.Typed.CValue.CValue t) instance GHC.Classes.Eq (Michelson.Typed.CValue.CValue t) instance GHC.Classes.Ord (Michelson.Typed.CValue.CValue t) -- | Module, containing data types for Michelson value. module Michelson.Typed.Value -- | Representation of Michelson value. -- -- Type parameter instr stands for Michelson instruction type, -- i.e. data type to represent an instruction of language. data Value' instr t [VC] :: CValue t -> Value' instr ( 'Tc t) [VKey] :: PublicKey -> Value' instr 'TKey [VUnit] :: Value' instr 'TUnit [VSignature] :: Signature -> Value' instr 'TSignature [VChainId] :: ChainId -> Value' instr 'TChainId [VOption] :: forall t instr. Maybe (Value' instr t) -> Value' instr ( 'TOption t) [VList] :: forall t instr. [Value' instr t] -> Value' instr ( 'TList t) [VSet] :: forall t instr. Set (CValue t) -> Value' instr ( 'TSet t) [VOp] :: Operation' instr -> Value' instr 'TOperation [VContract] :: forall arg instr. Address -> SomeEntryPointCallT arg -> Value' instr ( 'TContract arg) [VPair] :: forall l r instr. (Value' instr l, Value' instr r) -> Value' instr ( 'TPair l r) [VOr] :: forall l r instr. Either (Value' instr l) (Value' instr r) -> Value' instr ( 'TOr l r) [VLam] :: forall inp out instr. forall i o. (Show (instr i o), Eq (instr i o)) => RemFail instr (inp : '[]) (out : '[]) -> Value' instr ( 'TLambda inp out) [VMap] :: forall k v instr. Map (CValue k) (Value' instr v) -> Value' instr ( 'TMap k v) [VBigMap] :: forall k v instr. Map (CValue k) (Value' instr v) -> Value' instr ( 'TBigMap k v) data SomeValue' instr [SomeValue] :: (Typeable t, SingI t) => Value' instr t -> SomeValue' instr data SomeConstrainedValue' instr (c :: T -> Constraint) [SomeConstrainedValue] :: forall (t :: T) (c :: T -> Constraint) instr. c t => Value' instr t -> SomeConstrainedValue' instr c type ContractInp1 param st = 'TPair param st type ContractInp param st = '[ContractInp1 param st] type ContractOut1 st = 'TPair ( 'TList 'TOperation) st type ContractOut st = '[ContractOut1 st] data CreateContract instr cp st CreateContract :: !Address -> !Maybe KeyHash -> !Mutez -> !Value' instr st -> !instr (ContractInp cp st) (ContractOut st) -> CreateContract instr cp st [ccOriginator] :: CreateContract instr cp st -> !Address [ccDelegate] :: CreateContract instr cp st -> !Maybe KeyHash [ccBalance] :: CreateContract instr cp st -> !Mutez [ccStorageVal] :: CreateContract instr cp st -> !Value' instr st [ccContractCode] :: CreateContract instr cp st -> !instr (ContractInp cp st) (ContractOut st) -- | Representation of comparable value in Michelson language. -- -- By specification, we're allowed to compare only following types: int, -- nat, string, bytes, mutez, bool, key_hash, timestamp, address. -- -- Only these values can be used as map keys or set elements. data CValue t [CvInt] :: Integer -> CValue 'CInt [CvNat] :: Natural -> CValue 'CNat [CvString] :: MText -> CValue 'CString [CvBytes] :: ByteString -> CValue 'CBytes [CvMutez] :: Mutez -> CValue 'CMutez [CvBool] :: Bool -> CValue 'CBool [CvKeyHash] :: KeyHash -> CValue 'CKeyHash [CvTimestamp] :: Timestamp -> CValue 'CTimestamp [CvAddress] :: EpAddress -> CValue 'CAddress -- | Data type, representing operation, list of which is returned by -- Michelson contract (according to calling convention). -- -- These operations are to be further executed against system state after -- the contract execution. data Operation' instr [OpTransferTokens] :: ParameterScope p => TransferTokens instr p -> Operation' instr [OpSetDelegate] :: SetDelegate -> Operation' instr [OpCreateContract] :: (Show (instr (ContractInp cp st) (ContractOut st)), Typeable instr, ParameterScope cp, StorageScope st) => CreateContract instr cp st -> Operation' instr data SetDelegate SetDelegate :: !Maybe KeyHash -> SetDelegate [sdMbKeyHash] :: SetDelegate -> !Maybe KeyHash data TransferTokens instr p TransferTokens :: !Value' instr p -> !Mutez -> !Value' instr ( 'TContract p) -> TransferTokens instr p [ttTransferArgument] :: TransferTokens instr p -> !Value' instr p [ttAmount] :: TransferTokens instr p -> !Mutez [ttContract] :: TransferTokens instr p -> !Value' instr ( 'TContract p) -- | Wrapper over instruction which remembers whether this instruction -- always fails or not. data RemFail (instr :: k -> k -> Type) (i :: k) (o :: k) [RfNormal] :: instr i o -> RemFail instr i o [RfAlwaysFails] :: (forall o'. instr i o') -> RemFail instr i o -- | Merge two execution branches. rfMerge :: (forall o'. instr i1 o' -> instr i2 o' -> instr i3 o') -> RemFail instr i1 o -> RemFail instr i2 o -> RemFail instr i3 o -- | Get code disregard whether it always fails or not. rfAnyInstr :: RemFail instr i o -> instr i o -- | Modify inner code. rfMapAnyInstr :: (forall o'. instr i1 o' -> instr i2 o') -> RemFail instr i1 o -> RemFail instr i2 o -- | Make value of contract type which refers to the given address -- and does not call any entrypoint. addressToVContract :: forall t instr. ParameterScope t => Address -> Value' instr ( 'TContract t) buildVContract :: Value' instr ( 'TContract arg) -> Builder -- | Turn EpLiftSequence into actual function on Values. compileEpLiftSequence :: EpLiftSequence arg param -> Value' instr arg -> Value' instr param instance GHC.Classes.Eq (Michelson.Typed.Value.TransferTokens instr p) instance GHC.Show.Show (Michelson.Typed.Value.TransferTokens instr p) instance GHC.Classes.Eq Michelson.Typed.Value.SetDelegate instance GHC.Show.Show Michelson.Typed.Value.SetDelegate instance GHC.Show.Show (Michelson.Typed.Value.Operation' instr) instance GHC.Show.Show (Michelson.Typed.Value.CreateContract instr cp st) instance GHC.Classes.Eq (Michelson.Typed.Value.CreateContract instr cp st) instance forall k (instr :: k -> k -> *) (i :: k) (o :: k). (forall (o' :: k). GHC.Show.Show (instr i o')) => GHC.Show.Show (Michelson.Typed.Value.RemFail instr i o) instance GHC.Show.Show (Michelson.Typed.Value.Value' instr t) instance GHC.Classes.Eq (Michelson.Typed.Value.Value' instr t) instance GHC.Show.Show (Michelson.Typed.Value.SomeValue' instr) instance GHC.Show.Show (Michelson.Typed.Value.SomeConstrainedValue' instr c) instance GHC.Classes.Eq (Michelson.Typed.Value.SomeValue' instr) instance Formatting.Buildable.Buildable (Michelson.Typed.Value.Operation' instr) instance GHC.Classes.Eq (Michelson.Typed.Value.Operation' instr) instance Formatting.Buildable.Buildable (Michelson.Typed.Value.TransferTokens instr p) instance Formatting.Buildable.Buildable (Michelson.Typed.Value.CreateContract instr cp st) instance forall k (instr :: k -> k -> *) (i :: k) (o :: k). GHC.Classes.Eq (instr i o) => GHC.Classes.Eq (Michelson.Typed.Value.RemFail instr i o) instance Formatting.Buildable.Buildable Michelson.Typed.Value.SetDelegate -- | Module, containing type classes for operating with Michelson values in -- the context of polymorphic stack type operations. module Michelson.Typed.Polymorphic class EDivOp (n :: CT) (m :: CT) where { type family EDivOpRes n m :: CT; type family EModOpRes n m :: CT; } evalEDivOp :: EDivOp n m => CValue n -> CValue m -> Value' instr ( 'TOption ( 'TPair ( 'Tc (EDivOpRes n m)) ( 'Tc (EModOpRes n m)))) class MemOp (c :: T) where { type family MemOpKey c :: CT; } evalMem :: MemOp c => CValue (MemOpKey c) -> Value' cp c -> Bool class MapOp (c :: T) where { type family MapOpInp c :: T; type family MapOpRes c :: T -> T; } mapOpToList :: MapOp c => Value' instr c -> [Value' instr (MapOpInp c)] mapOpFromList :: MapOp c => Value' instr c -> [Value' instr b] -> Value' instr (MapOpRes c b) class IterOp (c :: T) where { type family IterOpEl c :: T; } iterOpDetachOne :: IterOp c => Value' instr c -> (Maybe (Value' instr (IterOpEl c)), Value' instr c) class SizeOp (c :: T) evalSize :: SizeOp c => Value' cp c -> Int class GetOp (c :: T) where { type family GetOpKey c :: CT; type family GetOpVal c :: T; } evalGet :: GetOp c => CValue (GetOpKey c) -> Value' cp c -> Maybe (Value' cp (GetOpVal c)) class UpdOp (c :: T) where { type family UpdOpKey c :: CT; type family UpdOpParams c :: T; } evalUpd :: UpdOp c => CValue (UpdOpKey c) -> Value' cp (UpdOpParams c) -> Value' cp c -> Value' cp c class SliceOp (c :: T) evalSlice :: SliceOp c => Natural -> Natural -> Value' cp c -> Maybe (Value' cp c) class ConcatOp (c :: T) evalConcat :: ConcatOp c => Value' cp c -> Value' cp c -> Value' cp c evalConcat' :: ConcatOp c => [Value' cp c] -> Value' cp c instance Michelson.Typed.Polymorphic.EDivOp 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Polymorphic.EDivOp 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Polymorphic.EDivOp 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Polymorphic.EDivOp 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Polymorphic.EDivOp 'Michelson.Untyped.Type.CMutez 'Michelson.Untyped.Type.CMutez instance Michelson.Typed.Polymorphic.EDivOp 'Michelson.Untyped.Type.CMutez 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Polymorphic.SliceOp ('Michelson.Typed.T.Tc 'Michelson.Untyped.Type.CString) instance Michelson.Typed.Polymorphic.SliceOp ('Michelson.Typed.T.Tc 'Michelson.Untyped.Type.CBytes) instance Michelson.Typed.Polymorphic.ConcatOp ('Michelson.Typed.T.Tc 'Michelson.Untyped.Type.CString) instance Michelson.Typed.Polymorphic.ConcatOp ('Michelson.Typed.T.Tc 'Michelson.Untyped.Type.CBytes) instance Michelson.Typed.Polymorphic.GetOp ('Michelson.Typed.T.TBigMap k v) instance Michelson.Typed.Polymorphic.GetOp ('Michelson.Typed.T.TMap k v) instance Michelson.Typed.Polymorphic.UpdOp ('Michelson.Typed.T.TMap k v) instance Michelson.Typed.Polymorphic.UpdOp ('Michelson.Typed.T.TBigMap k v) instance Michelson.Typed.Polymorphic.UpdOp ('Michelson.Typed.T.TSet a) instance Michelson.Typed.Polymorphic.SizeOp ('Michelson.Typed.T.Tc 'Michelson.Untyped.Type.CString) instance Michelson.Typed.Polymorphic.SizeOp ('Michelson.Typed.T.Tc 'Michelson.Untyped.Type.CBytes) instance Michelson.Typed.Polymorphic.SizeOp ('Michelson.Typed.T.TSet a) instance Michelson.Typed.Polymorphic.SizeOp ('Michelson.Typed.T.TList a) instance Michelson.Typed.Polymorphic.SizeOp ('Michelson.Typed.T.TMap k v) instance Michelson.Typed.Polymorphic.IterOp ('Michelson.Typed.T.TMap k v) instance Michelson.Typed.Polymorphic.IterOp ('Michelson.Typed.T.TList e) instance Michelson.Typed.Polymorphic.IterOp ('Michelson.Typed.T.TSet e) instance Michelson.Typed.Polymorphic.MapOp ('Michelson.Typed.T.TMap k v) instance Michelson.Typed.Polymorphic.MapOp ('Michelson.Typed.T.TList e) instance Michelson.Typed.Polymorphic.MemOp ('Michelson.Typed.T.TSet e) instance Michelson.Typed.Polymorphic.MemOp ('Michelson.Typed.T.TMap k v) instance Michelson.Typed.Polymorphic.MemOp ('Michelson.Typed.T.TBigMap k v) -- | Module, containing some boilerplate for support of arithmetic -- operations in Michelson language. module Michelson.Typed.Arith -- | Class for binary arithmetic operation. -- -- Takes binary operation marker as op parameter, types of left -- operand n and right operand m. class ArithOp aop (n :: CT) (m :: CT) where { -- | Type family ArithRes denotes the type resulting from -- computing operation op from operands of types n and -- m. -- -- For instance, adding integer to natural produces integer, which is -- reflected in following instance of type family: ArithRes Add CNat -- CInt = CInt. type family ArithRes aop n m :: CT; } -- | Evaluate arithmetic operation on given operands. evalOp :: ArithOp aop n m => proxy aop -> CValue n -> CValue m -> Either (ArithError (CValue n) (CValue m)) (CValue (ArithRes aop n m)) -- | Marker data type for add operation. class UnaryArithOp aop (n :: CT) where { type family UnaryArithRes aop n :: CT; } evalUnaryArithOp :: UnaryArithOp aop n => proxy aop -> CValue n -> CValue (UnaryArithRes aop n) -- | Represents an arithmetic error of the operation. data ArithError n m MutezArithError :: ArithErrorType -> n -> m -> ArithError n m ShiftArithError :: ArithErrorType -> n -> m -> ArithError n m -- | Denotes the error type occured in the arithmetic operation. data ArithErrorType AddOverflow :: ArithErrorType MulOverflow :: ArithErrorType SubUnderflow :: ArithErrorType LslOverflow :: ArithErrorType LsrUnderflow :: ArithErrorType -- | Class for comparison operations, special case of ArithOp. class CompareOp n -- | Evaluate compare operation. compareOp :: CompareOp n => CValue n -> CValue n -> Integer data Add data Sub data Mul data Abs data Neg data Or data And data Xor data Not data Lsl data Lsr data Compare data Eq' data Neq data Lt data Gt data Le data Ge instance (GHC.Classes.Ord n, GHC.Classes.Ord m) => GHC.Classes.Ord (Michelson.Typed.Arith.ArithError n m) instance (GHC.Classes.Eq n, GHC.Classes.Eq m) => GHC.Classes.Eq (Michelson.Typed.Arith.ArithError n m) instance (GHC.Show.Show n, GHC.Show.Show m) => GHC.Show.Show (Michelson.Typed.Arith.ArithError n m) instance GHC.Classes.Ord Michelson.Typed.Arith.ArithErrorType instance GHC.Classes.Eq Michelson.Typed.Arith.ArithErrorType instance GHC.Show.Show Michelson.Typed.Arith.ArithErrorType instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Ge 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Le 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Gt 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Lt 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Neq 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Eq' 'Michelson.Untyped.Type.CInt instance (n Data.Type.Equality.~ m, Michelson.Typed.Arith.CompareOp n) => Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Compare n m instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Lsr 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Lsl 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Not 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Not 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Not 'Michelson.Untyped.Type.CBool instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Xor 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Xor 'Michelson.Untyped.Type.CBool 'Michelson.Untyped.Type.CBool instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.And 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.And 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.And 'Michelson.Untyped.Type.CBool 'Michelson.Untyped.Type.CBool instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Or 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Or 'Michelson.Untyped.Type.CBool 'Michelson.Untyped.Type.CBool instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Neg 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Neg 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.UnaryArithOp Michelson.Typed.Arith.Abs 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Mul 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Mul 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Mul 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Mul 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Mul 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CMutez instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Mul 'Michelson.Untyped.Type.CMutez 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Sub 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Sub 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Sub 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Sub 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Sub 'Michelson.Untyped.Type.CTimestamp 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Sub 'Michelson.Untyped.Type.CTimestamp 'Michelson.Untyped.Type.CTimestamp instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Sub 'Michelson.Untyped.Type.CMutez 'Michelson.Untyped.Type.CMutez instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Add 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Add 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Add 'Michelson.Untyped.Type.CNat 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Add 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Add 'Michelson.Untyped.Type.CTimestamp 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Add 'Michelson.Untyped.Type.CInt 'Michelson.Untyped.Type.CTimestamp instance Michelson.Typed.Arith.ArithOp Michelson.Typed.Arith.Add 'Michelson.Untyped.Type.CMutez 'Michelson.Untyped.Type.CMutez instance (GHC.Show.Show n, GHC.Show.Show m) => Formatting.Buildable.Buildable (Michelson.Typed.Arith.ArithError n m) instance Formatting.Buildable.Buildable Michelson.Typed.Arith.ArithErrorType instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CBool instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CAddress instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CNat instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CInt instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CString instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CBytes instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CTimestamp instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CMutez instance Michelson.Typed.Arith.CompareOp 'Michelson.Untyped.Type.CKeyHash -- | Renderable documentation injected to contract code. module Michelson.Doc -- | A piece of documentation describing one property of a thing, be it a -- name or description of a contract, or an error throwable by given -- endpoint. -- -- Items of the same type appear close to each other in a rendered -- documentation and form a section. -- -- Doc items are later injected into a contract code via a dedicated -- nop-like instruction. Normally doc items which belong to one section -- appear in resulting doc in the same order in which they appeared in -- the contract. -- -- While documentation framework grows, this typeclass acquires more and -- more methods for fine tuning of existing rendering logic because we -- don't want to break backward compatibility, hope one day we will make -- everything concise :( E.g. all rendering and reording stuff could be -- merged in one method, and we could have several template -- implementations for it which would allow user to specify only stuff -- relevant to his case. class (Typeable d, DOrd d, KnownNat (DocItemPosition d)) => DocItem d where { -- | Position of this item in the resulting documentation; the smaller the -- value, the higher the section with this element will be placed. -- -- Documentation structure is not necessarily flat. If some doc item -- consolidates a whole documentation block within it, this block will -- have its own placement of items independent from outer parts of the -- doc. type family DocItemPosition d = (pos :: Nat) | pos -> d; -- | Defines where given doc item should be put. There are two options: 1. -- Inline right here (default behaviour); 2. Put into definitions -- section. -- -- Note that we require all doc items with "in definitions" placement to -- have Eq and Ord instances which comply the following -- law: if two documentation items describe the same entity or property, -- they should be considered equal. type family DocItemPlacement d :: DocItemPlacementKind; type DocItemPlacement d = 'DocItemInlined; } -- | When multiple items of the same type belong to one section, how this -- section will be called. -- -- If not provided, section will contain just untitled content. docItemSectionName :: DocItem d => Maybe Text -- | Description of a section. -- -- Can be used to mention some common things about all elements of this -- section. Markdown syntax is permitted here. docItemSectionDescription :: DocItem d => Maybe Markdown -- | How to render section name. -- -- Takes effect only if section name is set. docItemSectionNameStyle :: DocItem d => DocSectionNameStyle -- | Defines a function which constructs an unique identifier of given doc -- item, if it has been decided to put the doc item into definitions -- section. -- -- Identifier should be unique both among doc items of the same type and -- items of other types. Thus, consider using "typeId-contentId" pattern. docItemRef :: DocItem d => d -> DocItemRef (DocItemPlacement d) -- | Defines a function which constructs an unique identifier of given doc -- item, if it has been decided to put the doc item into definitions -- section. -- -- Identifier should be unique both among doc items of the same type and -- items of other types. Thus, consider using "typeId-contentId" pattern. docItemRef :: (DocItem d, DocItemPlacement d ~ 'DocItemInlined) => d -> DocItemRef (DocItemPlacement d) -- | Render given doc item to Markdown, preferably one line, optionally -- with header. -- -- Accepts the smallest allowed level of header. (Using smaller value -- than provided one will interfere with existing headers thus delivering -- mess). docItemToMarkdown :: DocItem d => HeaderLevel -> d -> Markdown -- | All doc items which this doc item refers to. -- -- They will automatically be put to definitions as soon as given doc -- item is detected. docItemDependencies :: DocItem d => d -> [SomeDocDefinitionItem] -- | This function accepts doc items put under the same section in the -- order in which they appeared in the contract and returns their new -- desired order. It's also fine to use this function for filtering or -- merging doc items. -- -- Default implementation * leaves inlined items as is; * for items put -- to definitions, lexicographically sorts them by their id. docItemsOrder :: DocItem d => [d] -> [d] -- | Get doc item position at term-level. docItemPosition :: forall d. DocItem d => DocItemPos -- | Some unique identifier of a doc item. -- -- All doc items which should be refer-able need to have this identifier. newtype DocItemId DocItemId :: Text -> DocItemId -- | Where do we place given doc item. data DocItemPlacementKind -- | Placed in the document content itself. DocItemInlined :: DocItemPlacementKind -- | Placed in dedicated definitions section; can later be referenced. DocItemInDefinitions :: DocItemPlacementKind -- | Defines an identifier which given doc item can be referenced with. data DocItemRef (p :: DocItemPlacementKind) [DocItemRef] :: DocItemId -> DocItemRef 'DocItemInDefinitions [DocItemNoRef] :: DocItemRef 'DocItemInlined -- | How to render section name. data DocSectionNameStyle -- | Suitable for block name. DocSectionNameBig :: DocSectionNameStyle -- | Suitable for subsection title within block. DocSectionNameSmall :: DocSectionNameStyle -- | Hides some documentation item. data SomeDocItem [SomeDocItem] :: DocItem d => d -> SomeDocItem -- | Hides some documentation item which is put to "definitions" section. data SomeDocDefinitionItem [SomeDocDefinitionItem] :: (DocItem d, DocItemPlacement d ~ 'DocItemInDefinitions) => d -> SomeDocDefinitionItem -- | A map from positions to document elements. -- -- Note that each value in this map keeps a list of doc items, all of -- which have the same type (since each doc item type is forced to have -- unique position). type DocBlock = Map DocItemPos (NonEmpty SomeDocItem) -- | A part of documentation to be grouped. Essentially incapsulates -- DocBlock. newtype SubDoc SubDoc :: DocBlock -> SubDoc -- | Keeps documentation gathered for some piece of contract code. -- -- Used for building documentation of a contract. data ContractDoc ContractDoc :: DocBlock -> DocBlock -> Set SomeDocDefinitionItem -> Set DocItemId -> ContractDoc -- | All inlined doc items. [cdContents] :: ContractDoc -> DocBlock -- | Definitions used in document. -- -- Usually you put some large and repetitive descriptions here. This -- differs from the document content in that it contains sections which -- are always at top-level, disregard the nesting. -- -- All doc items which define docItemId method go here, and only -- they. [cdDefinitions] :: ContractDoc -> DocBlock -- | We remember all already declared entries to avoid cyclic dependencies -- in documentation items discovery. [cdDefinitionsSet] :: ContractDoc -> Set SomeDocDefinitionItem -- | We remember all already used identifiers. (Documentation naturally -- should not declare multiple items with the same identifier because -- that would make references to the respective anchors ambiguous). [cdDefinitionIds] :: ContractDoc -> Set DocItemId -- | A function which groups a piece of doc under one doc item. type DocGrouping = SubDoc -> SomeDocItem cdContentsL :: Lens' ContractDoc DocBlock cdDefinitionsL :: Lens' ContractDoc DocBlock cdDefinitionsSetL :: Lens' ContractDoc (Set SomeDocDefinitionItem) cdDefinitionIdsL :: Lens' ContractDoc (Set DocItemId) -- | Render documentation for SubDoc. subDocToMarkdown :: HeaderLevel -> SubDoc -> Markdown someDocItemToBlock :: SomeDocItem -> DocBlock -- | Render given contract documentation to markdown document. contractDocToMarkdown :: ContractDoc -> LText -- | Apply given grouping to documentation being built. docGroupContent :: DocGrouping -> ContractDoc -> ContractDoc -- | Make a reference to doc item in definitions. docDefinitionRef :: (DocItem d, DocItemPlacement d ~ 'DocItemInDefinitions) => Markdown -> d -> Markdown -- | Give a name to document block. data DName DName :: Text -> SubDoc -> DName -- | Description of something. data DDescription DDescription :: Markdown -> DDescription -- | Specify version if given contract. data DVersion DVersion :: Natural -> DVersion -- | Specify version if given contract. data DGitRevision DGitRevision :: GitRepoSettings -> Text -> Text -> DGitRevision [dgrRepoSettings] :: DGitRevision -> GitRepoSettings [dgrCommitSha] :: DGitRevision -> Text [dgrCommitDate] :: DGitRevision -> Text -- | Repository settings for DGitRevision. newtype GitRepoSettings GitRepoSettings :: (Text -> Text) -> GitRepoSettings -- | By commit sha make up a url to that commit in remote repository. [grsMkGitRevision] :: GitRepoSettings -> Text -> Text -- | Make DGitRevision. -- --
--   >>> :t $mkDGitRevision
--   GitRepoSettings -> DGitRevision
--   
mkDGitRevision :: Q Exp morleyRepoSettings :: GitRepoSettings data DComment DComment :: Text -> DComment instance Michelson.Doc.DocItem Michelson.Doc.DComment instance Michelson.Doc.DocItem Michelson.Doc.DGitRevision instance Michelson.Doc.DocItem Michelson.Doc.DVersion instance Michelson.Doc.DocItem Michelson.Doc.DDescription instance Michelson.Doc.DocItem Michelson.Doc.DName instance GHC.Show.Show Michelson.Doc.DocGrouping instance GHC.Base.Semigroup Michelson.Doc.ContractDoc instance GHC.Base.Monoid Michelson.Doc.ContractDoc instance Formatting.Buildable.Buildable Michelson.Doc.DocItemPos instance GHC.Show.Show Michelson.Doc.DocItemPos instance GHC.Classes.Ord Michelson.Doc.DocItemPos instance GHC.Classes.Eq Michelson.Doc.DocItemPos instance GHC.Show.Show Michelson.Doc.DocItemId instance GHC.Classes.Ord Michelson.Doc.DocItemId instance GHC.Classes.Eq Michelson.Doc.DocItemId instance GHC.Show.Show Michelson.Doc.SomeDocItem instance GHC.Classes.Eq Michelson.Doc.SomeDocDefinitionItem instance GHC.Classes.Ord Michelson.Doc.SomeDocDefinitionItem -- | Module, containing data types for Michelson value. module Michelson.Typed.Instr -- | Representation of Michelson instruction or sequence of instructions. -- -- Each Michelson instruction is represented by exactly one constructor -- of this data type. Sequence of instructions is represented with use of -- Seq constructor in following way: SWAP; DROP ; DUP; -- -> SWAP Instr DROP Instr DUP. Special case -- where there are no instructions is represented by constructor -- Nop, e.g. IF_NONE {} { SWAP; DROP; } -> -- IF_NONE Nop (SWAP Instr DROP). -- -- Type parameter inp states for input stack type. That is, type -- of the stack that is required for operation to execute. -- -- Type parameter out states for output stack type or type of -- stack that will be left after instruction's execution. data Instr (inp :: [T]) (out :: [T]) -- | A wrapper for instruction that also contain annotations for the top -- type on the result stack. -- -- As of now, when converting from untyped representation, we only -- preserve field annotations and type annotations. Variable annotations -- are not preserved. -- -- This can wrap only instructions with at least one non-failing -- execution branch. [InstrWithNotes] :: PackedNotes b -> Instr a b -> Instr a b -- | Execute given instruction on truncated stack. -- -- This can wrap only instructions with at least one non-failing -- execution branch. -- -- Morley has no such instruction, it is used solely in eDSLs. This -- instruction is sound because for all Michelson instructions the -- following property holds: if some code accepts stack i and -- produces stack o, when it can also be run on stack i + -- s producing stack o + s; and also because Michelson -- never makes implicit assumptions on types, rather you have to express -- all "yet ambiguous" type information in code. We could make this not -- an instruction but rather a function which modifies an instruction -- (this would also automatically prove soundness of used -- transformation), but it occured to be tricky (in particular for -- TestAssert and DipN and family), so let's leave this for future work. [FrameInstr] :: forall a b s. (KnownList a, KnownList b) => Proxy s -> Instr a b -> Instr (a ++ s) (b ++ s) [Seq] :: Instr a b -> Instr b c -> Instr a c -- | Nop operation. Missing in Michelson spec, added to parse construction -- like `IF {} { SWAP; DROP; }`. [Nop] :: Instr s s [Ext] :: ExtInstr s -> Instr s s -- | Nested wrapper is going to wrap a sequence of instructions with { }. -- It is crucial because serialisation of a contract depends on precise -- structure of its code. [Nested] :: Instr inp out -> Instr inp out -- | Places documentation generated for given instruction under some group. -- This is not part of ExtInstr because it does not behave like -- Nop; instead, it inherits behaviour of instruction put within -- it. [DocGroup] :: DocGrouping -> Instr inp out -> Instr inp out -- | Variants of CAR/CDR to retain field annotations as they relate to the -- input stack, and hence won't be available from the annotation notes -- from the result stack we pack with the instructions during type check. [AnnCAR] :: FieldAnn -> Instr ( 'TPair a b : s) (a : s) [AnnCDR] :: FieldAnn -> Instr ( 'TPair a b : s) (b : s) [DROP] :: Instr (a : s) s [DROPN] :: forall (n :: Peano) s. (SingI n, KnownPeano n, RequireLongerOrSameLength s n) => Sing n -> Instr s (Drop n s) [DUP] :: Instr (a : s) (a : (a : s)) [SWAP] :: Instr (a : (b : s)) (b : (a : s)) [DIG] :: forall (n :: Peano) inp out a. ConstraintDIG n inp out a => Sing n -> Instr inp out [DUG] :: forall (n :: Peano) inp out a. ConstraintDUG n inp out a => Sing n -> Instr inp out [PUSH] :: forall t s. ConstantScope t => Value' Instr t -> Instr s (t : s) [SOME] :: Instr (a : s) ( 'TOption a : s) [NONE] :: forall a s. SingI a => Instr s ( 'TOption a : s) [UNIT] :: Instr s ( 'TUnit : s) [IF_NONE] :: Instr s s' -> Instr (a : s) s' -> Instr ( 'TOption a : s) s' [PAIR] :: Instr (a : (b : s)) ( 'TPair a b : s) [LEFT] :: forall b a s. SingI b => Instr (a : s) ( 'TOr a b : s) [RIGHT] :: forall a b s. SingI a => Instr (b : s) ( 'TOr a b : s) [IF_LEFT] :: Instr (a : s) s' -> Instr (b : s) s' -> Instr ( 'TOr a b : s) s' [NIL] :: SingI p => Instr s ( 'TList p : s) [CONS] :: Instr (a : ( 'TList a : s)) ( 'TList a : s) [IF_CONS] :: Instr (a : ( 'TList a : s)) s' -> Instr s s' -> Instr ( 'TList a : s) s' [SIZE] :: SizeOp c => Instr (c : s) ( 'Tc 'CNat : s) [EMPTY_SET] :: (Typeable e, SingI e) => Instr s ( 'TSet e : s) [EMPTY_MAP] :: (Typeable a, Typeable b, SingI a, SingI b) => Instr s ( 'TMap a b : s) [EMPTY_BIG_MAP] :: (Typeable a, Typeable b, SingI a, SingI b) => Instr s ( 'TBigMap a b : s) [MAP] :: MapOp c => Instr (MapOpInp c : s) (b : s) -> Instr (c : s) (MapOpRes c b : s) [ITER] :: IterOp c => Instr (IterOpEl c : s) s -> Instr (c : s) s [MEM] :: MemOp c => Instr ( 'Tc (MemOpKey c) : (c : s)) ( 'Tc 'CBool : s) [GET] :: GetOp c => Instr ( 'Tc (GetOpKey c) : (c : s)) ( 'TOption (GetOpVal c) : s) [UPDATE] :: UpdOp c => Instr ( 'Tc (UpdOpKey c) : (UpdOpParams c : (c : s))) (c : s) [IF] :: Instr s s' -> Instr s s' -> Instr ( 'Tc 'CBool : s) s' [LOOP] :: Instr s ( 'Tc 'CBool : s) -> Instr ( 'Tc 'CBool : s) s [LOOP_LEFT] :: Instr (a : s) ( 'TOr a b : s) -> Instr ( 'TOr a b : s) (b : s) [LAMBDA] :: forall i o s. Each [Typeable, SingI] [i, o] => Value' Instr ( 'TLambda i o) -> Instr s ( 'TLambda i o : s) [EXEC] :: Instr (t1 : ( 'TLambda t1 t2 : s)) (t2 : s) [APPLY] :: forall a b c s. ConstantScope a => Instr (a : ( 'TLambda ( 'TPair a b) c : s)) ( 'TLambda b c : s) [DIP] :: Instr a c -> Instr (b : a) (b : c) [DIPN] :: forall (n :: Peano) inp out s s'. ConstraintDIPN n inp out s s' => Sing n -> Instr s s' -> Instr inp out [FAILWITH] :: (Typeable a, SingI a) => Instr (a : s) t [CAST] :: forall a s. SingI a => Instr (a : s) (a : s) [RENAME] :: Instr (a : s) (a : s) [PACK] :: PackedValScope a => Instr (a : s) ( 'Tc 'CBytes : s) [UNPACK] :: UnpackedValScope a => Instr ( 'Tc 'CBytes : s) ( 'TOption a : s) [CONCAT] :: ConcatOp c => Instr (c : (c : s)) (c : s) [CONCAT'] :: ConcatOp c => Instr ( 'TList c : s) (c : s) [SLICE] :: SliceOp c => Instr ( 'Tc 'CNat : ( 'Tc 'CNat : (c : s))) ( 'TOption c : s) [ISNAT] :: Instr ( 'Tc 'CInt : s) ( 'TOption ( 'Tc 'CNat) : s) [ADD] :: (ArithOp Add n m, Typeable n, Typeable m) => Instr ( 'Tc n : ( 'Tc m : s)) ( 'Tc (ArithRes Add n m) : s) [SUB] :: (ArithOp Sub n m, Typeable n, Typeable m) => Instr ( 'Tc n : ( 'Tc m : s)) ( 'Tc (ArithRes Sub n m) : s) [MUL] :: (ArithOp Mul n m, Typeable n, Typeable m) => Instr ( 'Tc n : ( 'Tc m : s)) ( 'Tc (ArithRes Mul n m) : s) [EDIV] :: EDivOp n m => Instr ( 'Tc n : ( 'Tc m : s)) ( 'TOption ( 'TPair ( 'Tc (EDivOpRes n m)) ( 'Tc (EModOpRes n m))) : s) [ABS] :: UnaryArithOp Abs n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Abs n) : s) [NEG] :: UnaryArithOp Neg n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Neg n) : s) [LSL] :: (ArithOp Lsl n m, Typeable n, Typeable m) => Instr ( 'Tc n : ( 'Tc m : s)) ( 'Tc (ArithRes Lsl n m) : s) [LSR] :: (ArithOp Lsr n m, Typeable n, Typeable m) => Instr ( 'Tc n : ( 'Tc m : s)) ( 'Tc (ArithRes Lsr n m) : s) [OR] :: (ArithOp Or n m, Typeable n, Typeable m) => Instr ( 'Tc n : ( 'Tc m : s)) ( 'Tc (ArithRes Or n m) : s) [AND] :: (ArithOp And n m, Typeable n, Typeable m) => Instr ( 'Tc n : ( 'Tc m : s)) ( 'Tc (ArithRes And n m) : s) [XOR] :: (ArithOp Xor n m, Typeable n, Typeable m) => Instr ( 'Tc n : ( 'Tc m : s)) ( 'Tc (ArithRes Xor n m) : s) [NOT] :: UnaryArithOp Not n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Not n) : s) [COMPARE] :: (ArithOp Compare n n, Typeable n) => Instr ( 'Tc n : ( 'Tc n : s)) ( 'Tc (ArithRes Compare n n) : s) [EQ] :: UnaryArithOp Eq' n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Eq' n) : s) [NEQ] :: UnaryArithOp Neq n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Neq n) : s) [LT] :: UnaryArithOp Lt n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Lt n) : s) [GT] :: UnaryArithOp Gt n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Gt n) : s) [LE] :: UnaryArithOp Le n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Le n) : s) [GE] :: UnaryArithOp Ge n => Instr ( 'Tc n : s) ( 'Tc (UnaryArithRes Ge n) : s) [INT] :: Instr ( 'Tc 'CNat : s) ( 'Tc 'CInt : s) [SELF] :: forall (p :: T) s. ParameterScope p => Instr s ( 'TContract p : s) [CONTRACT] :: ParameterScope p => Notes p -> EpName -> Instr ( 'Tc 'CAddress : s) ( 'TOption ( 'TContract p) : s) [TRANSFER_TOKENS] :: ParameterScope p => Instr (p : ( 'Tc 'CMutez : ( 'TContract p : s))) ( 'TOperation : s) [SET_DELEGATE] :: Instr ( 'TOption ( 'Tc 'CKeyHash) : s) ( 'TOperation : s) [CREATE_CONTRACT] :: (ParameterScope p, StorageScope g) => FullContract p g -> Instr ( 'TOption ( 'Tc 'CKeyHash) : ( 'Tc 'CMutez : (g : s))) ( 'TOperation : ( 'Tc 'CAddress : s)) [IMPLICIT_ACCOUNT] :: Instr ( 'Tc 'CKeyHash : s) ( 'TContract 'TUnit : s) [NOW] :: Instr s ( 'Tc 'CTimestamp : s) [AMOUNT] :: Instr s ( 'Tc 'CMutez : s) [BALANCE] :: Instr s ( 'Tc 'CMutez : s) [CHECK_SIGNATURE] :: Instr ( 'TKey : ( 'TSignature : ( 'Tc 'CBytes : s))) ( 'Tc 'CBool : s) [SHA256] :: Instr ( 'Tc 'CBytes : s) ( 'Tc 'CBytes : s) [SHA512] :: Instr ( 'Tc 'CBytes : s) ( 'Tc 'CBytes : s) [BLAKE2B] :: Instr ( 'Tc 'CBytes : s) ( 'Tc 'CBytes : s) [HASH_KEY] :: Instr ( 'TKey : s) ( 'Tc 'CKeyHash : s) [STEPS_TO_QUOTA] :: Instr s ( 'Tc 'CNat : s) [SOURCE] :: Instr s ( 'Tc 'CAddress : s) [SENDER] :: Instr s ( 'Tc 'CAddress : s) [ADDRESS] :: Instr ( 'TContract a : s) ( 'Tc 'CAddress : s) [CHAIN_ID] :: Instr s ( 'TChainId : s) data ExtInstr s TEST_ASSERT :: TestAssert s -> ExtInstr s PRINT :: PrintComment s -> ExtInstr s DOC_ITEM :: SomeDocItem -> ExtInstr s -- | A reference into the stack of a given type. data StackRef (st :: [T]) -- | Keeps 0-based index to a stack element counting from the top. [StackRef] :: (KnownPeano idx, SingI idx, RequireLongerThan st idx) => Sing (idx :: Peano) -> StackRef st -- | Create a stack reference, performing checks at compile time. mkStackRef :: forall (gn :: Nat) st n. (n ~ ToPeano gn, SingI n, KnownPeano n, RequireLongerThan st n) => StackRef st -- | A print format with references into the stack newtype PrintComment (st :: [T]) PrintComment :: [Either Text (StackRef st)] -> PrintComment [unPrintComment] :: PrintComment -> [Either Text (StackRef st)] data TestAssert (s :: [T]) [TestAssert] :: Typeable out => Text -> PrintComment inp -> Instr inp ( 'Tc 'CBool : out) -> TestAssert inp type Contract cp st = Instr (ContractInp cp st) (ContractOut st) -- | Typed contract and information about annotations which is not present -- in the contract code. TODO [#12]: rename this to Contract and -- the current Contract to ContractCode? data FullContract cp st FullContract :: Contract cp st -> ParamNotes cp -> Notes st -> FullContract cp st [fcCode] :: FullContract cp st -> Contract cp st [fcParamNotesSafe] :: FullContract cp st -> ParamNotes cp [fcStoreNotes] :: FullContract cp st -> Notes st fcParamNotes :: FullContract cp st -> Notes cp mapFullContractCode :: (Contract cp st -> Contract cp st) -> FullContract cp st -> FullContract cp st pattern CAR :: Instr ( 'TPair a b : s) (a : s) pattern CDR :: Instr ( 'TPair a b : s) (b : s) -- | A wrapper to wrap annotations and corresponding singleton. Apart from -- packing notes along with the corresponding Singleton, this wrapper -- type, when included with Instr also helps to derive the -- Show instance for Instr as `Sing a` does not have a -- Show instance on its own. data PackedNotes a [PackedNotes] :: Notes a -> Sing a -> PackedNotes (a : s) type ConstraintDIPN n inp out s s' = ConstraintDIPN' T n inp out s s' -- | Constraint that is used in DIPN, we want to share it with typechecking -- code and eDSL code. type ConstraintDIPN' kind (n :: Peano) (inp :: [kind]) (out :: [kind]) (s :: [kind]) (s' :: [kind]) = (SingI n, KnownPeano n, RequireLongerOrSameLength inp n, ((Take n inp) ++ s) ~ inp, ((Take n inp) ++ s') ~ out) type ConstraintDIG n inp out a = ConstraintDIG' T n inp out a type ConstraintDIG' kind (n :: Peano) (inp :: [kind]) (out :: [kind]) (a :: kind) = (SingI n, KnownPeano n, RequireLongerThan inp n, inp ~ (Take n inp ++ (a : Drop ( 'S n) inp)), out ~ (a : Take n inp ++ Drop ( 'S n) inp)) type ConstraintDUG n inp out a = ConstraintDUG' T n inp out a type ConstraintDUG' kind (n :: Peano) (inp :: [kind]) (out :: [kind]) (a :: kind) = (SingI n, KnownPeano n, RequireLongerThan out n, inp ~ (a : Drop ( 'S 'Z) inp), out ~ (Take n (Drop ( 'S 'Z) inp) ++ (a : Drop ( 'S n) inp))) instance GHC.Show.Show (Michelson.Typed.Instr.ExtInstr s) instance GHC.Base.Monoid (Michelson.Typed.Instr.PrintComment st) instance GHC.Base.Semigroup (Michelson.Typed.Instr.PrintComment st) instance GHC.Generics.Generic (Michelson.Typed.Instr.PrintComment st) instance GHC.Show.Show (Michelson.Typed.Instr.PrintComment st) instance GHC.Classes.Eq (Michelson.Typed.Instr.PrintComment st) instance GHC.Show.Show (Michelson.Typed.Instr.Instr inp out) instance GHC.Show.Show (Michelson.Typed.Instr.TestAssert s) instance GHC.Show.Show (Michelson.Typed.Instr.FullContract cp st) instance GHC.Base.Semigroup (Michelson.Typed.Instr.Instr s s) instance GHC.Base.Monoid (Michelson.Typed.Instr.Instr s s) instance Control.DeepSeq.NFData (Michelson.Typed.Instr.Instr inp out) instance Data.String.IsString (Michelson.Typed.Instr.PrintComment st) instance GHC.Classes.Eq (Michelson.Typed.Instr.StackRef st) instance GHC.Show.Show (Michelson.Typed.Instr.StackRef st) instance GHC.Show.Show (Michelson.Typed.Instr.PackedNotes a) module Michelson.Typed.Convert convertContract :: forall param store. (SingI param, SingI store) => Contract param store -> Contract convertFullContract :: forall param store. (SingI param, SingI store) => FullContract param store -> Contract instrToOps :: HasCallStack => Instr inp out -> [ExpandedOp] -- | Convert a typed Val to an untyped Value. -- -- For full isomorphism type of the given Val should not contain -- TOperation - a compile error will be raised otherwise. You can -- analyse its presence with checkOpPresence function. untypeValue :: forall t. (SingI t, HasNoOp t) => Value' Instr t -> Value instance GHC.Classes.Eq (Michelson.Typed.Instr.Instr inp out) instance Data.Typeable.Internal.Typeable s => GHC.Classes.Eq (Michelson.Typed.Instr.TestAssert s) module Michelson.Typed.Aliases type Value = Value' Instr type SomeValue = SomeValue' Instr type SomeConstrainedValue = SomeConstrainedValue' Instr type Operation = Operation' Instr -- | General-purpose utility functions for typed types. module Michelson.Typed.Util -- | Options for dfsInstr. data DfsSettings x DfsSettings :: Bool -> CtorEffectsApp x -> DfsSettings x -- | Whether dfsInstr function should go into values which contain -- other instructions: lambdas and constant contracts (which can be -- passed to CREATE_CONTRACT). [dsGoToValues] :: DfsSettings x -> Bool -- | How do we handle intermediate nodes in instruction tree. [dsCtorEffectsApp] :: DfsSettings x -> CtorEffectsApp x -- | Describes how intermediate nodes in instruction tree are accounted. data CtorEffectsApp x CtorEffectsApp :: Text -> (forall i o. Semigroup x => x -> x -> Instr i o -> (Instr i o, x)) -> CtorEffectsApp x -- | Name of this way. [ceaName] :: CtorEffectsApp x -> Text -- | This function accepts: 1. Effects gathered after applying -- step to node's children, but before applying it to the node -- itself. 2. Effects gathered after applying step to the given -- intermediate node. 3. Instruction resulting after all modifications -- produced by step. [ceaApplyEffects] :: CtorEffectsApp x -> forall i o. Semigroup x => x -> x -> Instr i o -> (Instr i o, x) -- | Traverse a typed instruction in depth-first order. <> is -- used to concatenate intermediate results. Each instructions can be -- changed using the supplied step function. It does not -- consider extra instructions (not present in Michelson). dfsInstr :: forall x inp out. Semigroup x => DfsSettings x -> (forall i o. Instr i o -> (Instr i o, x)) -> Instr inp out -> (Instr inp out, x) -- | Specialization of dfsInstr for case when changing the -- instruction is not required. dfsFoldInstr :: forall x inp out. Semigroup x => DfsSettings x -> (forall i o. Instr i o -> x) -> Instr inp out -> x -- | Specialization of dfsInstr which only modifies given -- instruction. dfsModifyInstr :: DfsSettings () -> (forall i o. Instr i o -> Instr i o) -> Instr inp out -> Instr inp out -- | There are many ways to represent a sequence of more than 2 -- instructions. E. g. for `i1; i2; i3` it can be Seq i1 $ Seq i2 -- i3 or Seq (Seq i1 i2) i3. This function enforces a -- particular structure. Specifically, it makes each Instr have a -- single instruction (i. e. not Instr) in its second argument. -- This function also erases redundant Nops. linearizeLeft :: Instr inp out -> Instr inp out -- | If value is a string, return the stored string. isStringValue :: Value t -> Maybe MText -- | If value is a bytestring, return the stored bytestring. isBytesValue :: Value t -> Maybe ByteString -- | Takes a selector which checks whether an atomic value (i. e. that can -- not contain another value) can be converted to something. Recursively -- applies it to all atomic values in potentially non-atomic value. -- Collects extracted values in a list. -- -- Perhaps one day we'll have dfsValue. allAtomicValues :: forall t a. (forall t'. Value t' -> Maybe a) -> Value t -> [a] instance GHC.Show.Show (Michelson.Typed.Util.DfsSettings x) instance Data.Default.Class.Default (Michelson.Typed.Util.DfsSettings x) instance GHC.Show.Show (Michelson.Typed.Util.CtorEffectsApp x) -- | Conversions between haskell types/values and Michelson ones. module Michelson.Typed.Haskell.Value -- | Isomorphism between Michelson primitive values and plain Haskell -- types. class IsoCValue a where { -- | Type function that converts a regular Haskell type into a comparable -- type (which has kind CT). type family ToCT a :: CT; } -- | Converts a single Haskell value into CVal representation. toCVal :: IsoCValue a => a -> CValue (ToCT a) -- | Converts a CVal value into a single Haskell value. fromCVal :: IsoCValue a => CValue (ToCT a) -> a -- | Isomorphism between Michelson values and plain Haskell types. -- -- Default implementation of this typeclass converts ADTs to Michelson -- "pair"s and "or"s. class IsoValue a where { -- | Type function that converts a regular Haskell type into a T -- type. type family ToT a :: T; type ToT a = GValueType (Rep a); } -- | Converts a Haskell structure into Value representation. toVal :: IsoValue a => a -> Value (ToT a) -- | Converts a Haskell structure into Value representation. toVal :: (IsoValue a, Generic a, GIsoValue (Rep a), ToT a ~ GValueType (Rep a)) => a -> Value (ToT a) -- | Converts a Value into Haskell type. fromVal :: IsoValue a => Value (ToT a) -> a -- | Converts a Value into Haskell type. fromVal :: (IsoValue a, Generic a, GIsoValue (Rep a), ToT a ~ GValueType (Rep a)) => Value (ToT a) -> a -- | Implements ADT conversion to Michelson value. -- -- Thanks to Generic, Michelson representation will be a balanced tree; -- this reduces average access time in general case. -- -- A drawback of such approach is that, in theory, in new GHC version -- generified representation may change; however, chances are small and I -- (martoon) believe that contract versions will change much faster -- anyway. class GIsoValue (x :: Type -> Type) where { type family GValueType x :: T; } -- | Overloaded version of ToT to work on Haskell and T -- types. type family ToT' (t :: k) :: T -- | Hides some Haskell value put in line with Michelson Value. data SomeIsoValue [SomeIsoValue] :: (Typeable a, IsoValue a) => a -> SomeIsoValue -- | Any Haskell value which can be converted to Michelson Value. newtype AnyIsoValue AnyIsoValue :: (forall a. IsoValue a => a) -> AnyIsoValue -- | A useful property which holds for all CT types. type IsComparable c = ToT c ~ 'Tc (ToCT c) -- | Whether Michelson representation of the type is derived via Generics. type IsGenericIsoValue t = (IsoValue t, Generic t, ToT t ~ GValueType (Rep t)) type EntryPointCall param arg = EntryPointCallT (ToT param) (ToT arg) type SomeEntryPointCall arg = SomeEntryPointCallT (ToT arg) -- | Since Contract name is used to designate contract code, lets -- call analogy of TContract type as follows. data ContractRef (arg :: Type) ContractRef :: Address -> SomeEntryPointCall arg -> ContractRef [crAddress] :: ContractRef -> Address [crEntryPoint] :: ContractRef -> SomeEntryPointCall arg -- | Replace type argument of ContractAddr with isomorphic one. coerceContractRef :: ToT a ~ ToT b => ContractRef a -> ContractRef b newtype BigMap k v BigMap :: Map k v -> BigMap k v [unBigMap] :: BigMap k v -> Map k v -- | Type function to convert a Haskell stack type to T-based one. type family ToTs (ts :: [Type]) :: [T] -- | Overloaded version of ToTs to work on Haskell and T -- stacks. type family ToTs' (t :: [k]) :: [T] -- | Isomorphism between Michelson stack and its Haskell reflection. class IsoValuesStack (ts :: [Type]) toValStack :: IsoValuesStack ts => Rec Identity ts -> Rec Value (ToTs ts) fromValStack :: IsoValuesStack ts => Rec Value (ToTs ts) -> Rec Identity ts totsKnownLemma :: forall s. KnownList s :- KnownList (ToTs s) totsAppendLemma :: forall a b. KnownList a => Dict (ToTs (a ++ b) ~ (ToTs a ++ ToTs b)) instance GHC.Show.Show (Michelson.Typed.Haskell.Value.ContractRef arg) instance GHC.Classes.Eq (Michelson.Typed.Haskell.Value.ContractRef arg) instance GHC.Classes.Ord k => GHC.Base.Monoid (Michelson.Typed.Haskell.Value.BigMap k v) instance GHC.Classes.Ord k => GHC.Base.Semigroup (Michelson.Typed.Haskell.Value.BigMap k v) instance Data.Default.Class.Default (Michelson.Typed.Haskell.Value.BigMap k v) instance (GHC.Show.Show k, GHC.Show.Show v) => GHC.Show.Show (Michelson.Typed.Haskell.Value.BigMap k v) instance (GHC.Classes.Eq k, GHC.Classes.Eq v) => GHC.Classes.Eq (Michelson.Typed.Haskell.Value.BigMap k v) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.IsoValue (Data.Functor.Identity.Identity a) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.IsoValue (Named.Internal.NamedF Data.Functor.Identity.Identity a name) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.IsoValue (Named.Internal.NamedF GHC.Maybe.Maybe a name) instance Michelson.Typed.Haskell.Value.IsoValuesStack '[] instance (Michelson.Typed.Haskell.Value.IsoValue t, Michelson.Typed.Haskell.Value.IsoValuesStack st) => Michelson.Typed.Haskell.Value.IsoValuesStack (t : st) instance Formatting.Buildable.Buildable (Michelson.Typed.Haskell.Value.ContractRef arg) instance Michelson.Typed.Haskell.Value.IsoValue (Michelson.Typed.Haskell.Value.ContractRef arg) instance Michelson.Typed.Haskell.Value.IsoValue GHC.Integer.Type.Integer instance Michelson.Typed.Haskell.Value.IsoValue GHC.Natural.Natural instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Text.MText instance Michelson.Text.DoNotUseTextError => Michelson.Typed.Haskell.Value.IsoValue Data.Text.Internal.Text instance Michelson.Typed.Haskell.Value.IsoValue GHC.Types.Bool instance Michelson.Typed.Haskell.Value.IsoValue Data.ByteString.Internal.ByteString instance Michelson.Typed.Haskell.Value.IsoValue Tezos.Core.Mutez instance Michelson.Typed.Haskell.Value.IsoValue Tezos.Crypto.KeyHash instance Michelson.Typed.Haskell.Value.IsoValue Tezos.Core.Timestamp instance Michelson.Typed.Haskell.Value.IsoValue Tezos.Address.Address instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Typed.EntryPoints.EpAddress instance Michelson.Typed.Haskell.Value.IsoValue Tezos.Crypto.PublicKey instance Michelson.Typed.Haskell.Value.IsoValue Tezos.Crypto.Signature instance Michelson.Typed.Haskell.Value.IsoValue Tezos.Core.ChainId instance Michelson.Typed.Haskell.Value.IsoValue () instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.IsoValue [a] instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.IsoValue (GHC.Maybe.Maybe a) instance (Michelson.Typed.Haskell.Value.IsoValue l, Michelson.Typed.Haskell.Value.IsoValue r) => Michelson.Typed.Haskell.Value.IsoValue (Data.Either.Either l r) instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Haskell.Value.IsoValue b) => Michelson.Typed.Haskell.Value.IsoValue (a, b) instance (GHC.Classes.Ord c, Michelson.Typed.Haskell.Value.IsoCValue c) => Michelson.Typed.Haskell.Value.IsoValue (Data.Set.Internal.Set c) instance (GHC.Classes.Ord k, Michelson.Typed.Haskell.Value.IsoCValue k, Michelson.Typed.Haskell.Value.IsoValue v) => Michelson.Typed.Haskell.Value.IsoValue (Data.Map.Internal.Map k v) instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Typed.Aliases.Operation instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Haskell.Value.IsoValue b, Michelson.Typed.Haskell.Value.IsoValue c) => Michelson.Typed.Haskell.Value.IsoValue (a, b, c) instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Haskell.Value.IsoValue b, Michelson.Typed.Haskell.Value.IsoValue c, Michelson.Typed.Haskell.Value.IsoValue d) => Michelson.Typed.Haskell.Value.IsoValue (a, b, c, d) instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Haskell.Value.IsoValue b, Michelson.Typed.Haskell.Value.IsoValue c, Michelson.Typed.Haskell.Value.IsoValue d, Michelson.Typed.Haskell.Value.IsoValue e) => Michelson.Typed.Haskell.Value.IsoValue (a, b, c, d, e) instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Haskell.Value.IsoValue b, Michelson.Typed.Haskell.Value.IsoValue c, Michelson.Typed.Haskell.Value.IsoValue d, Michelson.Typed.Haskell.Value.IsoValue e, Michelson.Typed.Haskell.Value.IsoValue f) => Michelson.Typed.Haskell.Value.IsoValue (a, b, c, d, e, f) instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Haskell.Value.IsoValue b, Michelson.Typed.Haskell.Value.IsoValue c, Michelson.Typed.Haskell.Value.IsoValue d, Michelson.Typed.Haskell.Value.IsoValue e, Michelson.Typed.Haskell.Value.IsoValue f, Michelson.Typed.Haskell.Value.IsoValue g) => Michelson.Typed.Haskell.Value.IsoValue (a, b, c, d, e, f, g) instance (GHC.Classes.Ord k, Michelson.Typed.Haskell.Value.IsoCValue k, Michelson.Typed.Haskell.Value.IsoValue v) => Michelson.Typed.Haskell.Value.IsoValue (Michelson.Typed.Haskell.Value.BigMap k v) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.GIsoValue (GHC.Generics.Rec0 a) instance Michelson.Typed.Haskell.Value.GIsoValue x => Michelson.Typed.Haskell.Value.GIsoValue (GHC.Generics.M1 t i x) instance (Michelson.Typed.Haskell.Value.GIsoValue x, Michelson.Typed.Haskell.Value.GIsoValue y) => Michelson.Typed.Haskell.Value.GIsoValue (x GHC.Generics.:+: y) instance (Michelson.Typed.Haskell.Value.GIsoValue x, Michelson.Typed.Haskell.Value.GIsoValue y) => Michelson.Typed.Haskell.Value.GIsoValue (x GHC.Generics.:*: y) instance Michelson.Typed.Haskell.Value.GIsoValue GHC.Generics.U1 instance Michelson.Typed.Haskell.Value.IsoCValue GHC.Integer.Type.Integer instance Michelson.Typed.Haskell.Value.IsoCValue GHC.Natural.Natural instance Michelson.Typed.Haskell.Value.IsoCValue Michelson.Text.MText instance Michelson.Text.DoNotUseTextError => Michelson.Typed.Haskell.Value.IsoCValue Data.Text.Internal.Text instance Michelson.Typed.Haskell.Value.IsoCValue GHC.Types.Bool instance Michelson.Typed.Haskell.Value.IsoCValue Data.ByteString.Internal.ByteString instance Michelson.Typed.Haskell.Value.IsoCValue Tezos.Core.Mutez instance Michelson.Typed.Haskell.Value.IsoCValue Tezos.Address.Address instance Michelson.Typed.Haskell.Value.IsoCValue Michelson.Typed.EntryPoints.EpAddress instance Michelson.Typed.Haskell.Value.IsoCValue Tezos.Crypto.KeyHash instance Michelson.Typed.Haskell.Value.IsoCValue Tezos.Core.Timestamp -- | Instructions working on sum types derived from Haskell ones. module Michelson.Typed.Haskell.Instr.Sum type InstrWrapC dt name = (IsoValue dt, Generic dt, GInstrWrap (Rep dt) (LnrBranch (GetNamed name dt)) (LnrFieldType (GetNamed name dt)), GValueType (Rep dt) ~ ToT dt) type InstrCaseC dt inp out = (IsoValue dt, GInstrCase (Rep dt), GValueType (Rep dt) ~ ToT dt) type InstrUnwrapC dt name = (IsoValue dt, Generic dt, GInstrUnwrap (Rep dt) (LnrBranch (GetNamed name dt)) (CtorOnlyField name dt), GValueType (Rep dt) ~ ToT dt) -- | Wrap given element into a constructor with the given name. -- -- Mentioned constructor must have only one field. -- -- Since labels interpretable by OverloadedLabels extension cannot -- start with capital latter, prepend constructor name with letter "c" -- (see examples below). instrWrap :: forall dt name st. InstrWrapC dt name => Label name -> Instr (AppendCtorField (GetCtorField dt name) st) (ToT dt : st) -- | Wrap a haskell value into a constructor with the given name. -- -- This is symmetric to instrWrap. hsWrap :: forall dt name. InstrWrapC dt name => Label name -> ExtractCtorField (GetCtorField dt name) -> dt -- | Pattern-match on the given datatype. instrCase :: forall dt out inp. InstrCaseC dt inp out => Rec (CaseClause inp out) (CaseClauses dt) -> RemFail Instr (ToT dt : inp) out -- | Lift an instruction to case clause. -- -- You should write out constructor name corresponding to the clause -- explicitly. Prefix constructor name with "c" letter, otherwise your -- label will not be recognized by Haskell parser. Passing constructor -- name can be circumvented but doing so is not recomended as mentioning -- contructor name improves readability and allows avoiding some -- mistakes. (//->) :: Label ("c" `AppendSymbol` ctor) -> RemFail Instr (AppendCtorField x inp) out -> CaseClause inp out ( 'CaseClauseParam ctor x) infixr 8 //-> -- | Unwrap a constructor with the given name. -- -- Rules which apply to instrWrap function work here as well. -- Although, unlike instrWrap, this function does not work for -- nullary constructors. instrUnwrapUnsafe :: forall dt name st. InstrUnwrapC dt name => Label name -> Instr (ToT dt : st) (ToT (CtorOnlyField name dt) : st) -- | Try to unwrap a constructor with the given name. hsUnwrap :: forall dt name. InstrUnwrapC dt name => Label name -> dt -> Maybe (CtorOnlyField name dt) -- | In what different case branches differ - related constructor name and -- input stack type which the branch starts with. data CaseClauseParam CaseClauseParam :: Symbol -> CtorField -> CaseClauseParam -- | Type information about single case clause. data CaseClause (inp :: [T]) (out :: [T]) (param :: CaseClauseParam) [CaseClause] :: RemFail Instr (AppendCtorField x inp) out -> CaseClause inp out ( 'CaseClauseParam ctor x) -- | List of CaseClauseParams required to pattern match on the given -- type. type CaseClauses a = GCaseClauses (Rep a) type family GCaseClauses x :: [CaseClauseParam] type family GCaseBranchInput ctor x :: CaseClauseParam -- | Which branch to choose in generic tree representation: left, straight -- or right. S is used when there is one constructor with one -- field (something newtype-like). -- -- The reason why we need S can be explained by this example: data -- A = A1 B | A2 Integer data B = B Bool Now we may search for A1 -- constructor or B constructor. Without S in both cases path will -- be the same ([L]). data Branch L :: Branch S :: Branch R :: Branch -- | Path to a leaf (some field or constructor) in generic tree -- representation. type Path = [Branch] -- | We support only two scenarious - constructor with one field and -- without fields. Nonetheless, it's not that sad since for sum types we -- can't even assign names to fields if there are many (the style guide -- prohibits partial records). data CtorField OneField :: Type -> CtorField NoFields :: CtorField -- | Get something as field of the given constructor. type family ExtractCtorField (cf :: CtorField) -- | Push field to stack, if any. type family AppendCtorField (cf :: CtorField) (l :: [k]) :: [k] -- | To use AppendCtorField not only here for T-based stacks, -- but also later in Lorentz with Type-based stacks we need the -- following property. type AppendCtorFieldAxiom (cf :: CtorField) (st :: [Type]) = ToTs (AppendCtorField cf st) ~ AppendCtorField cf (ToTs st) -- | Proof of AppendCtorFieldAxiom. appendCtorFieldAxiom :: (AppendCtorFieldAxiom ( 'OneField Word) '[Int], AppendCtorFieldAxiom 'NoFields '[Int]) => Dict (AppendCtorFieldAxiom cf st) -- | Get type of constructor fields (one or zero) referred by given -- datatype and name. type GetCtorField dt ctor = LnrFieldType (GetNamed ctor dt) -- | Expect referred constructor to have only one field (in form of -- constraint) and extract its type. type CtorHasOnlyField ctor dt f = GetCtorField dt ctor ~ 'OneField f -- | Expect referred constructor to have only one field (otherwise compile -- error is raised) and extract its type. type CtorOnlyField name dt = RequireOneField name (GetCtorField dt name) data MyCompoundType -- | Whether given type represents an atomic Michelson value. type family IsPrimitiveValue (x :: Type) :: Bool instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Typed.Haskell.Instr.Sum.MyTypeWithNamedField instance GHC.Generics.Generic Michelson.Typed.Haskell.Instr.Sum.MyTypeWithNamedField instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Typed.Haskell.Instr.Sum.MyEnum instance GHC.Generics.Generic Michelson.Typed.Haskell.Instr.Sum.MyEnum instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Typed.Haskell.Instr.Sum.MyCompoundType instance GHC.Generics.Generic Michelson.Typed.Haskell.Instr.Sum.MyCompoundType instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Typed.Haskell.Instr.Sum.MyType' instance GHC.Generics.Generic Michelson.Typed.Haskell.Instr.Sum.MyType' instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Typed.Haskell.Instr.Sum.MyType instance GHC.Generics.Generic Michelson.Typed.Haskell.Instr.Sum.MyType instance Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap x path e => Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap (GHC.Generics.D1 i x) path e instance (Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap x path e, Michelson.Typed.Haskell.Value.GIsoValue y, Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.GValueType y)) => Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap (x GHC.Generics.:+: y) ('Michelson.Typed.Haskell.Instr.Helpers.L : path) e instance (Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap y path e, Michelson.Typed.Haskell.Value.GIsoValue x, Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.GValueType x)) => Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap (x GHC.Generics.:+: y) ('Michelson.Typed.Haskell.Instr.Helpers.R : path) e instance Michelson.Typed.Haskell.Value.IsoValue e => Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap (GHC.Generics.C1 c (GHC.Generics.S1 i (GHC.Generics.Rec0 e))) '[ 'Michelson.Typed.Haskell.Instr.Helpers.S] e instance (path Data.Type.Equality.~ (x : xs), Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap (GHC.Generics.Rep sub) path e, GHC.Generics.Generic sub, Michelson.Typed.Haskell.Value.GIsoValue (GHC.Generics.Rep sub), Michelson.Typed.Haskell.Value.IsoValue sub, Michelson.Typed.Haskell.Value.GValueType (GHC.Generics.Rep sub) Data.Type.Equality.~ Michelson.Typed.Haskell.Value.ToT sub) => Michelson.Typed.Haskell.Instr.Sum.GInstrUnwrap (GHC.Generics.C1 c (GHC.Generics.S1 i (GHC.Generics.Rec0 sub))) ('Michelson.Typed.Haskell.Instr.Helpers.S : x : xs) e instance Michelson.Typed.Haskell.Instr.Sum.GInstrCaseBranch ctor x => Michelson.Typed.Haskell.Instr.Sum.GInstrCase (GHC.Generics.C1 ('GHC.Generics.MetaCons ctor _1 _2) x) instance (Michelson.Typed.Haskell.Value.GIsoValue x, Michelson.Typed.Haskell.Value.GIsoValue y, (TypeError ...)) => Michelson.Typed.Haskell.Instr.Sum.GInstrCaseBranch ctor (x GHC.Generics.:*: y) instance Michelson.Typed.Haskell.Instr.Sum.GInstrCaseBranch ctor x => Michelson.Typed.Haskell.Instr.Sum.GInstrCaseBranch ctor (GHC.Generics.S1 i x) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Instr.Sum.GInstrCaseBranch ctor (GHC.Generics.Rec0 a) instance Michelson.Typed.Haskell.Instr.Sum.GInstrCaseBranch ctor GHC.Generics.U1 instance Michelson.Typed.Haskell.Instr.Sum.GInstrCase x => Michelson.Typed.Haskell.Instr.Sum.GInstrCase (GHC.Generics.D1 i x) instance (Michelson.Typed.Haskell.Instr.Sum.GInstrCase x, Michelson.Typed.Haskell.Instr.Sum.GInstrCase y, Util.Type.RSplit (Michelson.Typed.Haskell.Instr.Sum.GCaseClauses x) (Michelson.Typed.Haskell.Instr.Sum.GCaseClauses y)) => Michelson.Typed.Haskell.Instr.Sum.GInstrCase (x GHC.Generics.:+: y) instance Michelson.Typed.Haskell.Instr.Sum.GInstrWrap x path e => Michelson.Typed.Haskell.Instr.Sum.GInstrWrap (GHC.Generics.D1 i x) path e instance (Michelson.Typed.Haskell.Instr.Sum.GInstrWrap x path e, Michelson.Typed.Haskell.Value.GIsoValue y, Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.GValueType y)) => Michelson.Typed.Haskell.Instr.Sum.GInstrWrap (x GHC.Generics.:+: y) ('Michelson.Typed.Haskell.Instr.Helpers.L : path) e instance (Michelson.Typed.Haskell.Instr.Sum.GInstrWrap y path e, Michelson.Typed.Haskell.Value.GIsoValue x, Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.GValueType x)) => Michelson.Typed.Haskell.Instr.Sum.GInstrWrap (x GHC.Generics.:+: y) ('Michelson.Typed.Haskell.Instr.Helpers.R : path) e instance Michelson.Typed.Haskell.Value.IsoValue e => Michelson.Typed.Haskell.Instr.Sum.GInstrWrap (GHC.Generics.C1 c (GHC.Generics.S1 i (GHC.Generics.Rec0 e))) '[ 'Michelson.Typed.Haskell.Instr.Helpers.S] ('Michelson.Typed.Haskell.Instr.Sum.OneField e) instance (path Data.Type.Equality.~ (x : xs), Michelson.Typed.Haskell.Instr.Sum.GInstrWrap (GHC.Generics.Rep sub) path e, GHC.Generics.Generic sub, Michelson.Typed.Haskell.Value.GIsoValue (GHC.Generics.Rep sub), Michelson.Typed.Haskell.Value.IsoValue sub, Michelson.Typed.Haskell.Value.GValueType (GHC.Generics.Rep sub) Data.Type.Equality.~ Michelson.Typed.Haskell.Value.ToT sub) => Michelson.Typed.Haskell.Instr.Sum.GInstrWrap (GHC.Generics.C1 c (GHC.Generics.S1 i (GHC.Generics.Rec0 sub))) ('Michelson.Typed.Haskell.Instr.Helpers.S : x : xs) e instance Michelson.Typed.Haskell.Instr.Sum.GInstrWrap (GHC.Generics.C1 c GHC.Generics.U1) '[ 'Michelson.Typed.Haskell.Instr.Helpers.S] 'Michelson.Typed.Haskell.Instr.Sum.NoFields -- | Instructions working on product types derived from Haskell ones. module Michelson.Typed.Haskell.Instr.Product -- | Constraint for instrGetField. type InstrGetFieldC dt name = (IsoValue dt, Generic dt, GInstrGet name (Rep dt) (LnrBranch (GetNamed name dt)) (LnrFieldType (GetNamed name dt)), GValueType (Rep dt) ~ ToT dt) -- | Constraint for instrSetField. type InstrSetFieldC dt name = (IsoValue dt, Generic dt, GInstrSetField name (Rep dt) (LnrBranch (GetNamed name dt)) (LnrFieldType (GetNamed name dt)), GValueType (Rep dt) ~ ToT dt) -- | Constraint for instrConstruct. type InstrConstructC dt = (IsoValue dt, Generic dt, GInstrConstruct (Rep dt), GValueType (Rep dt) ~ ToT dt) -- | Make an instruction which accesses given field of the given datatype. instrGetField :: forall dt name st. InstrGetFieldC dt name => Label name -> Instr (ToT dt : st) (ToT (GetFieldType dt name) : st) -- | For given complex type dt and its field fieldTy -- update the field value. instrSetField :: forall dt name st. InstrSetFieldC dt name => Label name -> Instr (ToT (GetFieldType dt name) : (ToT dt : st)) (ToT dt : st) -- | For given complex type dt and its field fieldTy -- update the field value. instrConstruct :: forall dt st. InstrConstructC dt => Rec (FieldConstructor st) (ConstructorFieldTypes dt) -> Instr st (ToT dt : st) -- | Get type of field by datatype it is contained in and field name. type GetFieldType dt name = LnrFieldType (GetNamed name dt) -- | Types of all fields in a datatype. type ConstructorFieldTypes dt = GFieldTypes (Rep dt) -- | Way to construct one of the fields in a complex datatype. newtype FieldConstructor (st :: [k]) (field :: Type) FieldConstructor :: Instr (ToTs' st) (ToT field : ToTs' st) -> FieldConstructor instance Michelson.Typed.Haskell.Value.IsoValue Michelson.Typed.Haskell.Instr.Product.MyType2 instance GHC.Generics.Generic Michelson.Typed.Haskell.Instr.Product.MyType2 instance Michelson.Typed.Haskell.Instr.Product.GInstrConstruct x => Michelson.Typed.Haskell.Instr.Product.GInstrConstruct (GHC.Generics.M1 t i x) instance (Michelson.Typed.Haskell.Instr.Product.GInstrConstruct x, Michelson.Typed.Haskell.Instr.Product.GInstrConstruct y, Util.Type.RSplit (Michelson.Typed.Haskell.Instr.Product.GFieldTypes x) (Michelson.Typed.Haskell.Instr.Product.GFieldTypes y)) => Michelson.Typed.Haskell.Instr.Product.GInstrConstruct (x GHC.Generics.:*: y) instance Michelson.Typed.Haskell.Instr.Product.GInstrConstruct GHC.Generics.U1 instance ((TypeError ...), Michelson.Typed.Haskell.Value.GIsoValue x, Michelson.Typed.Haskell.Value.GIsoValue y) => Michelson.Typed.Haskell.Instr.Product.GInstrConstruct (x GHC.Generics.:+: y) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Instr.Product.GInstrConstruct (GHC.Generics.Rec0 a) instance Michelson.Typed.Haskell.Instr.Product.GInstrSetField name x path f => Michelson.Typed.Haskell.Instr.Product.GInstrSetField name (GHC.Generics.M1 t i x) path f instance (Michelson.Typed.Haskell.Value.IsoValue f, Michelson.Typed.Haskell.Value.ToT f Data.Type.Equality.~ Michelson.Typed.Haskell.Value.ToT f') => Michelson.Typed.Haskell.Instr.Product.GInstrSetField name (GHC.Generics.Rec0 f) '[] f' instance (Michelson.Typed.Haskell.Instr.Product.GInstrSetField name x path f, Michelson.Typed.Haskell.Value.GIsoValue y) => Michelson.Typed.Haskell.Instr.Product.GInstrSetField name (x GHC.Generics.:*: y) ('Michelson.Typed.Haskell.Instr.Helpers.L : path) f instance (Michelson.Typed.Haskell.Instr.Product.GInstrSetField name y path f, Michelson.Typed.Haskell.Value.GIsoValue x) => Michelson.Typed.Haskell.Instr.Product.GInstrSetField name (x GHC.Generics.:*: y) ('Michelson.Typed.Haskell.Instr.Helpers.R : path) f instance Michelson.Typed.Haskell.Instr.Product.GInstrGet name x path f => Michelson.Typed.Haskell.Instr.Product.GInstrGet name (GHC.Generics.M1 t i x) path f instance (Michelson.Typed.Haskell.Value.IsoValue f, Michelson.Typed.Haskell.Value.ToT f Data.Type.Equality.~ Michelson.Typed.Haskell.Value.ToT f') => Michelson.Typed.Haskell.Instr.Product.GInstrGet name (GHC.Generics.Rec0 f) '[] f' instance (Michelson.Typed.Haskell.Instr.Product.GInstrGet name x path f, Michelson.Typed.Haskell.Value.GIsoValue y) => Michelson.Typed.Haskell.Instr.Product.GInstrGet name (x GHC.Generics.:*: y) ('Michelson.Typed.Haskell.Instr.Helpers.L : path) f instance (Michelson.Typed.Haskell.Instr.Product.GInstrGet name y path f, Michelson.Typed.Haskell.Value.GIsoValue x) => Michelson.Typed.Haskell.Instr.Product.GInstrGet name (x GHC.Generics.:*: y) ('Michelson.Typed.Haskell.Instr.Helpers.R : path) f module Michelson.Typed.Haskell.Instr -- | Representation of Haskell sum types via loosy typed Michelson values, -- useful for e.g. errors and enums. -- -- In particular, ADT sum can be represented as constructor name + data -- it carries. Such expression does not have particular type because -- different constructors may carry different data, and we avoid lifting -- this data to a union in order to keep only the significant parts (and -- thus not to confuse the client). module Michelson.Typed.Haskell.LooseSum -- | Possible outcomes of an attempt to construct a Haskell ADT value from -- constructor name and relevant data. data ComposeResult a -- | Composed fine. ComposeOk :: a -> ComposeResult a -- | No constructor with such name. ComposeCtorNotFound :: ComposeResult a -- | Found required constructor, but type of data does not correspond to -- provided one. ComposeFieldTypeMismatch :: TypeRep -> TypeRep -> ComposeResult a -- | Inverse to toTaggedVal. fromTaggedVal :: LooseSumC dt => (Text, SomeValue) -> ComposeResult dt -- | Decompose Haskell type into constructor name and data it carries, -- converting the latter into Michelson Value. toTaggedVal :: LooseSumC dt => dt -> (Text, SomeValue) -- | Constraint for hsDecompose and hsCompose. type LooseSumC dt = (Generic dt, GLooseSum (Rep dt)) instance GHC.Base.Functor Michelson.Typed.Haskell.LooseSum.ComposeResult instance (Michelson.Typed.Haskell.LooseSum.GAccessField x, GHC.TypeLits.KnownSymbol ctor) => Michelson.Typed.Haskell.LooseSum.GLooseSum (GHC.Generics.C1 ('GHC.Generics.MetaCons ctor f o) x) instance Michelson.Typed.Haskell.LooseSum.GAccessField x => Michelson.Typed.Haskell.LooseSum.GAccessField (GHC.Generics.S1 i x) instance (Data.Typeable.Internal.Typeable a, Michelson.Typed.Haskell.Value.IsoValue a, Data.Typeable.Internal.Typeable (Michelson.Typed.Haskell.Value.ToT a), Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.ToT a)) => Michelson.Typed.Haskell.LooseSum.GAccessField (GHC.Generics.Rec0 a) instance Michelson.Typed.Haskell.LooseSum.GAccessField GHC.Generics.U1 instance (TypeError ...) => Michelson.Typed.Haskell.LooseSum.GAccessField (x GHC.Generics.:*: y) instance Michelson.Typed.Haskell.LooseSum.GLooseSum x => Michelson.Typed.Haskell.LooseSum.GLooseSum (GHC.Generics.D1 i x) instance (Michelson.Typed.Haskell.LooseSum.GLooseSum x, Michelson.Typed.Haskell.LooseSum.GLooseSum y) => Michelson.Typed.Haskell.LooseSum.GLooseSum (x GHC.Generics.:+: y) instance Michelson.Typed.Haskell.LooseSum.GLooseSum GHC.Generics.V1 instance GHC.Base.Semigroup (Michelson.Typed.Haskell.LooseSum.ComposeResult a) instance GHC.Base.Monoid (Michelson.Typed.Haskell.LooseSum.ComposeResult a) -- | Documentation of types appearing in contracts. module Michelson.Typed.Haskell.Doc -- | Stands for representation of some Haskell ADT corresponding to -- Michelson value. Type parameter a is what you put in place of -- each field of the datatype, e.g. information about field type. -- -- Outer list layer corresponds to union, and the inner one corresponds -- to products within constructors. Constructors and fields names are -- present. type ADTRep a = NonEmpty (Text, [(Maybe Text, a)]) -- | Whether given text should be rendered grouped in parentheses (if they -- make sense). newtype WithinParens WithinParens :: Bool -> WithinParens -- | Description for a Haskell type appearing in documentation. class Typeable a => TypeHasDoc a -- | Name of type as it appears in definitions section. -- -- Each type must have its own unique name because it will be used in -- identifier for references. -- -- Default definition derives name from Generics. If it does not fit, -- consider defining this function manually. (We tried using Data -- for this, but it produces names including module names which is not do -- we want). typeDocName :: TypeHasDoc a => Proxy a -> Text -- | Name of type as it appears in definitions section. -- -- Each type must have its own unique name because it will be used in -- identifier for references. -- -- Default definition derives name from Generics. If it does not fit, -- consider defining this function manually. (We tried using Data -- for this, but it produces names including module names which is not do -- we want). typeDocName :: (TypeHasDoc a, Generic a, KnownSymbol (GenericTypeName a)) => Proxy a -> Text -- | Explanation of a type. Markdown formatting is allowed. typeDocMdDescription :: TypeHasDoc a => Markdown -- | How reference to this type is rendered, in Markdown. -- -- Examples: * Integer, * Maybe -- (). -- -- Consider using one of the following functions as default -- implementation; which one to use depends on number of type arguments -- in your type: * homomorphicTypeDocMdReference * -- poly1TypeDocMdReference * poly2TypeDocMdReference -- -- If none of them fits your purposes precisely, consider using -- customTypeDocMdReference. typeDocMdReference :: TypeHasDoc a => Proxy a -> WithinParens -> Markdown -- | How reference to this type is rendered, in Markdown. -- -- Examples: * Integer, * Maybe -- (). -- -- Consider using one of the following functions as default -- implementation; which one to use depends on number of type arguments -- in your type: * homomorphicTypeDocMdReference * -- poly1TypeDocMdReference * poly2TypeDocMdReference -- -- If none of them fits your purposes precisely, consider using -- customTypeDocMdReference. typeDocMdReference :: (TypeHasDoc a, Typeable a, IsHomomorphic a) => Proxy a -> WithinParens -> Markdown -- | All types which this type directly contains. -- -- Used in automatic types discovery. typeDocDependencies :: TypeHasDoc a => Proxy a -> [SomeTypeWithDoc] -- | All types which this type directly contains. -- -- Used in automatic types discovery. typeDocDependencies :: (TypeHasDoc a, Generic a, GTypeHasDoc (Rep a)) => Proxy a -> [SomeTypeWithDoc] -- | For complex types - their immediate Haskell representation. -- -- For primitive types set this to Nothing. -- -- For homomorphic types use homomorphicTypeDocHaskellRep -- implementation. -- -- For polymorhpic types consider using concreteTypeDocHaskellRep -- as implementation. -- -- Modifier haskellRepNoFields can be used to hide names of -- fields, beneficial for newtypes. -- -- Another modifier called haskellRepStripFieldPrefix can be used -- for datatypes to leave only meaningful part of name in every field. typeDocHaskellRep :: TypeHasDoc a => TypeDocHaskellRep a -- | For complex types - their immediate Haskell representation. -- -- For primitive types set this to Nothing. -- -- For homomorphic types use homomorphicTypeDocHaskellRep -- implementation. -- -- For polymorhpic types consider using concreteTypeDocHaskellRep -- as implementation. -- -- Modifier haskellRepNoFields can be used to hide names of -- fields, beneficial for newtypes. -- -- Another modifier called haskellRepStripFieldPrefix can be used -- for datatypes to leave only meaningful part of name in every field. typeDocHaskellRep :: (TypeHasDoc a, Generic a, GTypeHasDoc (Rep a), IsHomomorphic a) => TypeDocHaskellRep a -- | Final michelson representation of a type. -- -- For homomorphic types use homomorphicTypeDocMichelsonRep -- implementation. -- -- For polymorhpic types consider using -- concreteTypeDocMichelsonRep as implementation. typeDocMichelsonRep :: TypeHasDoc a => TypeDocMichelsonRep a -- | Final michelson representation of a type. -- -- For homomorphic types use homomorphicTypeDocMichelsonRep -- implementation. -- -- For polymorhpic types consider using -- concreteTypeDocMichelsonRep as implementation. typeDocMichelsonRep :: (TypeHasDoc a, SingI (ToT a), IsHomomorphic a) => TypeDocMichelsonRep a -- | Signature of typeDocHaskellRep function. -- -- When value is Just, it contains types which this type is built -- from. -- -- First element of provided pair may contain name a concrete type which -- has the same type constructor as a (or just a for -- homomorphic types), and the second element of the pair - its unfolding -- in Haskell. -- -- For example, for some newtype MyNewtype = MyNewtype (Integer, -- Natural) we would not specify the first element in the pair -- because MyNewtype is already a concrete type, and second -- element would contain (Integer, Natural). For polymorhpic -- types like newtype MyPolyNewtype a = MyPolyNewtype (Text, a), -- we want to describe its representation on some example of a, -- because working with type variables is too non-trivial; so the first -- element of the pair may be e.g. "MyPolyNewType Integer", and -- the second one shows that it unfolds to (Text, Integer). -- -- When rendered, values of this type look like: * (Integer, -- Natural) - for homomorphic type. * MyError Integer = (Text, -- Integer) - concrete sample for polymorhpic type. type TypeDocHaskellRep a = Proxy a -> Maybe (Maybe DocTypeRepLHS, ADTRep SomeTypeWithDoc) -- | Signature of typeDocMichelsonRep function. -- -- As in TypeDocHaskellRep, set the first element of the pair to -- Nothing for primitive types, otherwise it stands as some -- instantiation of a type, and its Michelson representation is given in -- the second element of the pair. -- -- Examples of rendered representation: * pair int nat - for -- homomorphic type. * MyError Integer = pair string int - -- concrete sample for polymorhpic type. type TypeDocMichelsonRep a = Proxy a -> (Maybe DocTypeRepLHS, T) -- | Constraint, required when deriving TypeHasDoc for polymorphic -- type with the least possible number of methods defined manually. type PolyTypeHasDocC ts = Each '[TypeHasDoc] ts -- | Data hides some type implementing TypeHasDoc. data SomeTypeWithDoc [SomeTypeWithDoc] :: TypeHasDoc td => Proxy td -> SomeTypeWithDoc -- | Like typeDocDependencies but returns values of more common type -- which is used in docItemDependencies. typeDocDependencies' :: TypeHasDoc a => Proxy a -> [SomeDocDefinitionItem] -- | Require two types to be built from the same type constructor. -- -- E.g. HaveCommonTypeCtor (Maybe Integer) (Maybe Natural) is -- defined, while HaveCmmonTypeCtor (Maybe Integer) [Integer] is -- not. class HaveCommonTypeCtor a b -- | Require this type to be homomorphic. class IsHomomorphic a -- | Implement typeDocDependencies via getting all immediate fields -- of a datatype. -- -- Note: this will not include phantom types, I'm not sure yet how this -- scenario should be handled (@martoon). genericTypeDocDependencies :: forall a. (Generic a, GTypeHasDoc (Rep a)) => Proxy a -> [SomeTypeWithDoc] -- | Render a reference to a type which consists of type constructor (you -- have to provide name of this type constructor and documentation for -- the whole type) and zero or more type arguments. customTypeDocMdReference :: (Text, DType) -> [DType] -> WithinParens -> Markdown -- | Derive typeDocMdReference, for homomorphic types only. homomorphicTypeDocMdReference :: forall (t :: Type). (Typeable t, TypeHasDoc t, IsHomomorphic t) => Proxy t -> WithinParens -> Markdown -- | Derive typeDocMdReference, for polymorphic type with one type -- argument, like Maybe Integer. poly1TypeDocMdReference :: forall t (r :: Type) (a :: Type). (r ~ t a, Typeable t, Each '[TypeHasDoc] [r, a], IsHomomorphic t) => Proxy r -> WithinParens -> Markdown -- | Derive typeDocMdReference, for polymorphic type with two type -- arguments, like Lambda Integer Natural. poly2TypeDocMdReference :: forall t (r :: Type) (a :: Type) (b :: Type). (r ~ t a b, Typeable t, Each '[TypeHasDoc] [r, a, b], IsHomomorphic t) => Proxy r -> WithinParens -> Markdown -- | Implement typeDocHaskellRep for a homomorphic type. -- -- Note that it does not require your type to be of IsHomomorphic -- instance, which can be useful for some polymorhpic types which, for -- documentation purposes, we want to consider homomorphic. Example: -- Operation is in fact polymorhpic, but we don't want this fact -- to be reflected in the documentation. homomorphicTypeDocHaskellRep :: forall a. (Generic a, GTypeHasDoc (Rep a)) => TypeDocHaskellRep a -- | Implement typeDocHaskellRep on example of given concrete type. -- -- This is a best effort attempt to implement typeDocHaskellRep -- for polymorhpic types, as soon as there is no simple way to preserve -- type variables when automatically deriving Haskell representation of a -- type. concreteTypeDocHaskellRep :: forall a b. (Typeable a, IsoValue a, Generic a, GTypeHasDoc (Rep a), HaveCommonTypeCtor b a) => TypeDocHaskellRep b -- | Version of concreteTypeDocHaskellRep which does not ensure -- whether the type for which representation is built is any similar to -- the original type which you implement a TypeHasDoc instance -- for. concreteTypeDocHaskellRepUnsafe :: forall a b. (Typeable a, IsoValue a, Generic a, GTypeHasDoc (Rep a)) => TypeDocHaskellRep b -- | Erase fields from Haskell datatype representation. -- -- Use this when rendering fields names is undesired. haskellRepNoFields :: TypeDocHaskellRep a -> TypeDocHaskellRep a -- | Cut fields prefixes which we use according to the style guide. -- -- E.g. cmMyField field will be transformed to myField. haskellRepStripFieldPrefix :: HasCallStack => TypeDocHaskellRep a -> TypeDocHaskellRep a -- | Implement typeDocMichelsonRep for homomorphic type. homomorphicTypeDocMichelsonRep :: forall a. SingI (ToT a) => TypeDocMichelsonRep a -- | Implement typeDocMichelsonRep on example of given concrete -- type. -- -- This function exists for the same reason as -- concreteTypeDocHaskellRep. concreteTypeDocMichelsonRep :: forall a b. (Typeable a, SingI (ToT a), HaveCommonTypeCtor b a) => TypeDocMichelsonRep b -- | Version of concreteTypeDocHaskellRepUnsafe which does not -- ensure whether the type for which representation is built is any -- similar to the original type which you implement a TypeHasDoc -- instance for. concreteTypeDocMichelsonRepUnsafe :: forall a b. (Typeable a, SingI (ToT a)) => TypeDocMichelsonRep b -- | Doc element with description of a type. data DType [DType] :: TypeHasDoc a => Proxy a -> DType -- | Generic traversal for automatic deriving of some methods in -- TypeHasDoc. class GTypeHasDoc (x :: Type -> Type) -- | Show given ADTRep in a neat way. buildADTRep :: forall a. (WithinParens -> a -> Markdown) -> ADTRep a -> Markdown applyWithinParens :: WithinParens -> Markdown -> Markdown instance Formatting.Buildable.Buildable Michelson.Typed.Haskell.Doc.DocTypeRepLHS instance Data.String.IsString Michelson.Typed.Haskell.Doc.DocTypeRepLHS instance Michelson.Typed.Haskell.Doc.PolyCTypeHasDocC '[a] => Michelson.Typed.Haskell.Doc.TypeHasDoc (Data.Set.Internal.Set a) instance (Michelson.Typed.Haskell.Doc.PolyCTypeHasDocC '[k], Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[v], GHC.Classes.Ord k) => Michelson.Typed.Haskell.Doc.TypeHasDoc (Data.Map.Internal.Map k v) instance (Michelson.Typed.Haskell.Doc.PolyCTypeHasDocC '[k], Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[v], GHC.Classes.Ord k) => Michelson.Typed.Haskell.Doc.TypeHasDoc (Michelson.Typed.Haskell.Value.BigMap k v) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[a] => Michelson.Typed.Haskell.Doc.TypeHasDoc [a] instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[a] => Michelson.Typed.Haskell.Doc.TypeHasDoc (GHC.Maybe.Maybe a) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[l, r] => Michelson.Typed.Haskell.Doc.TypeHasDoc (Data.Either.Either l r) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[a, b] => Michelson.Typed.Haskell.Doc.TypeHasDoc (a, b) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[cp] => Michelson.Typed.Haskell.Doc.TypeHasDoc (Michelson.Typed.Haskell.Value.ContractRef cp) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[a, b, c] => Michelson.Typed.Haskell.Doc.TypeHasDoc (a, b, c) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[a, b, c, d] => Michelson.Typed.Haskell.Doc.TypeHasDoc (a, b, c, d) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[a, b, c, d, e] => Michelson.Typed.Haskell.Doc.TypeHasDoc (a, b, c, d, e) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[a, b, c, d, e, f] => Michelson.Typed.Haskell.Doc.TypeHasDoc (a, b, c, d, e, f) instance Michelson.Typed.Haskell.Doc.PolyTypeHasDocC '[a, b, c, d, e, f, g] => Michelson.Typed.Haskell.Doc.TypeHasDoc (a, b, c, d, e, f, g) instance (Michelson.Typed.Haskell.Doc.GProductHasDoc x, GHC.TypeLits.KnownSymbol ctor) => Michelson.Typed.Haskell.Doc.GTypeHasDoc (GHC.Generics.C1 ('GHC.Generics.MetaCons ctor _1 _2) x) instance (Michelson.Typed.Haskell.Doc.GProductHasDoc x, Michelson.Typed.Haskell.Doc.GProductHasDoc y) => Michelson.Typed.Haskell.Doc.GProductHasDoc (x GHC.Generics.:*: y) instance Michelson.Typed.Haskell.Doc.TypeHasDoc a => Michelson.Typed.Haskell.Doc.GProductHasDoc (GHC.Generics.S1 ('GHC.Generics.MetaSel 'GHC.Maybe.Nothing _1 _2 _3) (GHC.Generics.Rec0 a)) instance (Michelson.Typed.Haskell.Doc.TypeHasDoc a, GHC.TypeLits.KnownSymbol field) => Michelson.Typed.Haskell.Doc.GProductHasDoc (GHC.Generics.S1 ('GHC.Generics.MetaSel ('GHC.Maybe.Just field) _1 _2 _3) (GHC.Generics.Rec0 a)) instance Michelson.Typed.Haskell.Doc.GProductHasDoc GHC.Generics.U1 instance GHC.Classes.Eq Michelson.Typed.Haskell.Doc.DType instance GHC.Classes.Ord Michelson.Typed.Haskell.Doc.DType instance Michelson.Doc.DocItem Michelson.Typed.Haskell.Doc.DType instance Michelson.Typed.Haskell.Doc.TypeHasDoc Michelson.Text.MText instance Michelson.Typed.Haskell.Doc.TypeHasDoc Michelson.Typed.Aliases.Operation instance GHC.Show.Show Michelson.Typed.Haskell.Doc.SomeTypeWithDoc instance Michelson.Typed.Haskell.Doc.GTypeHasDoc x => Michelson.Typed.Haskell.Doc.GTypeHasDoc (GHC.Generics.D1 i x) instance (Michelson.Typed.Haskell.Doc.GTypeHasDoc x, Michelson.Typed.Haskell.Doc.GTypeHasDoc y) => Michelson.Typed.Haskell.Doc.GTypeHasDoc (x GHC.Generics.:+: y) instance (TypeError ...) => Michelson.Typed.Haskell.Doc.GTypeHasDoc GHC.Generics.V1 instance Michelson.Typed.Haskell.Doc.TypeHasDoc GHC.Integer.Type.Integer instance Michelson.Typed.Haskell.Doc.TypeHasDoc GHC.Natural.Natural instance Michelson.Typed.Haskell.Doc.TypeHasDoc GHC.Types.Bool instance Michelson.Typed.Haskell.Doc.TypeHasDoc Data.ByteString.Internal.ByteString instance Michelson.Typed.Haskell.Doc.TypeHasDoc Tezos.Core.Mutez instance Michelson.Typed.Haskell.Doc.TypeHasDoc Tezos.Crypto.KeyHash instance Michelson.Typed.Haskell.Doc.TypeHasDoc Tezos.Core.Timestamp instance Michelson.Typed.Haskell.Doc.TypeHasDoc Tezos.Address.Address instance Michelson.Typed.Haskell.Doc.TypeHasDoc Michelson.Typed.EntryPoints.EpAddress instance Michelson.Typed.Haskell.Doc.TypeHasDoc Tezos.Crypto.PublicKey instance Michelson.Typed.Haskell.Doc.TypeHasDoc Tezos.Crypto.Signature instance Michelson.Typed.Haskell.Doc.TypeHasDoc () instance (Michelson.Typed.Haskell.Doc.TypeHasDoc (Util.Named.ApplyNamedFunctor f a), GHC.TypeLits.KnownSymbol n, Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.ToT (Util.Named.ApplyNamedFunctor f GHC.Integer.Type.Integer)), Data.Typeable.Internal.Typeable f, Data.Typeable.Internal.Typeable a) => Michelson.Typed.Haskell.Doc.TypeHasDoc (Named.Internal.NamedF f a n) instance forall k1 k2 (a :: k1 -> k2) (b :: k1). (TypeError ...) => Michelson.Typed.Haskell.Doc.IsHomomorphic (a b) instance forall k (a :: k). Michelson.Typed.Haskell.Doc.IsHomomorphic a instance forall k1 k2 k3 k4 (ac :: k3 -> k4) (bc :: k1 -> k2) (a :: k3) (b :: k1). Michelson.Typed.Haskell.Doc.HaveCommonTypeCtor ac bc => Michelson.Typed.Haskell.Doc.HaveCommonTypeCtor (ac a) (bc b) instance forall k (a :: k). Michelson.Typed.Haskell.Doc.HaveCommonTypeCtor a a -- | Haskell-Michelson conversions. module Michelson.Typed.Haskell -- | Path to a leaf (some field or constructor) in generic tree -- representation. type Path = [Branch] -- | Which branch to choose in generic tree representation: left, straight -- or right. S is used when there is one constructor with one -- field (something newtype-like). -- -- The reason why we need S can be explained by this example: data -- A = A1 B | A2 Integer data B = B Bool Now we may search for A1 -- constructor or B constructor. Without S in both cases path will -- be the same ([L]). data Branch L :: Branch S :: Branch R :: Branch -- | Isomorphism between Michelson stack and its Haskell reflection. class IsoValuesStack (ts :: [Type]) toValStack :: IsoValuesStack ts => Rec Identity ts -> Rec Value (ToTs ts) fromValStack :: IsoValuesStack ts => Rec Value (ToTs ts) -> Rec Identity ts -- | Overloaded version of ToTs to work on Haskell and T -- stacks. type family ToTs' (t :: [k]) :: [T] -- | Type function to convert a Haskell stack type to T-based one. type family ToTs (ts :: [Type]) :: [T] -- | Whether Michelson representation of the type is derived via Generics. type IsGenericIsoValue t = (IsoValue t, Generic t, ToT t ~ GValueType (Rep t)) newtype BigMap k v BigMap :: Map k v -> BigMap k v [unBigMap] :: BigMap k v -> Map k v -- | Since Contract name is used to designate contract code, lets -- call analogy of TContract type as follows. data ContractRef (arg :: Type) ContractRef :: Address -> SomeEntryPointCall arg -> ContractRef [crAddress] :: ContractRef -> Address [crEntryPoint] :: ContractRef -> SomeEntryPointCall arg type SomeEntryPointCall arg = SomeEntryPointCallT (ToT arg) type EntryPointCall param arg = EntryPointCallT (ToT param) (ToT arg) -- | A useful property which holds for all CT types. type IsComparable c = ToT c ~ 'Tc (ToCT c) -- | Any Haskell value which can be converted to Michelson Value. newtype AnyIsoValue AnyIsoValue :: (forall a. IsoValue a => a) -> AnyIsoValue -- | Hides some Haskell value put in line with Michelson Value. data SomeIsoValue [SomeIsoValue] :: (Typeable a, IsoValue a) => a -> SomeIsoValue -- | Overloaded version of ToT to work on Haskell and T -- types. type family ToT' (t :: k) :: T -- | Isomorphism between Michelson values and plain Haskell types. -- -- Default implementation of this typeclass converts ADTs to Michelson -- "pair"s and "or"s. class IsoValue a where { -- | Type function that converts a regular Haskell type into a T -- type. type family ToT a :: T; type ToT a = GValueType (Rep a); } -- | Converts a Haskell structure into Value representation. toVal :: IsoValue a => a -> Value (ToT a) -- | Converts a Haskell structure into Value representation. toVal :: (IsoValue a, Generic a, GIsoValue (Rep a), ToT a ~ GValueType (Rep a)) => a -> Value (ToT a) -- | Converts a Value into Haskell type. fromVal :: IsoValue a => Value (ToT a) -> a -- | Converts a Value into Haskell type. fromVal :: (IsoValue a, Generic a, GIsoValue (Rep a), ToT a ~ GValueType (Rep a)) => Value (ToT a) -> a -- | Isomorphism between Michelson primitive values and plain Haskell -- types. class IsoCValue a where { -- | Type function that converts a regular Haskell type into a comparable -- type (which has kind CT). type family ToCT a :: CT; } -- | Converts a single Haskell value into CVal representation. toCVal :: IsoCValue a => a -> CValue (ToCT a) -- | Converts a CVal value into a single Haskell value. fromCVal :: IsoCValue a => CValue (ToCT a) -> a -- | Replace type argument of ContractAddr with isomorphic one. coerceContractRef :: ToT a ~ ToT b => ContractRef a -> ContractRef b totsKnownLemma :: forall s. KnownList s :- KnownList (ToTs s) totsAppendLemma :: forall a b. KnownList a => Dict (ToTs (a ++ b) ~ (ToTs a ++ ToTs b)) type InstrUnwrapC dt name = (IsoValue dt, Generic dt, GInstrUnwrap (Rep dt) (LnrBranch (GetNamed name dt)) (CtorOnlyField name dt), GValueType (Rep dt) ~ ToT dt) type family GCaseBranchInput ctor x :: CaseClauseParam type family GCaseClauses x :: [CaseClauseParam] -- | List of CaseClauseParams required to pattern match on the given -- type. type CaseClauses a = GCaseClauses (Rep a) -- | Type information about single case clause. data CaseClause (inp :: [T]) (out :: [T]) (param :: CaseClauseParam) [CaseClause] :: RemFail Instr (AppendCtorField x inp) out -> CaseClause inp out ( 'CaseClauseParam ctor x) -- | In what different case branches differ - related constructor name and -- input stack type which the branch starts with. data CaseClauseParam CaseClauseParam :: Symbol -> CtorField -> CaseClauseParam type InstrCaseC dt inp out = (IsoValue dt, GInstrCase (Rep dt), GValueType (Rep dt) ~ ToT dt) data MyCompoundType type InstrWrapC dt name = (IsoValue dt, Generic dt, GInstrWrap (Rep dt) (LnrBranch (GetNamed name dt)) (LnrFieldType (GetNamed name dt)), GValueType (Rep dt) ~ ToT dt) -- | Expect referred constructor to have only one field (otherwise compile -- error is raised) and extract its type. type CtorOnlyField name dt = RequireOneField name (GetCtorField dt name) -- | Expect referred constructor to have only one field (in form of -- constraint) and extract its type. type CtorHasOnlyField ctor dt f = GetCtorField dt ctor ~ 'OneField f -- | Get type of constructor fields (one or zero) referred by given -- datatype and name. type GetCtorField dt ctor = LnrFieldType (GetNamed ctor dt) -- | Whether given type represents an atomic Michelson value. type family IsPrimitiveValue (x :: Type) :: Bool -- | To use AppendCtorField not only here for T-based stacks, -- but also later in Lorentz with Type-based stacks we need the -- following property. type AppendCtorFieldAxiom (cf :: CtorField) (st :: [Type]) = ToTs (AppendCtorField cf st) ~ AppendCtorField cf (ToTs st) -- | Push field to stack, if any. type family AppendCtorField (cf :: CtorField) (l :: [k]) :: [k] -- | Get something as field of the given constructor. type family ExtractCtorField (cf :: CtorField) -- | We support only two scenarious - constructor with one field and -- without fields. Nonetheless, it's not that sad since for sum types we -- can't even assign names to fields if there are many (the style guide -- prohibits partial records). data CtorField OneField :: Type -> CtorField NoFields :: CtorField -- | Proof of AppendCtorFieldAxiom. appendCtorFieldAxiom :: (AppendCtorFieldAxiom ( 'OneField Word) '[Int], AppendCtorFieldAxiom 'NoFields '[Int]) => Dict (AppendCtorFieldAxiom cf st) -- | Wrap given element into a constructor with the given name. -- -- Mentioned constructor must have only one field. -- -- Since labels interpretable by OverloadedLabels extension cannot -- start with capital latter, prepend constructor name with letter "c" -- (see examples below). instrWrap :: forall dt name st. InstrWrapC dt name => Label name -> Instr (AppendCtorField (GetCtorField dt name) st) (ToT dt : st) -- | Wrap a haskell value into a constructor with the given name. -- -- This is symmetric to instrWrap. hsWrap :: forall dt name. InstrWrapC dt name => Label name -> ExtractCtorField (GetCtorField dt name) -> dt -- | Pattern-match on the given datatype. instrCase :: forall dt out inp. InstrCaseC dt inp out => Rec (CaseClause inp out) (CaseClauses dt) -> RemFail Instr (ToT dt : inp) out -- | Lift an instruction to case clause. -- -- You should write out constructor name corresponding to the clause -- explicitly. Prefix constructor name with "c" letter, otherwise your -- label will not be recognized by Haskell parser. Passing constructor -- name can be circumvented but doing so is not recomended as mentioning -- contructor name improves readability and allows avoiding some -- mistakes. (//->) :: Label ("c" `AppendSymbol` ctor) -> RemFail Instr (AppendCtorField x inp) out -> CaseClause inp out ( 'CaseClauseParam ctor x) infixr 8 //-> -- | Unwrap a constructor with the given name. -- -- Rules which apply to instrWrap function work here as well. -- Although, unlike instrWrap, this function does not work for -- nullary constructors. instrUnwrapUnsafe :: forall dt name st. InstrUnwrapC dt name => Label name -> Instr (ToT dt : st) (ToT (CtorOnlyField name dt) : st) -- | Try to unwrap a constructor with the given name. hsUnwrap :: forall dt name. InstrUnwrapC dt name => Label name -> dt -> Maybe (CtorOnlyField name dt) -- | Constraint for instrConstruct. type InstrConstructC dt = (IsoValue dt, Generic dt, GInstrConstruct (Rep dt), GValueType (Rep dt) ~ ToT dt) -- | Types of all fields in a datatype. type ConstructorFieldTypes dt = GFieldTypes (Rep dt) -- | Way to construct one of the fields in a complex datatype. newtype FieldConstructor (st :: [k]) (field :: Type) FieldConstructor :: Instr (ToTs' st) (ToT field : ToTs' st) -> FieldConstructor -- | Constraint for instrSetField. type InstrSetFieldC dt name = (IsoValue dt, Generic dt, GInstrSetField name (Rep dt) (LnrBranch (GetNamed name dt)) (LnrFieldType (GetNamed name dt)), GValueType (Rep dt) ~ ToT dt) -- | Constraint for instrGetField. type InstrGetFieldC dt name = (IsoValue dt, Generic dt, GInstrGet name (Rep dt) (LnrBranch (GetNamed name dt)) (LnrFieldType (GetNamed name dt)), GValueType (Rep dt) ~ ToT dt) -- | Get type of field by datatype it is contained in and field name. type GetFieldType dt name = LnrFieldType (GetNamed name dt) -- | Make an instruction which accesses given field of the given datatype. instrGetField :: forall dt name st. InstrGetFieldC dt name => Label name -> Instr (ToT dt : st) (ToT (GetFieldType dt name) : st) -- | For given complex type dt and its field fieldTy -- update the field value. instrSetField :: forall dt name st. InstrSetFieldC dt name => Label name -> Instr (ToT (GetFieldType dt name) : (ToT dt : st)) (ToT dt : st) -- | For given complex type dt and its field fieldTy -- update the field value. instrConstruct :: forall dt st. InstrConstructC dt => Rec (FieldConstructor st) (ConstructorFieldTypes dt) -> Instr st (ToT dt : st) -- | Constraint for hsDecompose and hsCompose. type LooseSumC dt = (Generic dt, GLooseSum (Rep dt)) -- | Possible outcomes of an attempt to construct a Haskell ADT value from -- constructor name and relevant data. data ComposeResult a -- | Composed fine. ComposeOk :: a -> ComposeResult a -- | No constructor with such name. ComposeCtorNotFound :: ComposeResult a -- | Found required constructor, but type of data does not correspond to -- provided one. ComposeFieldTypeMismatch :: TypeRep -> TypeRep -> ComposeResult a -- | Decompose Haskell type into constructor name and data it carries, -- converting the latter into Michelson Value. toTaggedVal :: LooseSumC dt => dt -> (Text, SomeValue) -- | Inverse to toTaggedVal. fromTaggedVal :: LooseSumC dt => (Text, SomeValue) -> ComposeResult dt -- | Constraint, required when deriving TypeHasDoc for polymorphic -- type with the least possible number of methods defined manually. type PolyTypeHasDocC ts = Each '[TypeHasDoc] ts -- | Generic traversal for automatic deriving of some methods in -- TypeHasDoc. class GTypeHasDoc (x :: Type -> Type) -- | Require this type to be homomorphic. class IsHomomorphic a -- | Require two types to be built from the same type constructor. -- -- E.g. HaveCommonTypeCtor (Maybe Integer) (Maybe Natural) is -- defined, while HaveCmmonTypeCtor (Maybe Integer) [Integer] is -- not. class HaveCommonTypeCtor a b -- | Doc element with description of a type. data DType [DType] :: TypeHasDoc a => Proxy a -> DType -- | Data hides some type implementing TypeHasDoc. data SomeTypeWithDoc [SomeTypeWithDoc] :: TypeHasDoc td => Proxy td -> SomeTypeWithDoc -- | Signature of typeDocMichelsonRep function. -- -- As in TypeDocHaskellRep, set the first element of the pair to -- Nothing for primitive types, otherwise it stands as some -- instantiation of a type, and its Michelson representation is given in -- the second element of the pair. -- -- Examples of rendered representation: * pair int nat - for -- homomorphic type. * MyError Integer = pair string int - -- concrete sample for polymorhpic type. type TypeDocMichelsonRep a = Proxy a -> (Maybe DocTypeRepLHS, T) -- | Signature of typeDocHaskellRep function. -- -- When value is Just, it contains types which this type is built -- from. -- -- First element of provided pair may contain name a concrete type which -- has the same type constructor as a (or just a for -- homomorphic types), and the second element of the pair - its unfolding -- in Haskell. -- -- For example, for some newtype MyNewtype = MyNewtype (Integer, -- Natural) we would not specify the first element in the pair -- because MyNewtype is already a concrete type, and second -- element would contain (Integer, Natural). For polymorhpic -- types like newtype MyPolyNewtype a = MyPolyNewtype (Text, a), -- we want to describe its representation on some example of a, -- because working with type variables is too non-trivial; so the first -- element of the pair may be e.g. "MyPolyNewType Integer", and -- the second one shows that it unfolds to (Text, Integer). -- -- When rendered, values of this type look like: * (Integer, -- Natural) - for homomorphic type. * MyError Integer = (Text, -- Integer) - concrete sample for polymorhpic type. type TypeDocHaskellRep a = Proxy a -> Maybe (Maybe DocTypeRepLHS, ADTRep SomeTypeWithDoc) -- | Description for a Haskell type appearing in documentation. class Typeable a => TypeHasDoc a -- | Name of type as it appears in definitions section. -- -- Each type must have its own unique name because it will be used in -- identifier for references. -- -- Default definition derives name from Generics. If it does not fit, -- consider defining this function manually. (We tried using Data -- for this, but it produces names including module names which is not do -- we want). typeDocName :: TypeHasDoc a => Proxy a -> Text -- | Name of type as it appears in definitions section. -- -- Each type must have its own unique name because it will be used in -- identifier for references. -- -- Default definition derives name from Generics. If it does not fit, -- consider defining this function manually. (We tried using Data -- for this, but it produces names including module names which is not do -- we want). typeDocName :: (TypeHasDoc a, Generic a, KnownSymbol (GenericTypeName a)) => Proxy a -> Text -- | Explanation of a type. Markdown formatting is allowed. typeDocMdDescription :: TypeHasDoc a => Markdown -- | How reference to this type is rendered, in Markdown. -- -- Examples: * Integer, * Maybe -- (). -- -- Consider using one of the following functions as default -- implementation; which one to use depends on number of type arguments -- in your type: * homomorphicTypeDocMdReference * -- poly1TypeDocMdReference * poly2TypeDocMdReference -- -- If none of them fits your purposes precisely, consider using -- customTypeDocMdReference. typeDocMdReference :: TypeHasDoc a => Proxy a -> WithinParens -> Markdown -- | How reference to this type is rendered, in Markdown. -- -- Examples: * Integer, * Maybe -- (). -- -- Consider using one of the following functions as default -- implementation; which one to use depends on number of type arguments -- in your type: * homomorphicTypeDocMdReference * -- poly1TypeDocMdReference * poly2TypeDocMdReference -- -- If none of them fits your purposes precisely, consider using -- customTypeDocMdReference. typeDocMdReference :: (TypeHasDoc a, Typeable a, IsHomomorphic a) => Proxy a -> WithinParens -> Markdown -- | All types which this type directly contains. -- -- Used in automatic types discovery. typeDocDependencies :: TypeHasDoc a => Proxy a -> [SomeTypeWithDoc] -- | All types which this type directly contains. -- -- Used in automatic types discovery. typeDocDependencies :: (TypeHasDoc a, Generic a, GTypeHasDoc (Rep a)) => Proxy a -> [SomeTypeWithDoc] -- | For complex types - their immediate Haskell representation. -- -- For primitive types set this to Nothing. -- -- For homomorphic types use homomorphicTypeDocHaskellRep -- implementation. -- -- For polymorhpic types consider using concreteTypeDocHaskellRep -- as implementation. -- -- Modifier haskellRepNoFields can be used to hide names of -- fields, beneficial for newtypes. -- -- Another modifier called haskellRepStripFieldPrefix can be used -- for datatypes to leave only meaningful part of name in every field. typeDocHaskellRep :: TypeHasDoc a => TypeDocHaskellRep a -- | For complex types - their immediate Haskell representation. -- -- For primitive types set this to Nothing. -- -- For homomorphic types use homomorphicTypeDocHaskellRep -- implementation. -- -- For polymorhpic types consider using concreteTypeDocHaskellRep -- as implementation. -- -- Modifier haskellRepNoFields can be used to hide names of -- fields, beneficial for newtypes. -- -- Another modifier called haskellRepStripFieldPrefix can be used -- for datatypes to leave only meaningful part of name in every field. typeDocHaskellRep :: (TypeHasDoc a, Generic a, GTypeHasDoc (Rep a), IsHomomorphic a) => TypeDocHaskellRep a -- | Final michelson representation of a type. -- -- For homomorphic types use homomorphicTypeDocMichelsonRep -- implementation. -- -- For polymorhpic types consider using -- concreteTypeDocMichelsonRep as implementation. typeDocMichelsonRep :: TypeHasDoc a => TypeDocMichelsonRep a -- | Final michelson representation of a type. -- -- For homomorphic types use homomorphicTypeDocMichelsonRep -- implementation. -- -- For polymorhpic types consider using -- concreteTypeDocMichelsonRep as implementation. typeDocMichelsonRep :: (TypeHasDoc a, SingI (ToT a), IsHomomorphic a) => TypeDocMichelsonRep a -- | Whether given text should be rendered grouped in parentheses (if they -- make sense). newtype WithinParens WithinParens :: Bool -> WithinParens -- | Stands for representation of some Haskell ADT corresponding to -- Michelson value. Type parameter a is what you put in place of -- each field of the datatype, e.g. information about field type. -- -- Outer list layer corresponds to union, and the inner one corresponds -- to products within constructors. Constructors and fields names are -- present. type ADTRep a = NonEmpty (Text, [(Maybe Text, a)]) -- | Show given ADTRep in a neat way. buildADTRep :: forall a. (WithinParens -> a -> Markdown) -> ADTRep a -> Markdown applyWithinParens :: WithinParens -> Markdown -> Markdown -- | Like typeDocDependencies but returns values of more common type -- which is used in docItemDependencies. typeDocDependencies' :: TypeHasDoc a => Proxy a -> [SomeDocDefinitionItem] -- | Render a reference to a type which consists of type constructor (you -- have to provide name of this type constructor and documentation for -- the whole type) and zero or more type arguments. customTypeDocMdReference :: (Text, DType) -> [DType] -> WithinParens -> Markdown -- | Derive typeDocMdReference, for homomorphic types only. homomorphicTypeDocMdReference :: forall (t :: Type). (Typeable t, TypeHasDoc t, IsHomomorphic t) => Proxy t -> WithinParens -> Markdown -- | Derive typeDocMdReference, for polymorphic type with one type -- argument, like Maybe Integer. poly1TypeDocMdReference :: forall t (r :: Type) (a :: Type). (r ~ t a, Typeable t, Each '[TypeHasDoc] [r, a], IsHomomorphic t) => Proxy r -> WithinParens -> Markdown -- | Derive typeDocMdReference, for polymorphic type with two type -- arguments, like Lambda Integer Natural. poly2TypeDocMdReference :: forall t (r :: Type) (a :: Type) (b :: Type). (r ~ t a b, Typeable t, Each '[TypeHasDoc] [r, a, b], IsHomomorphic t) => Proxy r -> WithinParens -> Markdown -- | Implement typeDocDependencies via getting all immediate fields -- of a datatype. -- -- Note: this will not include phantom types, I'm not sure yet how this -- scenario should be handled (@martoon). genericTypeDocDependencies :: forall a. (Generic a, GTypeHasDoc (Rep a)) => Proxy a -> [SomeTypeWithDoc] -- | Implement typeDocHaskellRep for a homomorphic type. -- -- Note that it does not require your type to be of IsHomomorphic -- instance, which can be useful for some polymorhpic types which, for -- documentation purposes, we want to consider homomorphic. Example: -- Operation is in fact polymorhpic, but we don't want this fact -- to be reflected in the documentation. homomorphicTypeDocHaskellRep :: forall a. (Generic a, GTypeHasDoc (Rep a)) => TypeDocHaskellRep a -- | Implement typeDocHaskellRep on example of given concrete type. -- -- This is a best effort attempt to implement typeDocHaskellRep -- for polymorhpic types, as soon as there is no simple way to preserve -- type variables when automatically deriving Haskell representation of a -- type. concreteTypeDocHaskellRep :: forall a b. (Typeable a, IsoValue a, Generic a, GTypeHasDoc (Rep a), HaveCommonTypeCtor b a) => TypeDocHaskellRep b -- | Version of concreteTypeDocHaskellRep which does not ensure -- whether the type for which representation is built is any similar to -- the original type which you implement a TypeHasDoc instance -- for. concreteTypeDocHaskellRepUnsafe :: forall a b. (Typeable a, IsoValue a, Generic a, GTypeHasDoc (Rep a)) => TypeDocHaskellRep b -- | Erase fields from Haskell datatype representation. -- -- Use this when rendering fields names is undesired. haskellRepNoFields :: TypeDocHaskellRep a -> TypeDocHaskellRep a -- | Cut fields prefixes which we use according to the style guide. -- -- E.g. cmMyField field will be transformed to myField. haskellRepStripFieldPrefix :: HasCallStack => TypeDocHaskellRep a -> TypeDocHaskellRep a -- | Implement typeDocMichelsonRep for homomorphic type. homomorphicTypeDocMichelsonRep :: forall a. SingI (ToT a) => TypeDocMichelsonRep a -- | Implement typeDocMichelsonRep on example of given concrete -- type. -- -- This function exists for the same reason as -- concreteTypeDocHaskellRep. concreteTypeDocMichelsonRep :: forall a b. (Typeable a, SingI (ToT a), HaveCommonTypeCtor b a) => TypeDocMichelsonRep b -- | Version of concreteTypeDocHaskellRepUnsafe which does not -- ensure whether the type for which representation is built is any -- similar to the original type which you implement a TypeHasDoc -- instance for. concreteTypeDocMichelsonRepUnsafe :: forall a b. (Typeable a, SingI (ToT a)) => TypeDocMichelsonRep b -- | Extracting documentation from instructions set. module Michelson.Typed.Doc -- | Assemble contract documentation. buildInstrDoc :: Instr inp out -> ContractDoc -- | Recursevly traverse an instruction and modify documentation items -- matching given type. modifyInstrDoc :: DocItem i => (i -> i) -> Instr inp out -> Instr inp out -- | Leave only instructions related to documentation. -- -- Generated documentation for resulting instruction remains the same, -- but semantics of instruction itself gets lost. We have to pass -- optimizer here as an argument to avoid cyclic dependencies. cutInstrNonDoc :: (forall i o. Instr i o -> Instr i o) -> Instr inp out -> Instr s s module Michelson.Typed module Michelson.TypeCheck.Types -- | Data type holding type information for stack (Heterogeneous Stack -- Type). -- -- This data type is used along with instruction data type Instr -- to carry information about its input and output stack types. -- -- That is, if there is value instr :: Instr inp out, along with -- this instr one may carry inpHST :: HST inp and -- outHST :: HST out which will contain whole information about -- input and output stack types for instr. -- -- Data type HST is very similar to Data.Vinyl.Rec, but -- is specialized for a particular purpose. In particular, definition of -- HST (t1 ': t2 ': ... tn ': '[]) requires constraints -- (Typeable t1, Typeable t2, ..., Typeable tn) as well as -- constraints (Typeable '[ t1 ], Typeable '[ t1, t2 ], ...). -- These applications of Typeable class are required for -- convenient usage of type encoded by HST ts with some -- functions from Data.Typeable. -- -- Data type HST (Heterogeneous Stack Type) is a heterogenuous -- list of triples. First element of triple is a type singleton which is -- due to main motivation behind HST, namely for it to be used -- as representation of Instr type data for pattern-matching. -- Second element of triple is a structure, holding field and type -- annotations for a given type. Third element of triple is an optional -- variable annotation for the stack element. data HST (ts :: [T]) [SNil] :: HST '[] [::&] :: (Typeable xs, Typeable x, SingI x) => (Sing x, Notes x, VarAnn) -> HST xs -> HST (x : xs) infixr 7 ::& -- | Append a type to HST, assuming that notes and annotations for -- this type are unknown. (-:&) :: (Typeable xs, Typeable x, SingI x) => Sing x -> HST xs -> HST (x : xs) infixr 7 -:& -- | No-argument type wrapper for HST data type. data SomeHST [SomeHST] :: Typeable ts => HST ts -> SomeHST -- | This data type keeps part of type check result - instruction and -- corresponding output stack. data SomeInstrOut inp -- | Type-check result with concrete output stack, most common case. -- -- Output stack type is wrapped inside the type and Typeable -- constraint is provided to allow convenient unwrapping. [:::] :: Typeable out => Instr inp out -> HST out -> SomeInstrOut inp -- | Type-check result which matches against arbitrary output stack. -- Information about annotations in the output stack is absent. -- -- This case is only possible when the corresponding code terminates with -- FAILWITH instruction in all possible executions. The opposite -- may be not true though (example: you push always-failing lambda and -- immediatelly execute it - stack type is known). [AnyOutInstr] :: (forall out. Instr inp out) -> SomeInstrOut inp infix 9 ::: -- | Data type keeping the whole type check result: instruction and type -- representations of instruction's input and output. data SomeInstr inp [:/] :: HST inp -> SomeInstrOut inp -> SomeInstr inp infix 8 :/ -- | Data type, holding strictly-typed Michelson value along with its type -- singleton. data SomeNotedValue [::::] :: (SingI t, Typeable t) => Value t -> (Sing t, Notes t) -> SomeNotedValue data SomeContract [SomeContract] :: FullContract cp st -> SomeContract -- | Data type, holding strictly-typed Michelson value along with its type -- singleton. data SomeCValue [:--:] :: (SingI t, Typeable t) => CValue t -> Sing t -> SomeCValue -- | Datatype used in typeCheckStorageOrParameter instead of -- simple Bool for more convenience. data StorageOrParameter Storage :: StorageOrParameter Parameter :: StorageOrParameter -- | Set of variables defined in a let-block. data BoundVars BoundVars :: Map Var Type -> Maybe SomeHST -> BoundVars -- | State for type checking nop type TcExtFrames = [BoundVars] mapSomeContract :: (forall inp out. Instr inp out -> Instr inp out) -> SomeContract -> SomeContract noBoundVars :: BoundVars instance GHC.Classes.Eq Michelson.TypeCheck.Types.StorageOrParameter instance GHC.Show.Show Michelson.TypeCheck.Types.SomeHST instance GHC.Show.Show Michelson.TypeCheck.Types.SomeContract instance GHC.Show.Show Michelson.TypeCheck.Types.SomeNotedValue instance GHC.Show.Show (Michelson.Typed.Instr.ExtInstr inp) => GHC.Show.Show (Michelson.TypeCheck.Types.SomeInstr inp) instance GHC.Show.Show (Michelson.Typed.Instr.ExtInstr inp) => GHC.Show.Show (Michelson.TypeCheck.Types.SomeInstrOut inp) instance GHC.Classes.Eq Michelson.TypeCheck.Types.SomeHST instance GHC.Show.Show (Michelson.TypeCheck.Types.HST ts) instance GHC.Classes.Eq (Michelson.TypeCheck.Types.HST ts) -- | Errors that can occur when some code is being typechecked. module Michelson.TypeCheck.Error -- | Description of the instruction which wants more items on stack than -- currently present. data NotEnoughItemsInstr NotEnoughDrop :: NotEnoughItemsInstr NotEnoughDip :: NotEnoughItemsInstr NotEnoughDig :: NotEnoughItemsInstr NotEnoughDug :: NotEnoughItemsInstr -- | Data type that represents various errors which are related to type -- system. These errors are used to specify info about type check errors -- in TCError data type. data TCTypeError -- | Annotation unify error AnnError :: AnnConvergeError -> TCTypeError -- | Type equality error TypeEqError :: T -> T -> TCTypeError -- | Stacks equality error StackEqError :: [T] -> [T] -> TCTypeError -- | Error that happens when type cannot be used in the corresponding -- scope. Argument of this constructor carries types which, in the -- aggregate, violate the restriction (e.g. timestamp and -- timestamp passed to MUL instruction). UnsupportedTypes :: [T] -> TCTypeError -- | Error that happens when a Value is never a valid source for -- this type (e.g. timestamp cannot be obtained from a -- ValueTrue) InvalidValueType :: T -> TCTypeError -- | There are not enough items on stack to perform a certain instruction. NotEnoughItemsOnStack :: !Word -> !NotEnoughItemsInstr -> TCTypeError -- | Invalid entrypoint name provided IllegalEntryPoint :: EpNameFromRefAnnError -> TCTypeError IllegalParamDecl :: ParamEpError -> TCTypeError -- | Natural numbers cannot be negative NegativeNat :: TCTypeError -- | Exceeds the maximal mutez value MutezOverflow :: TCTypeError -- | Address couldn't be parsed from its textual representation InvalidAddress :: ParseEpAddressError -> TCTypeError -- | KeyHash couldn't be parsed from its textual representation InvalidKeyHash :: CryptoParseError -> TCTypeError -- | Timestamp is not RFC339 compliant InvalidTimestamp :: TCTypeError -- | Type check error data TCError TCFailedOnInstr :: ExpandedInstr -> SomeHST -> Text -> InstrCallStack -> Maybe TCTypeError -> TCError TCFailedOnValue :: Value -> T -> Text -> InstrCallStack -> Maybe TCTypeError -> TCError TCContractError :: Text -> Maybe TCTypeError -> TCError TCUnreachableCode :: InstrCallStack -> NonEmpty ExpandedOp -> TCError TCExtError :: SomeHST -> InstrCallStack -> ExtError -> TCError -- | Various type errors possible when checking Morley extension commands data ExtError LengthMismatch :: StackTypePattern -> ExtError VarError :: Text -> StackFn -> ExtError TypeMismatch :: StackTypePattern -> Int -> TCTypeError -> ExtError TyVarMismatch :: Var -> Type -> StackTypePattern -> Int -> TCTypeError -> ExtError StkRestMismatch :: StackTypePattern -> SomeHST -> SomeHST -> TCTypeError -> ExtError TestAssertError :: Text -> ExtError InvalidStackReference :: StackRef -> StackSize -> ExtError newtype StackSize StackSize :: Natural -> StackSize instance GHC.Classes.Eq Michelson.TypeCheck.Error.TCError instance GHC.Classes.Eq Michelson.TypeCheck.Error.ExtError instance GHC.Classes.Eq Michelson.TypeCheck.Error.StackSize instance GHC.Show.Show Michelson.TypeCheck.Error.StackSize instance GHC.Classes.Eq Michelson.TypeCheck.Error.TCTypeError instance GHC.Show.Show Michelson.TypeCheck.Error.TCTypeError instance GHC.Classes.Eq Michelson.TypeCheck.Error.NotEnoughItemsInstr instance GHC.Show.Show Michelson.TypeCheck.Error.NotEnoughItemsInstr instance Formatting.Buildable.Buildable Michelson.TypeCheck.Error.TCError instance Formatting.Buildable.Buildable Michelson.Untyped.Instr.ExpandedInstr => GHC.Show.Show Michelson.TypeCheck.Error.TCError instance Formatting.Buildable.Buildable Michelson.Untyped.Instr.ExpandedInstr => GHC.Exception.Type.Exception Michelson.TypeCheck.Error.TCError instance Formatting.Buildable.Buildable Michelson.TypeCheck.Error.ExtError instance Formatting.Buildable.Buildable Michelson.TypeCheck.Error.TCTypeError instance Formatting.Buildable.Buildable Michelson.TypeCheck.Error.NotEnoughItemsInstr module Michelson.TypeCheck.TypeCheck type TcInstrHandler = forall inp. Typeable inp => ExpandedInstr -> HST inp -> TypeCheckInstr (SomeInstr inp) type TcOriginatedContracts = Map ContractHash Type type TcResult inp = Either TCError (SomeInstr inp) -- | The typechecking state data TypeCheckEnv TypeCheckEnv :: TcExtFrames -> Type -> TcOriginatedContracts -> TypeCheckEnv [tcExtFrames] :: TypeCheckEnv -> TcExtFrames [tcContractParam] :: TypeCheckEnv -> Type [tcContracts] :: TypeCheckEnv -> TcOriginatedContracts type TypeCheck a = ExceptT TCError (State TypeCheckEnv) a runTypeCheck :: Type -> TcOriginatedContracts -> TypeCheck a -> Either TCError a type TypeCheckInstr a = ReaderT InstrCallStack (ExceptT TCError (State TypeCheckEnv)) a -- | Run type checker as if it worked isolated from other world - no access -- to environment of the current contract is allowed. -- -- Use this function for test purposes only or for some utilities when -- environment does not matter. In particular, it is assumed that -- whatever we typecheck does not depend on the parameter type of the -- contract which is being typechecked (because there is no contract that -- we are typechecking). runTypeCheckIsolated :: TypeCheck a -> Either TCError a -- | Run TypeCheckInstr and modify thrown errors using given -- functions. mapTCError :: (TCError -> TCError) -> TypeCheckInstr a -> TypeCheckInstr a tcContractParamL :: Lens' TypeCheckEnv Type tcContractsL :: Lens' TypeCheckEnv TcOriginatedContracts tcExtFramesL :: Lens' TypeCheckEnv TcExtFrames module Michelson.TypeCheck.Helpers onLeft :: Either a c -> (a -> b) -> Either b c -- | Function which derives special annotations for CDR / CAR instructions. deriveSpecialVN :: VarAnn -> FieldAnn -> VarAnn -> VarAnn -- | Function which derives special annotations for PAIR instruction. -- -- Namely, it does following transformation: PAIR % -- % [ p.a int : p.b int : .. ] ~ [ p -- (pair (int %a) (int %b) : .. ] -- -- All relevant cases (e.g. PAIR %myf % ) are handled -- as they should be according to spec. deriveSpecialFNs :: FieldAnn -> FieldAnn -> VarAnn -> VarAnn -> (VarAnn, FieldAnn, FieldAnn) -- | Append suffix to variable annotation (if it's not empty) deriveVN :: VarAnn -> VarAnn -> VarAnn -- | Function which extracts annotations for or type (for left and -- right parts). -- -- It extracts field/type annotations and also auto-generates variable -- annotations if variable annotation is not provided as second argument. deriveNsOr :: Notes ( 'TOr a b) -> VarAnn -> (Notes a, Notes b, VarAnn, VarAnn) -- | Function which extracts annotations for option t type. -- -- It extracts field/type annotations and also auto-generates variable -- annotation for Some case if it is not provided as second -- argument. deriveNsOption :: Notes ( 'TOption a) -> VarAnn -> (Notes a, VarAnn) convergeHSTEl :: (Sing t, Notes t, VarAnn) -> (Sing t, Notes t, VarAnn) -> Either AnnConvergeError (Sing t, Notes t, VarAnn) -- | Combine annotations from two given stack types convergeHST :: HST ts -> HST ts -> Either AnnConvergeError (HST ts) -- | Extract singleton for each single type of the given stack. hstToTs :: HST st -> [T] -- | Check whether the given stack types are equal. eqHST :: forall as bs. (Typeable as, Typeable bs) => HST as -> HST bs -> Either TCTypeError (as :~: bs) -- | Check whether the given stack has size 1 and its only element matches -- the given type. This function is a specialized version of -- eqHST. eqHST1 :: forall t st. (Typeable st, Typeable t, SingI t) => HST st -> Either TCTypeError (st :~: '[t]) lengthHST :: HST xs -> Natural -- | Check whether elements go in strictly ascending order and return the -- original list (to keep only one pass on the original list). ensureDistinctAsc :: (Ord b, Show a) => (a -> b) -> [a] -> Either Text [a] -- | Function eqType is a simple wrapper around -- Data.Typeable.eqT suited for use within Either -- TCTypeError a applicative. eqType :: forall (a :: T) (b :: T). Each [Typeable, SingI] [a, b] => Either TCTypeError (a :~: b) checkEqT :: forall (a :: T) (b :: T) ts m. (Each [Typeable, SingI] [a, b], Typeable ts, MonadReader InstrCallStack m, MonadError TCError m) => ExpandedInstr -> HST ts -> Text -> m (a :~: b) checkEqHST :: forall (a :: [T]) (b :: [T]) ts m. (Typeable a, Typeable b, Typeable ts, MonadReader InstrCallStack m, MonadError TCError m) => HST a -> HST b -> ExpandedInstr -> HST ts -> Text -> m (a :~: b) onTypeCheckInstrAnnErr :: (MonadReader InstrCallStack m, MonadError TCError m, Typeable ts) => ExpandedInstr -> HST ts -> Text -> Either AnnConvergeError a -> m a onTypeCheckInstrErr :: (MonadReader InstrCallStack m, MonadError TCError m) => ExpandedInstr -> SomeHST -> Text -> Either TCTypeError a -> m a typeCheckInstrErr :: (MonadReader InstrCallStack m, MonadError TCError m) => ExpandedInstr -> SomeHST -> Text -> m a typeCheckImpl :: forall inp. Typeable inp => TcInstrHandler -> [ExpandedOp] -> HST inp -> TypeCheckInstr (SomeInstr inp) -- | Check whether typed and untyped types converge compareTypes :: forall t. (Typeable t, SingI t) => (Sing t, Notes t) -> Type -> Either TCTypeError () -- | Generic implementation for MEMeration memImpl :: forall (q :: CT) (c :: T) ts inp m. (MonadReader InstrCallStack m, MonadError TCError m, Typeable ts, Typeable (MemOpKey c), SingI (MemOpKey c), MemOp c, inp ~ ( 'Tc q : (c : ts))) => ExpandedInstr -> HST inp -> VarAnn -> m (SomeInstr inp) getImpl :: forall c getKey rs inp m. (GetOp c, Typeable (GetOpKey c), Typeable (GetOpVal c), SingI (GetOpVal c), SingI (GetOpKey c), inp ~ (getKey : (c : rs)), MonadReader InstrCallStack m, MonadError TCError m) => ExpandedInstr -> HST (getKey : (c : rs)) -> Sing (GetOpVal c) -> Notes (GetOpVal c) -> VarAnn -> m (SomeInstr inp) updImpl :: forall c updKey updParams rs inp m. (UpdOp c, Typeable (UpdOpKey c), SingI (UpdOpKey c), Typeable (UpdOpParams c), SingI (UpdOpParams c), inp ~ (updKey : (updParams : (c : rs))), MonadReader InstrCallStack m, MonadError TCError m) => ExpandedInstr -> HST (updKey : (updParams : (c : rs))) -> VarAnn -> m (SomeInstr inp) sliceImpl :: (SliceOp c, Typeable c, inp ~ ( 'Tc 'CNat : ( 'Tc 'CNat : (c : rs))), Monad m) => HST inp -> VarAnn -> m (SomeInstr inp) concatImpl :: (ConcatOp c, Typeable c, inp ~ (c : (c : rs)), MonadReader InstrCallStack m, MonadError TCError m) => HST inp -> VarAnn -> m (SomeInstr inp) concatImpl' :: (ConcatOp c, Typeable c, inp ~ ( 'TList c : rs), Monad m) => HST inp -> VarAnn -> m (SomeInstr inp) sizeImpl :: (SizeOp c, inp ~ (c : rs), Monad m) => HST inp -> VarAnn -> m (SomeInstr inp) -- | Helper function to construct instructions for binary arithmetic -- operations. arithImpl :: (Typeable (ArithRes aop n m), SingI (ArithRes aop n m), Typeable ( 'Tc (ArithRes aop n m) : s), inp ~ ( 'Tc n : ( 'Tc m : s)), Monad t) => Instr inp ( 'Tc (ArithRes aop n m) : s) -> HST inp -> VarAnn -> t (SomeInstr inp) addImpl :: forall a b inp rs m. (Typeable rs, Each [Typeable, SingI] [a, b], inp ~ ( 'Tc a : ( 'Tc b : rs)), MonadReader InstrCallStack m, MonadError TCError m) => Sing a -> Sing b -> HST inp -> VarAnn -> m (SomeInstr inp) subImpl :: forall a b inp rs m. (Typeable rs, Each [Typeable, SingI] [a, b], inp ~ ( 'Tc a : ( 'Tc b : rs)), MonadReader InstrCallStack m, MonadError TCError m) => Sing a -> Sing b -> HST inp -> VarAnn -> m (SomeInstr inp) mulImpl :: forall a b inp rs m. (Typeable rs, Each [Typeable, SingI] [a, b], inp ~ ( 'Tc a : ( 'Tc b : rs)), MonadReader InstrCallStack m, MonadError TCError m) => Sing a -> Sing b -> HST inp -> VarAnn -> m (SomeInstr inp) edivImpl :: forall a b inp rs m. (Typeable rs, Each [Typeable, SingI] [a, b], inp ~ ( 'Tc a : ( 'Tc b : rs)), MonadReader InstrCallStack m, MonadError TCError m) => Sing a -> Sing b -> HST inp -> VarAnn -> m (SomeInstr inp) compareImpl :: forall a inp rs m. (Typeable rs, With [Typeable, SingI] a, inp ~ ( 'Tc a : ( 'Tc a : rs)), MonadReader InstrCallStack m) => Sing a -> HST inp -> VarAnn -> m (SomeInstr inp) -- | Helper function to construct instructions for binary arithmetic -- operations. unaryArithImpl :: (Typeable (UnaryArithRes aop n), SingI (UnaryArithRes aop n), Typeable ( 'Tc (UnaryArithRes aop n) : s), inp ~ ( 'Tc n : s), Monad t) => Instr inp ( 'Tc (UnaryArithRes aop n) : s) -> HST inp -> VarAnn -> t (SomeInstr inp) module Michelson.TypeCheck.Value -- | Function typeCheckValImpl converts a single Michelson value -- given in representation from Michelson.Type module to -- representation in strictly typed GADT. -- -- As a third argument, typeCheckValImpl accepts expected type -- of value. -- -- Type checking algorithm pattern-matches on parse value representation, -- expected type t and constructs Val t value. -- -- If there was no match on a given pair of value and expected type, that -- is interpreted as input of wrong type and type check finishes with -- error. typeCheckValImpl :: TcInstrHandler -> Value -> (Sing t, Notes t) -> TypeCheckInstr SomeNotedValue typeCheckCValue :: Value' op -> CT -> Either (Value' op, TCTypeError) SomeCValue -- | Type-checking of Morley extension. module Michelson.TypeCheck.Ext typeCheckExt :: forall s. Typeable s => TypeCheckListHandler s -> ExpandedExtInstr -> HST s -> TypeCheckInstr (SomeInstr s) -- | Module, providing functions for conversion from instruction and value -- representation from Michelson.Type module to strictly-typed -- GADT-based representation from Michelson.Value module. -- -- This conversion is labeled as type check because that's what we are -- obliged to do on our way. -- -- Type check algorithm relies on the property of Michelson language that -- each instruction on a given input stack type produces a definite -- output stack type. Michelson contract defines concrete types for -- storage and parameter, from which input stack type is deduced. Then -- this type is being combined with each subsequent instruction, -- producing next stack type after each application. -- -- Function typeCheck takes list of instructions and returns -- value of type Instr inp out along with HST inp and -- HST out all wrapped into SomeInstr data type. This -- wrapping is done to satsify Haskell type system (which has no support -- for dependent types). Functions typeCheckInstr, -- typeCheckValue behave similarly. -- -- When a recursive call is made within typeCheck, -- typeCheckInstr or typeCheckValue, result of a call -- is unwrapped from SomeInstr and type information from HST -- inp and HST out is being used to assert that recursive -- call returned instruction of expected type (error is thrown -- otherwise). module Michelson.TypeCheck.Instr typeCheckContract :: TcOriginatedContracts -> Contract -> Either TCError SomeContract -- | Function typeCheckValue converts a single Michelson value -- given in representation from Michelson.Untyped module -- hierarchy to representation in strictly typed GADT. -- -- As a second argument, typeCheckValue accepts expected type of -- value. -- -- Type checking algorithm pattern-matches on parse value representation, -- expected type t and constructs Val t value. -- -- If there was no match on a given pair of value and expected type, that -- is interpreted as input of wrong type and type check finishes with -- error. typeCheckValue :: Value -> (Sing t, Notes t) -> TypeCheckInstr SomeNotedValue -- | Like typeCheckValue, but returns value of a desired type. typeVerifyValue :: forall t. (Typeable t, SingI t) => Value -> TypeCheckInstr (Value t) -- | Function typeCheckList converts list of Michelson -- instructions given in representation from Michelson.Type -- module to representation in strictly typed GADT. -- -- Types are checked along the way which is neccessary to construct a -- strictly typed value. -- -- As a second argument, typeCheckList accepts input stack type -- representation. typeCheckList :: Typeable inp => [ExpandedOp] -> HST inp -> TypeCheck (SomeInstr inp) typeCheckStorageOrParameter :: StorageOrParameter -> Value -> TcOriginatedContracts -> Contract -> Either TCError SomeValue -- | Datatype used in typeCheckStorageOrParameter instead of -- simple Bool for more convenience. data StorageOrParameter Storage :: StorageOrParameter Parameter :: StorageOrParameter module Michelson.TypeCheck typeCheckContract :: TcOriginatedContracts -> Contract -> Either TCError SomeContract typeCheckStorageOrParameter :: StorageOrParameter -> Value -> TcOriginatedContracts -> Contract -> Either TCError SomeValue -- | Function typeCheckValue converts a single Michelson value -- given in representation from Michelson.Untyped module -- hierarchy to representation in strictly typed GADT. -- -- As a second argument, typeCheckValue accepts expected type of -- value. -- -- Type checking algorithm pattern-matches on parse value representation, -- expected type t and constructs Val t value. -- -- If there was no match on a given pair of value and expected type, that -- is interpreted as input of wrong type and type check finishes with -- error. typeCheckValue :: Value -> (Sing t, Notes t) -> TypeCheckInstr SomeNotedValue -- | Like typeCheckValue, but returns value of a desired type. typeVerifyValue :: forall t. (Typeable t, SingI t) => Value -> TypeCheckInstr (Value t) -- | Function typeCheckList converts list of Michelson -- instructions given in representation from Michelson.Type -- module to representation in strictly typed GADT. -- -- Types are checked along the way which is neccessary to construct a -- strictly typed value. -- -- As a second argument, typeCheckList accepts input stack type -- representation. typeCheckList :: Typeable inp => [ExpandedOp] -> HST inp -> TypeCheck (SomeInstr inp) typeCheckCValue :: Value' op -> CT -> Either (Value' op, TCTypeError) SomeCValue typeCheckExt :: forall s. Typeable s => TypeCheckListHandler s -> ExpandedExtInstr -> HST s -> TypeCheckInstr (SomeInstr s) -- | Function eqType is a simple wrapper around -- Data.Typeable.eqT suited for use within Either -- TCTypeError a applicative. eqType :: forall (a :: T) (b :: T). Each [Typeable, SingI] [a, b] => Either TCTypeError (a :~: b) -- | Check whether typed and untyped types converge compareTypes :: forall t. (Typeable t, SingI t) => (Sing t, Notes t) -> Type -> Either TCTypeError () -- | Utilities for arbitrary data generation in property tests. module Michelson.Test.Gen -- | Minimal (earliest) timestamp used for Arbitrary (CValue -- 'CTimestamp) minTimestamp :: Timestamp -- | Maximal (latest) timestamp used for Arbitrary (CValue -- 'CTimestamp) maxTimestamp :: Timestamp -- | Median of minTimestamp and maxTimestamp. Useful for -- testing (exactly half of generated dates will be before and after this -- date). midTimestamp :: Timestamp instance Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.CValue.CValue 'Michelson.Untyped.Type.CKeyHash) instance Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.CValue.CValue 'Michelson.Untyped.Type.CMutez) instance Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.CValue.CValue 'Michelson.Untyped.Type.CInt) instance Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.CValue.CValue a) => Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.Value.Value' instr ('Michelson.Typed.T.Tc a)) instance Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.Value.Value' instr a) => Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.Value.Value' instr ('Michelson.Typed.T.TList a)) instance Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.Value.Value' instr 'Michelson.Typed.T.TUnit) instance (Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.Value.Value' instr a), Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.Value.Value' instr b)) => Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.Value.Value' instr ('Michelson.Typed.T.TPair a b)) instance Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Typed.CValue.CValue 'Michelson.Untyped.Type.CTimestamp) instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Core.Mutez instance Test.QuickCheck.Arbitrary.Arbitrary Tezos.Core.Timestamp -- | Global blockchain state (emulated). module Michelson.Runtime.GState -- | State of a contract with code. data ContractState ContractState :: !Mutez -> !Value -> !Contract -> !Maybe SomeContract -> !Maybe SomeValue -> ContractState -- | Amount of mutez owned by this contract. [csBalance] :: ContractState -> !Mutez -- | Storage value associated with this contract. [csStorage] :: ContractState -> !Value -- | Contract itself (untyped). [csContract] :: ContractState -> !Contract [csTypedContract] :: ContractState -> !Maybe SomeContract -- | We keep typed representation of contract code and storage in form, -- that hides their actual type in order to simplify the rest of the code -- (e.g. avoid type parameters for ContractState and so on). They -- are made optional in order to perform safe parsing from JSON (we -- simply return Nothing in this parser and use -- getTypedStorage or getTypedContract that optionally -- typecheck storage or contract code). [csTypedStorage] :: ContractState -> !Maybe SomeValue getTypedContract :: GState -> ContractState -> Either TCError SomeContract getTypedStorage :: GState -> ContractState -> Either TCError SomeValue -- | State of an arbitrary address. data AddressState -- | For contracts without code we store only its balance. ASSimple :: !Mutez -> AddressState -- | For contracts with code we store more state represented by -- ContractState. ASContract :: !ContractState -> AddressState -- | Extract balance from AddressState. asBalance :: AddressState -> Mutez -- | Persistent data passed to Morley contracts which can be updated as -- result of contract execution. data GState GState :: ChainId -> Map Address AddressState -> GState -- | Identifier of chain. [gsChainId] :: GState -> ChainId -- | All known addresses and their state. [gsAddresses] :: GState -> Map Address AddressState gsChainIdL :: Lens' GState ChainId gsAddressesL :: Lens' GState (Map Address AddressState) -- | Initially these addresses have a lot of money. genesisAddresses :: NonEmpty Address -- | KeyHash of genesis address. genesisKeyHashes :: NonEmpty KeyHash -- | One of genesis addresses. genesisAddress :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress1 :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress2 :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress3 :: Address genesisAddress4 :: Address genesisAddress5 :: Address genesisAddress6 :: Address -- | One of genesis key hashes. genesisKeyHash :: KeyHash -- | Initial GState. It's supposed to be used if no GState is -- provided. It puts plenty of money on each genesis address. initGState :: GState -- | Read GState from a file. readGState :: FilePath -> IO GState -- | Write GState to a file. writeGState :: FilePath -> GState -> IO () -- | Updates that can be applied to GState. data GStateUpdate GSAddAddress :: !Address -> !AddressState -> GStateUpdate GSSetStorageValue :: !Address -> !Value -> !SomeValue -> GStateUpdate GSSetBalance :: !Address -> !Mutez -> GStateUpdate data GStateUpdateError GStateAddressExists :: !Address -> GStateUpdateError GStateUnknownAddress :: !Address -> GStateUpdateError GStateNotContract :: !Address -> GStateUpdateError -- | Apply GStateUpdate to GState. applyUpdate :: GStateUpdate -> GState -> Either GStateUpdateError GState -- | Apply a list of GStateUpdates to GState. applyUpdates :: [GStateUpdate] -> GState -> Either GStateUpdateError GState -- | Retrive all contracts stored in GState extractAllContracts :: GState -> TcOriginatedContracts instance GHC.Show.Show Michelson.Runtime.GState.GStateUpdateError instance GHC.Show.Show Michelson.Runtime.GState.GStateUpdate instance GHC.Show.Show Michelson.Runtime.GState.GStateParseError instance Formatting.Buildable.Buildable Michelson.Runtime.GState.GStateUpdateError instance Formatting.Buildable.Buildable Michelson.Runtime.GState.GStateUpdate instance GHC.Exception.Type.Exception Michelson.Runtime.GState.GStateParseError instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Runtime.GState.GState instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Runtime.GState.GState instance GHC.Show.Show Michelson.Runtime.GState.GState instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Runtime.GState.AddressState instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Runtime.GState.AddressState instance GHC.Generics.Generic Michelson.Runtime.GState.AddressState instance GHC.Show.Show Michelson.Runtime.GState.AddressState instance GHC.Show.Show Michelson.Runtime.GState.ContractState instance Formatting.Buildable.Buildable Michelson.Runtime.GState.AddressState instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Runtime.GState.ContractState instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Runtime.GState.ContractState instance Formatting.Buildable.Buildable Michelson.Runtime.GState.ContractState module Michelson.Printer -- | Generalize converting a type into a Text.PrettyPrint.Leijen.Text.Doc. -- Used to pretty print Michelson code and define Fmt.Buildable -- instances. class RenderDoc a renderDoc :: RenderDoc a => RenderContext -> a -> Doc -- | Whether a value can be represented in Michelson code. Normally either -- all values of some type are renderable or not renderable. However, in -- case of instructions we have extra instructions which should not be -- rendered. Note: it's not suficcient to just return mempty for -- such instructions, because sometimes we want to print lists of -- instructions and we need to ignore them complete (to avoid putting -- redundant separators). isRenderable :: RenderDoc a => a -> Bool -- | Convert Doc to Text with a line width of 80. printDoc :: Bool -> Doc -> Text -- | Convert an untyped contract into a textual representation which will -- be accepted by the OCaml reference client. printUntypedContract :: RenderDoc op => Bool -> Contract' op -> Text -- | Convert a typed contract into a textual representation which will be -- accepted by the OCaml reference client. printTypedContract :: (SingI p, SingI s) => Bool -> Contract p s -> Text printTypedFullContract :: Bool -> FullContract p s -> Text printSomeContract :: Bool -> SomeContract -> Text printTypedValue :: forall t. ProperPrintedValBetterErrors t => Bool -> Value t -> Text module Michelson.Macro data CadrStruct A :: CadrStruct D :: CadrStruct data PairStruct F :: (VarAnn, FieldAnn) -> PairStruct P :: PairStruct -> PairStruct -> PairStruct -- | Built-in Michelson Macros defined by the specification data Macro CASE :: NonEmpty [ParsedOp] -> Macro TAG :: Natural -> NonEmpty Type -> Macro ACCESS :: Natural -> Positive -> Macro SET :: Natural -> Positive -> Macro CONSTRUCT :: NonEmpty [ParsedOp] -> Macro VIEW :: [ParsedOp] -> Macro VOID :: [ParsedOp] -> Macro CMP :: ParsedInstr -> VarAnn -> Macro IFX :: ParsedInstr -> [ParsedOp] -> [ParsedOp] -> Macro IFCMP :: ParsedInstr -> VarAnn -> [ParsedOp] -> [ParsedOp] -> Macro FAIL :: Macro PAPAIR :: PairStruct -> TypeAnn -> VarAnn -> Macro UNPAIR :: PairStruct -> Macro CADR :: [CadrStruct] -> VarAnn -> FieldAnn -> Macro SET_CADR :: [CadrStruct] -> VarAnn -> FieldAnn -> Macro MAP_CADR :: [CadrStruct] -> VarAnn -> FieldAnn -> [ParsedOp] -> Macro DIIP :: Word -> [ParsedOp] -> Macro DUUP :: Word -> VarAnn -> Macro ASSERT :: Macro ASSERTX :: ParsedInstr -> Macro ASSERT_CMP :: ParsedInstr -> Macro ASSERT_NONE :: Macro ASSERT_SOME :: Macro ASSERT_LEFT :: Macro ASSERT_RIGHT :: Macro IF_SOME :: [ParsedOp] -> [ParsedOp] -> Macro IF_RIGHT :: [ParsedOp] -> [ParsedOp] -> Macro -- | A programmer-defined macro data LetMacro LetMacro :: Text -> StackFn -> [ParsedOp] -> LetMacro [lmName] :: LetMacro -> Text [lmSig] :: LetMacro -> StackFn [lmExpr] :: LetMacro -> [ParsedOp] type ParsedValue = Value' ParsedOp type ParsedInstr = InstrAbstract ParsedOp -- | Unexpanded instructions produced directly by the ops parser, -- which contains primitive Michelson Instructions, inline-able macros -- and sequences data ParsedOp -- | Primitive Michelson instruction Prim :: ParsedInstr -> SrcPos -> ParsedOp -- | Built-in Michelson macro defined by the specification Mac :: Macro -> SrcPos -> ParsedOp -- | User-defined macro with instructions to be inlined LMac :: LetMacro -> SrcPos -> ParsedOp -- | A sequence of instructions Seq :: [ParsedOp] -> SrcPos -> ParsedOp type ParsedUExtInstr = ExtInstrAbstract ParsedOp -- | Expand all macros in parsed contract. expandContract :: Contract' ParsedOp -> Contract expandValue :: ParsedValue -> Value mapLeaves :: [(VarAnn, FieldAnn)] -> PairStruct -> PairStruct expand :: LetCallStack -> ParsedOp -> ExpandedOp expandList :: [ParsedOp] -> [ExpandedOp] expandMacro :: InstrCallStack -> Macro -> [ExpandedOp] expandPapair :: InstrCallStack -> PairStruct -> TypeAnn -> VarAnn -> [ExpandedOp] expandUnpapair :: InstrCallStack -> PairStruct -> [ExpandedOp] expandCadr :: InstrCallStack -> [CadrStruct] -> VarAnn -> FieldAnn -> [ExpandedOp] expandSetCadr :: InstrCallStack -> [CadrStruct] -> VarAnn -> FieldAnn -> [ExpandedOp] expandMapCadr :: InstrCallStack -> [CadrStruct] -> VarAnn -> FieldAnn -> [ParsedOp] -> [ExpandedOp] instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Macro.Macro instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Macro.Macro instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Macro.CadrStruct instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Macro.CadrStruct instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Macro.PairStruct instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Macro.PairStruct instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Macro.LetMacro instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Macro.LetMacro instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Macro.ParsedOp instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Macro.ParsedOp instance GHC.Generics.Generic Michelson.Macro.LetMacro instance Data.Data.Data Michelson.Macro.LetMacro instance GHC.Show.Show Michelson.Macro.LetMacro instance GHC.Classes.Eq Michelson.Macro.LetMacro instance GHC.Generics.Generic Michelson.Macro.ParsedOp instance Data.Data.Data Michelson.Macro.ParsedOp instance GHC.Show.Show Michelson.Macro.ParsedOp instance GHC.Classes.Eq Michelson.Macro.ParsedOp instance GHC.Generics.Generic Michelson.Macro.Macro instance Data.Data.Data Michelson.Macro.Macro instance GHC.Show.Show Michelson.Macro.Macro instance GHC.Classes.Eq Michelson.Macro.Macro instance GHC.Generics.Generic Michelson.Macro.CadrStruct instance Data.Data.Data Michelson.Macro.CadrStruct instance GHC.Show.Show Michelson.Macro.CadrStruct instance GHC.Classes.Eq Michelson.Macro.CadrStruct instance GHC.Generics.Generic Michelson.Macro.PairStruct instance Data.Data.Data Michelson.Macro.PairStruct instance GHC.Show.Show Michelson.Macro.PairStruct instance GHC.Classes.Eq Michelson.Macro.PairStruct instance Formatting.Buildable.Buildable Michelson.Macro.LetMacro instance Michelson.Printer.Util.RenderDoc Michelson.Macro.ParsedOp instance Formatting.Buildable.Buildable Michelson.Macro.ParsedOp instance Formatting.Buildable.Buildable Michelson.Macro.Macro instance Formatting.Buildable.Buildable Michelson.Macro.CadrStruct instance Formatting.Buildable.Buildable Michelson.Macro.PairStruct module Michelson.Let -- | A programmer-defined type-synonym data LetType LetType :: Text -> Type -> LetType [ltName] :: LetType -> Text [ltSig] :: LetType -> Type -- | A programmer-defined constant data LetValue LetValue :: Text -> Type -> Value' ParsedOp -> LetValue [lvName] :: LetValue -> Text [lvSig] :: LetValue -> Type [lvVal] :: LetValue -> Value' ParsedOp instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Let.LetType instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Let.LetType instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Let.LetValue instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Let.LetValue instance GHC.Show.Show Michelson.Let.LetType instance GHC.Classes.Eq Michelson.Let.LetType instance GHC.Show.Show Michelson.Let.LetValue instance GHC.Classes.Eq Michelson.Let.LetValue -- | Core parser types module Michelson.Parser.Types type Parser = ReaderT LetEnv (Parsec CustomParserException Text) -- | The environment containing lets from the let-block data LetEnv LetEnv :: Map Text LetMacro -> Map Text LetValue -> Map Text LetType -> LetEnv [letMacros] :: LetEnv -> Map Text LetMacro [letValues] :: LetEnv -> Map Text LetValue [letTypes] :: LetEnv -> Map Text LetType noLetEnv :: LetEnv instance GHC.Classes.Eq Michelson.Parser.Types.LetEnv instance GHC.Show.Show Michelson.Parser.Types.LetEnv instance Data.Default.Class.Default a => Data.Default.Class.Default (Michelson.Parser.Types.Parser a) module Michelson.Parser.Lexer lexeme :: Parser a -> Parser a mSpace :: Parser () symbol :: Tokens Text -> Parser () symbol' :: Text -> Parser () string' :: (MonadParsec e s f, Tokens s ~ Text) => Text -> f Text parens :: Parser a -> Parser a braces :: Parser a -> Parser a brackets :: Parser a -> Parser a brackets' :: Parser a -> Parser a semicolon :: Parser () comma :: Parser () varID :: Parser Var module Michelson.Parser.Helpers -- | Make a parser from a string mkParser :: (a -> Text) -> a -> Parser a sepEndBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a) -- | endBy2 p sep parses two or more occurrences of p, -- separated by sep. sepBy2 :: MonadPlus m => m a -> m sep -> m (NonEmpty a) -- | Apply given parser and return default value if it fails. parseDef :: Default a => Parser a -> Parser a -- | Parse a positive number. positive :: Parser Positive -- | Parse expression which can be wrapped in parentheses. mparens :: Parser a -> Parser a -- | Parsing of untyped Michelson values. module Michelson.Parser.Value -- | Parse untyped ParsedValue. Take instruction parser as argument -- to avoid cyclic dependencies between modules, hence ' in its name. value' :: Parser ParsedOp -> Parser ParsedValue mkLetVal :: Map Text LetValue -> Parser LetValue stringLiteral :: Parser ParsedValue bytesLiteral :: Parser (Value' op) intLiteral :: Parser (Value' op) module Michelson.Parser.Annotations noteV :: Parser VarAnn noteF :: Parser FieldAnn noteFDef :: Parser FieldAnn noteTDef :: Parser TypeAnn noteVDef :: Parser VarAnn notesTVF :: Parser (TypeAnn, VarAnn, FieldAnn) notesTVF2 :: Parser (TypeAnn, VarAnn, (FieldAnn, FieldAnn)) notesTV :: Parser (TypeAnn, VarAnn) notesVF :: Parser (VarAnn, FieldAnn) fieldType :: Default a => Parser a -> Parser (a, TypeAnn) permute2Def :: (Default a, Default b, Monad f, Alternative f) => f a -> f b -> f (a, b) permute3Def :: (Default a, Default b, Default c, Monad f, Alternative f) => f a -> f b -> f c -> f (a, b, c) -- | Parsing of Michelson types. module Michelson.Parser.Type -- | Parse untyped Michelson Type (i. e. one with annotations). type_ :: Parser Type comparable :: Parser Comparable -- | Parsing logic for extra instructions (Morley extensions) module Michelson.Parser.Ext extInstr :: Parser [ParsedOp] -> Parser ParsedUExtInstr stackType :: Parser StackTypePattern printComment :: Parser PrintComment -- | Parsing of Michelson instructions. module Michelson.Parser.Instr -- | Parser for primitive Michelson instruction (no macros and extensions). primInstr :: Parser (Contract' ParsedOp) -> Parser ParsedOp -> Parser ParsedInstr -- | Parse a sequence of instructions. ops' :: Parser ParsedOp -> Parser [ParsedOp] mapOp :: Parser ParsedOp -> Parser ParsedInstr pairOp :: Parser ParsedInstr cmpOp :: Parser ParsedInstr -- | Parsing of built-in Michelson macros. module Michelson.Parser.Macro macro :: Parser ParsedOp -> Parser Macro pairMac :: Parser Macro ifCmpMac :: Parser ParsedOp -> Parser Macro mapCadrMac :: Parser ParsedOp -> Parser Macro -- | Parsing of let blocks module Michelson.Parser.Let -- | let block parser letBlock :: Parser ParsedOp -> Parser LetEnv mkLetMac :: Map Text LetMacro -> Parser LetMacro letType :: Parser LetType module Michelson.Parser type Parser = ReaderT LetEnv (Parsec CustomParserException Text) -- | Michelson contract with let definitions program :: Parsec CustomParserException Text (Contract' ParsedOp) value :: Parser ParsedValue data CustomParserException UnknownTypeException :: CustomParserException StringLiteralException :: StringLiteralParserException -> CustomParserException OddNumberBytesException :: CustomParserException WrongTagArgs :: Natural -> Positive -> CustomParserException WrongAccessArgs :: Natural -> Positive -> CustomParserException WrongSetArgs :: Natural -> Positive -> CustomParserException -- | A non-empty collection of ParseErrors equipped with -- PosState that allows to pretty-print the errors efficiently and -- correctly. data ParseErrorBundle s e data ParserException ParserException :: ParseErrorBundle Text CustomParserException -> ParserException data StringLiteralParserException InvalidEscapeSequence :: Char -> StringLiteralParserException InvalidChar :: Char -> StringLiteralParserException -- | Parse with empty environment parseNoEnv :: Parser a -> String -> Text -> Either (ParseErrorBundle Text CustomParserException) a -- | Parse untyped value from text which comes from something that is not a -- file (which is often the case). So we assume it does not need any -- parsing environment. parseValue :: Text -> Either ParserException ParsedValue -- | Like parseValue, but also expands macros. parseExpandValue :: Text -> Either ParserException Value -- | Parses code block after "code" keyword of a contract. -- -- This function is part of the module API, its semantics should not -- change. codeEntry :: Parser [ParsedOp] -- | Parse untyped Michelson Type (i. e. one with annotations). type_ :: Parser Type letType :: Parser LetType stringLiteral :: Parser ParsedValue bytesLiteral :: Parser (Value' op) intLiteral :: Parser (Value' op) printComment :: Parser PrintComment -- | Apply some transformations to Michelson code. module Michelson.Preprocess -- | Transform all strings in a typed instructions using given function. -- The first argument specifies whether we should go into arguments that -- contain instructions. transformStrings :: Bool -> (MText -> MText) -> Instr inp out -> Instr inp out -- | Similar to transformStrings but for bytes. TODO [TM-375]: -- deduplicate transformBytes :: Bool -> (ByteString -> ByteString) -> Instr inp out -> Instr inp out -- | Module, carrying logic of UNPACK instruction. -- -- This is nearly symmetric to adjacent Pack.hs module. -- -- When implementing this the following sources were used: -- -- module Michelson.Interpret.Unpack -- | Any decoding error. newtype UnpackError UnpackError :: Text -> UnpackError [unUnpackError] :: UnpackError -> Text -- | Deserialize bytes into the given value. Suitable for UNPACK -- operation only. unpackValue :: UnpackedValScope t => LByteString -> Either UnpackError (Value t) -- | Like unpackValue, for strict byte array. unpackValue' :: UnpackedValScope t => ByteString -> Either UnpackError (Value t) instance GHC.Classes.Eq Michelson.Interpret.Unpack.UnpackError instance GHC.Show.Show Michelson.Interpret.Unpack.UnpackError instance Formatting.Buildable.Buildable Michelson.Interpret.Unpack.UnpackError instance GHC.Exception.Type.Exception Michelson.Interpret.Unpack.UnpackError -- | Module, carrying logic of PACK instruction. -- -- This is nearly symmetric to adjacent Unpack.hs module. module Michelson.Interpret.Pack packCode' :: Instr inp out -> ByteString packT' :: forall (t :: T). SingI t => ByteString -- | Serialize a value given to PACK instruction. packValue :: PackedValScope t => Value t -> LByteString -- | Same as packValue, for strict bytestring. packValue' :: PackedValScope t => Value t -> ByteString -- | Encode contents of a given number. encodeIntPayload :: Integer -> LByteString -- | Optimizer for typed instructions. -- -- It's quite experimental and incomplete. List of possible improvements: -- 1. pushDrop, dupDrop, unitDrop rules are -- essentially the same. It would be good to generalize them into one -- rule. The same applies to pushDip. It probably can be done -- more efficiently. module Michelson.Optimizer -- | Optimize a typed instruction by replacing some sequences of -- instructions with smaller equivalent sequences. Applies default set of -- rewrite rules. optimize :: Instr inp out -> Instr inp out -- | Optimize a typed instruction using a custom set of rules. optimizeWithConf :: OptimizerConf -> Instr inp out -> Instr inp out defaultRules :: Rule -> Rule -- | We do not enable pushPack rule by default because it is -- potentially dangerous. There are various code processing functions -- that may depend on constants, e. g. string transformations. defaultRulesAndPushPack :: Rule -> Rule -- | Combine two rule fixpoints. orRule :: (Rule -> Rule) -> (Rule -> Rule) -> Rule -> Rule -- | Combine a rule fixpoint and a simple rule. orSimpleRule :: (Rule -> Rule) -> Rule -> Rule -> Rule type Rule = forall inp out. Instr inp out -> Maybe (Instr inp out) data OptimizerConf OptimizerConf :: Bool -> (Rule -> Rule) -> OptimizerConf [gotoValues] :: OptimizerConf -> Bool [ruleset] :: OptimizerConf -> Rule -> Rule instance Data.Default.Class.Default Michelson.Optimizer.OptimizerConf -- | Measuring operation size. -- -- When originating a contract or making a transfer, tezos node forms -- operation which is submitted over network. Size of this operation -- depends on content of originated contract or transfer parameter resp., -- and tezos has a hard limit on operation size thus it has to be -- accounted. -- -- Functions declared in this module allow assessing size of origination -- or transfer operation with up to constant precision because it yet -- accounts only for Michelson primitives participating in the operation. -- Other stuff which affects op size include parameters which user passes -- to origination or transfer themselves, for instance, amount of mutez -- carried to the contract. ATM we don't have necessary primitives in -- Haskell to be able to handle those parameters here, probably waiting -- for [TM-89]. Currently, we can assess overall transfer size only -- approximatelly, like in smallTransferOpSize. module Michelson.OpSize -- | Operation size in bytes. -- -- We use newtype wrapper because there are different units of measure -- (another one is gas, and we don't want to confuse them). newtype OpSize OpSize :: Word -> OpSize [unOpSize] :: OpSize -> Word -- | Maximal operation size allowed by Tezos production nodes. opSizeHardLimit :: OpSize -- | Base cost of any transfer of 0 mutez with no extra parameters. (Add -- 'valueOpSize param' to it to get assessment of actual transfer -- op size) smallTransferOpSize :: OpSize instrOpSize :: InstrAbstract ExpandedOp -> OpSize expandedInstrsOpSize :: [ExpandedOp] -> OpSize valueOpSize :: Value -> OpSize instance GHC.Classes.Ord Michelson.OpSize.OpSize instance GHC.Classes.Eq Michelson.OpSize.OpSize instance GHC.Show.Show Michelson.OpSize.OpSize instance forall k x (t :: k). Michelson.OpSize.AnnsOpSizeVararg x => Michelson.OpSize.AnnsOpSizeVararg (Michelson.Untyped.Annotation.Annotation t -> x) instance forall k x (t :: k). Michelson.OpSize.AnnsOpSizeVararg x => Michelson.OpSize.AnnsOpSizeVararg ([Michelson.Untyped.Annotation.Annotation t] -> x) instance Michelson.OpSize.AnnsOpSizeVararg Michelson.OpSize.OpSize instance GHC.Base.Semigroup Michelson.OpSize.OpSize instance GHC.Base.Monoid Michelson.OpSize.OpSize -- | Module, containing function to interpret Michelson instructions -- against given context and input stack. module Michelson.Interpret -- | Environment for contract execution. data ContractEnv ContractEnv :: !Timestamp -> !RemainingSteps -> !Mutez -> TcOriginatedContracts -> !Address -> !Address -> !Address -> !Mutez -> !ChainId -> ContractEnv -- | Timestamp returned by the NOW instruction. [ceNow] :: ContractEnv -> !Timestamp -- | Number of steps after which execution unconditionally terminates. [ceMaxSteps] :: ContractEnv -> !RemainingSteps -- | Current amount of mutez of the current contract. [ceBalance] :: ContractEnv -> !Mutez -- | Mapping from existing contracts' addresses to their executable -- representation. [ceContracts] :: ContractEnv -> TcOriginatedContracts -- | Address of the interpreted contract. [ceSelf] :: ContractEnv -> !Address -- | The contract that initiated the current transaction. [ceSource] :: ContractEnv -> !Address -- | The contract that initiated the current internal transaction. [ceSender] :: ContractEnv -> !Address -- | Amount of the current transaction. [ceAmount] :: ContractEnv -> !Mutez -- | Identifier of the current chain. [ceChainId] :: ContractEnv -> !ChainId data InterpreterState InterpreterState :: MorleyLogs -> RemainingSteps -> InterpreterState [isMorleyLogs] :: InterpreterState -> MorleyLogs [isRemainingSteps] :: InterpreterState -> RemainingSteps -- | Represents `[FAILED]` state of a Michelson program. Contains value -- that was on top of the stack when FAILWITH was called. data MichelsonFailed [MichelsonFailedWith] :: (Typeable t, SingI t) => Value t -> MichelsonFailed [MichelsonArithError] :: (Typeable n, Typeable m) => ArithError (CValue n) (CValue m) -> MichelsonFailed [MichelsonGasExhaustion] :: MichelsonFailed [MichelsonFailedTestAssert] :: Text -> MichelsonFailed [MichelsonAmbigousEpRef] :: EpName -> EpAddress -> MichelsonFailed newtype RemainingSteps RemainingSteps :: Word64 -> RemainingSteps data SomeItStack [SomeItStack] :: ExtInstr inp -> Rec Value inp -> SomeItStack type EvalOp a = ExceptT MichelsonFailed (ReaderT ContractEnv (State InterpreterState)) a -- | Morley interpreter state newtype MorleyLogs MorleyLogs :: [Text] -> MorleyLogs [unMorleyLogs] :: MorleyLogs -> [Text] noMorleyLogs :: MorleyLogs interpret :: Contract cp st -> Value cp -> Value st -> ContractEnv -> ContractReturn st -- | Emulate multiple calls of a contract. interpretRepeated :: Contract cp st -> [Value cp] -> Value st -> ContractEnv -> ContractReturn st -- | Interpret an instruction in vacuum, putting no extra contraints on its -- execution. -- -- Mostly for testing purposes. interpretInstr :: ContractEnv -> Instr inp out -> Rec Value inp -> Either MichelsonFailed (Rec Value out) type ContractReturn st = (Either MichelsonFailed ([Operation], Value st), InterpreterState) -- | Interpret a contract without performing any side effects using typed -- representation of contract, parameter and storage. interpretSome :: SomeContract -> SomeValue -> SomeValue -> ContractEnv -> Either InterpretError InterpretResult -- | Interpret a contract without performing any side effects. This -- function uses untyped representation of contract, parameter and -- storage. Mostly used for testing. interpretUntyped :: Contract -> Value -> Value -> ContractEnv -> Either InterpretError InterpretResult data InterpretError RuntimeFailure :: (MichelsonFailed, MorleyLogs) -> InterpretError IllTypedContract :: TCError -> InterpretError IllTypedParam :: TCError -> InterpretError IllTypedStorage :: TCError -> InterpretError UnexpectedParamType :: TCTypeError -> InterpretError UnexpectedStorageType :: TCTypeError -> InterpretError data InterpretResult [InterpretResult] :: StorageScope st => {iurOps :: [Operation], iurNewStorage :: Value st, iurNewState :: InterpreterState} -> InterpretResult -- | Function to change amount of remaining steps stored in State monad runInstr :: Instr inp out -> Rec Value inp -> EvalOp (Rec Value out) runInstrNoGas :: forall a b. Instr a b -> Rec Value a -> EvalOp (Rec Value b) -- | Unpacks given raw data into a typed value. runUnpack :: forall t. UnpackedValScope t => ByteString -> Either UnpackError (Value t) instance GHC.Show.Show Michelson.Interpret.InterpreterState instance GHC.Num.Num Michelson.Interpret.RemainingSteps instance Formatting.Buildable.Buildable Michelson.Interpret.RemainingSteps instance GHC.Classes.Ord Michelson.Interpret.RemainingSteps instance GHC.Classes.Eq Michelson.Interpret.RemainingSteps instance GHC.Show.Show Michelson.Interpret.RemainingSteps instance GHC.Generics.Generic Michelson.Interpret.InterpretError instance Formatting.Buildable.Buildable Michelson.Interpret.MorleyLogs instance Data.Default.Class.Default Michelson.Interpret.MorleyLogs instance GHC.Show.Show Michelson.Interpret.MorleyLogs instance GHC.Classes.Eq Michelson.Interpret.MorleyLogs instance GHC.Show.Show Michelson.Interpret.MichelsonFailed instance GHC.Show.Show Michelson.Interpret.InterpretError instance GHC.Show.Show Michelson.Interpret.InterpretResult instance Formatting.Buildable.Buildable Michelson.Interpret.InterpretError instance GHC.Classes.Eq Michelson.Interpret.MichelsonFailed instance Formatting.Buildable.Buildable Michelson.Interpret.MichelsonFailed -- | Utility functions for unit testing. module Michelson.Test.Unit type ContractReturn st = (Either MichelsonFailed ([Operation], Value st), InterpreterState) -- | Type for contract execution validation. -- -- It's a function which is supplied with contract execution output -- (failure or new storage with operation list). -- -- Function returns a property which type is designated by type variable -- prop and might be Property or Expectation or -- anything else relevant. type ContractPropValidator st prop = ContractReturn st -> prop -- | Contract's property tester against given input. Takes contract -- environment, initial storage and parameter, interprets contract on -- this input and invokes validation function. contractProp :: (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> param -> storage -> prop -- | Version of contractProp which takes Val as arguments -- instead of regular Haskell values. contractPropVal :: Contract cp st -> ContractPropValidator st prop -> ContractEnv -> Value cp -> Value st -> prop contractRepeatedProp :: (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> [param] -> storage -> prop contractRepeatedPropVal :: Contract cp st -> ContractPropValidator st prop -> ContractEnv -> [Value cp] -> Value st -> prop -- | Dummy data to be used in tests where it's not essential. module Michelson.Test.Dummy -- | Dummy timestamp, can be used to specify current NOW value or -- maybe something else. dummyNow :: Timestamp -- | Dummy value for maximal number of steps a contract can make. -- Intentionally quite large, because most likely if you use dummy value -- you don't want the interpreter to stop due to gas exhaustion. On the -- other hand, it probably still prevents the interpreter from working -- for eternity. dummyMaxSteps :: RemainingSteps -- | Dummy ContractEnv with some reasonable hardcoded values. You -- can override values you are interested in using record update syntax. dummyContractEnv :: ContractEnv -- | OriginationOperation with most data hardcoded to some -- reasonable values. Contract and initial values must be passed -- explicitly, because otherwise it hardly makes sense. dummyOrigination :: Value -> Contract -> OriginationOperation -- | Interpreter and typechecker of a contract in Morley language. module Michelson.Runtime -- | Originate a contract. Returns the address of the originated contract. originateContract :: FilePath -> OriginationOperation -> ("verbose" :! Bool) -> IO Address -- | Run a contract. The contract is originated first (if it's not already) -- and then we pretend that we send a transaction to it. runContract :: Maybe Timestamp -> Word64 -> Mutez -> FilePath -> Value -> Contract -> TxData -> ("verbose" :! Bool) -> ("dryRun" :! Bool) -> IO () -- | Send a transaction to given address with given parameters. transfer :: Maybe Timestamp -> Word64 -> FilePath -> Address -> TxData -> ("verbose" :! Bool) -> ("dryRun" :? Bool) -> IO () -- | Parse a contract from Text. parseContract :: Maybe FilePath -> Text -> Either ParserException (Contract' ParsedOp) -- | Parse a contract from Text and expand macros. parseExpandContract :: Maybe FilePath -> Text -> Either ParserException Contract -- | Read and parse a contract from give path or stdin (if the -- argument is Nothing). The contract is not expanded. readAndParseContract :: Maybe FilePath -> IO (Contract' ParsedOp) -- | Read a contract using readAndParseContract, expand and flatten. -- The contract is not type checked. prepareContract :: Maybe FilePath -> IO Contract typeCheckWithDb :: FilePath -> Contract -> IO (Either TCError SomeContract) -- | State of a contract with code. data ContractState ContractState :: !Mutez -> !Value -> !Contract -> !Maybe SomeContract -> !Maybe SomeValue -> ContractState -- | Amount of mutez owned by this contract. [csBalance] :: ContractState -> !Mutez -- | Storage value associated with this contract. [csStorage] :: ContractState -> !Value -- | Contract itself (untyped). [csContract] :: ContractState -> !Contract [csTypedContract] :: ContractState -> !Maybe SomeContract -- | We keep typed representation of contract code and storage in form, -- that hides their actual type in order to simplify the rest of the code -- (e.g. avoid type parameters for ContractState and so on). They -- are made optional in order to perform safe parsing from JSON (we -- simply return Nothing in this parser and use -- getTypedStorage or getTypedContract that optionally -- typecheck storage or contract code). [csTypedStorage] :: ContractState -> !Maybe SomeValue -- | State of an arbitrary address. data AddressState -- | For contracts without code we store only its balance. ASSimple :: !Mutez -> AddressState -- | For contracts with code we store more state represented by -- ContractState. ASContract :: !ContractState -> AddressState -- | Data associated with a particular transaction. data TxData TxData :: !Address -> !Value -> !Mutez -> TxData [tdSenderAddress] :: TxData -> !Address [tdParameter] :: TxData -> !Value [tdAmount] :: TxData -> !Mutez -- | Operations executed by interpreter. In our model one Michelson's -- operation (operation type in Michelson) corresponds to 0 or 1 -- interpreter operation. -- -- Note: Address is not part of TxData, because -- TxData is supposed to be provided by the user, while -- Address can be computed by our code. data InterpreterOp -- | Originate a contract. OriginateOp :: !OriginationOperation -> InterpreterOp -- | Send a transaction to given address which is assumed to be the address -- of an originated contract. TransferOp :: Address -> TxData -> InterpreterOp -- | Result of a single execution of interpreter. data InterpreterRes InterpreterRes :: !GState -> [InterpreterOp] -> ![GStateUpdate] -> [(Address, InterpretResult)] -> !Maybe Address -> !RemainingSteps -> InterpreterRes -- | New GState. [_irGState] :: InterpreterRes -> !GState -- | List of operations to be added to the operations queue. [_irOperations] :: InterpreterRes -> [InterpreterOp] -- | Updates applied to GState. [_irUpdates] :: InterpreterRes -> ![GStateUpdate] -- | During execution a contract can print logs and in the end it returns a -- pair. All logs and returned values are kept until all called contracts -- are executed. In the end they are printed. [_irInterpretResults] :: InterpreterRes -> [(Address, InterpretResult)] -- | As soon as transfer operation is encountered, this address is set to -- its input. [_irSourceAddress] :: InterpreterRes -> !Maybe Address -- | Now much gas all remaining executions can consume. [_irRemainingSteps] :: InterpreterRes -> !RemainingSteps -- | Errors that can happen during contract interpreting. Type parameter -- a determines how contracts will be represented in these -- errors, e.g. Address data InterpreterError' a -- | The interpreted contract hasn't been originated. IEUnknownContract :: !a -> InterpreterError' a -- | Interpretation of Michelson contract failed. IEInterpreterFailed :: !a -> !InterpretError -> InterpreterError' a -- | A contract is already originated. IEAlreadyOriginated :: !a -> !ContractState -> InterpreterError' a -- | Sender address is unknown. IEUnknownSender :: !a -> InterpreterError' a -- | Manager address is unknown. IEUnknownManager :: !a -> InterpreterError' a -- | Sender doesn't have enough funds. IENotEnoughFunds :: !a -> !Mutez -> InterpreterError' a -- | Sending 0tz towards an address. IEZeroTransaction :: !a -> InterpreterError' a -- | Failed to apply updates to GState. IEFailedToApplyUpdates :: !GStateUpdateError -> InterpreterError' a -- | A contract is ill-typed. IEIllTypedContract :: !TCError -> InterpreterError' a -- | Contract storage is ill-typed IEIllTypedStorage :: !TCError -> InterpreterError' a -- | Contract parameter is ill-typed IEIllTypedParameter :: !TCError -> InterpreterError' a type InterpreterError = InterpreterError' Address -- | Implementation of interpreter outside IO. It reads operations, -- interprets them one by one and updates state accordingly. Each -- operation from the passed list is fully interpreted before the next -- one is considered. interpreterPure :: Timestamp -> RemainingSteps -> GState -> [InterpreterOp] -> Either InterpreterError InterpreterRes irInterpretResults :: Lens' InterpreterRes [(Address, InterpretResult)] irUpdates :: Lens' InterpreterRes [GStateUpdate] instance GHC.Show.Show a => GHC.Show.Show (Michelson.Runtime.InterpreterError' a) instance Formatting.Buildable.Buildable a => Formatting.Buildable.Buildable (Michelson.Runtime.InterpreterError' a) instance (Data.Typeable.Internal.Typeable a, GHC.Show.Show a, Formatting.Buildable.Buildable a) => GHC.Exception.Type.Exception (Michelson.Runtime.InterpreterError' a) instance GHC.Base.Semigroup Michelson.Runtime.InterpreterRes instance GHC.Show.Show Michelson.Runtime.InterpreterRes instance GHC.Show.Show Michelson.Runtime.InterpreterOp -- | Utilities for integrational testing. Example tests can be found in the -- 'morley-test' test suite. module Michelson.Test.Integrational -- | Data associated with a particular transaction. data TxData TxData :: !Address -> !Value -> !Mutez -> TxData [tdSenderAddress] :: TxData -> !Address [tdParameter] :: TxData -> !Value [tdAmount] :: TxData -> !Mutez -- | One of genesis addresses. genesisAddress :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress1 :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress2 :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress3 :: Address genesisAddress4 :: Address genesisAddress5 :: Address genesisAddress6 :: Address -- | Validator for integrational testing. If an error is expected, it -- should be Left with validator for errors. Otherwise it should -- check final global state and its updates. type IntegrationalValidator = Either (InterpreterError -> Bool) SuccessValidator -- | Validator for integrational testing that expects successful execution. type SuccessValidator = InternalState -> GState -> [GStateUpdate] -> Either ValidationError () -- | A monad inside which integrational tests can be described using -- do-notation. type IntegrationalScenarioM = StateT InternalState (Except ScenarioError) type IntegrationalScenario = IntegrationalScenarioM Validated data ValidationError UnexpectedInterpreterError :: IntegrationalInterpreterError -> ValidationError UnexpectedTypeCheckError :: TCError -> ValidationError ExpectingInterpreterToFail :: ValidationError IncorrectUpdates :: ValidationError -> [GStateUpdate] -> ValidationError IncorrectStorageUpdate :: AddressName -> Text -> ValidationError InvalidStorage :: AddressName -> ExpectedStorage -> Text -> ValidationError InvalidBalance :: AddressName -> ExpectedBalance -> Text -> ValidationError UnexpectedUpdates :: NonEmpty GStateUpdate -> ValidationError CustomValidationError :: Text -> ValidationError -- | Integrational test that executes given operations and validates them -- using given validator. It can fail using Expectation -- capability. It starts with initGState and some reasonable dummy -- values for gas limit and current timestamp. You can update blockchain -- state by performing some operations. integrationalTestExpectation :: HasCallStack => IntegrationalScenario -> Expectation -- | Integrational test similar to integrationalTestExpectation. It -- can fail using Property capability. It can be used with -- QuickCheck's forAll to make a property-based test with -- arbitrary data. integrationalTestProperty :: IntegrationalScenario -> Property -- | Originate a contract with given initial storage and balance. Its -- address is returned. originate :: Contract -> Text -> Value -> Mutez -> IntegrationalScenarioM Address -- | Transfer tokens to given address. transfer :: TxData -> Address -> IntegrationalScenarioM () -- | Execute all operations that were added to the scenarion since last -- validate call. If validator fails, the execution will be -- aborted. validate :: IntegrationalValidator -> IntegrationalScenario -- | Make all further interpreter calls (which are triggered by the -- validate function) use given gas limit. setMaxSteps :: RemainingSteps -> IntegrationalScenarioM () -- | Make all further interpreter calls (which are triggered by the -- validate function) use modified timestamp as the current one. modifyNow :: (Timestamp -> Timestamp) -> IntegrationalScenarioM () -- | Make all further interpreter calls (which are triggered by the -- validate function) use given timestamp as the current one. setNow :: Timestamp -> IntegrationalScenarioM () -- | Increase current time by the given number of seconds. rewindTime :: Integer -> IntegrationalScenarioM () -- | Pretend that given address initiates all the transfers within the code -- block (i.e. SENDER instruction will return this address). withSender :: Address -> IntegrationalScenarioM a -> IntegrationalScenarioM a -- | Make all further interpreter calls (which are triggered by the -- validate function) use given chain id. setChainId :: ChainId -> IntegrationalScenarioM () -- | Execute multiple testing scenarios independently, basing them on -- scenario built till this point. -- -- The following property holds for this function: -- -- pre >> branchout [a, b, c] = branchout [pre >> a, pre -- >> b, pre >> c] . -- -- In case of property failure in one of the branches no following branch -- is executed. -- -- Providing empty list of scenarios to this function causes error; we do -- not require NonEmpty here though for convenience. branchout :: HasCallStack => [(Text, IntegrationalScenario)] -> IntegrationalScenario -- | Make a tuple with name without extra syntactic noise. (?-) :: Text -> a -> (Text, a) infixr 0 ?- -- | Test given scenario with the state gathered till this moment; if this -- scenario passes, go on as if it never happened. offshoot :: Text -> IntegrationalScenario -> IntegrationalScenarioM () -- | Compose two success validators. -- -- For example: -- -- expectBalance bal addr composeValidators -- expectStorageUpdateConst addr2 ValueUnit composeValidators :: SuccessValidator -> SuccessValidator -> SuccessValidator -- | Compose a list of success validators. composeValidatorsList :: [SuccessValidator] -> SuccessValidator -- | SuccessValidator that always passes. expectAnySuccess :: SuccessValidator -- | Check that there were no updates. expectNoUpdates :: SuccessValidator -- | Check that there were no storage updates. expectNoStorageUpdates :: SuccessValidator -- | Check that storage value is updated for given address. Takes a -- predicate that is used to check the value. -- -- It works even if updates are not filtered (i. e. a value can be -- updated more than once). expectStorageUpdate :: Address -> (Value -> Either ValidationError ()) -> SuccessValidator -- | Like expectStorageUpdate, but expects a constant. expectStorageUpdateConst :: Address -> Value -> SuccessValidator -- | Check that eventually address has some particular balance. expectBalance :: Address -> Mutez -> SuccessValidator -- | Check that eventually address has some particular storage value. expectStorageConst :: Address -> Value -> SuccessValidator -- | Check that interpreter failed due to gas exhaustion. expectGasExhaustion :: InterpreterError -> Bool -- | Expect that interpretation of contract with given address ended with -- [FAILED]. expectMichelsonFailed :: (MichelsonFailed -> Bool) -> Address -> InterpreterError -> Bool instance Formatting.Buildable.Buildable Michelson.Test.Integrational.ScenarioError instance GHC.Show.Show Michelson.Test.Integrational.ValidationError instance GHC.Show.Show Michelson.Test.Integrational.AddressName instance GHC.Show.Show Michelson.Test.Integrational.ExpectedBalance instance GHC.Show.Show Michelson.Test.Integrational.ExpectedStorage instance Formatting.Buildable.Buildable Michelson.Test.Integrational.ValidationError instance GHC.Exception.Type.Exception Michelson.Test.Integrational.ValidationError instance Formatting.Buildable.Buildable Michelson.Test.Integrational.AddressName instance Formatting.Buildable.Buildable Michelson.Test.Integrational.ScenarioBranchName -- | Typical usages of FAILWITH instruction. module Michelson.FailPattern -- | This data type captures typical ways to use FAILWITH -- instruction. Each constructor corresponds to a usage pattern. data TypicalFailWith -- | Extract error tag out of TypicalFailWith. typicalFailWithTag :: TypicalFailWith -> MText -- | Check whether given instruction ends with a typical FAILWITH -- usage. It does not recursively check instructions that can be passed -- to other instructions. isTypicalFailWith :: Instr inp out -> Maybe TypicalFailWith -- | If given instruction ends with a typical FAILWITH usage, modify -- the tag used there using given transformation function. It can return -- any value, not necessarily a string. modifyTypicalFailWith :: (HasCallStack, ConstantScope t, Typeable t) => (MText -> Value t) -> Instr inp out -> Instr inp out instance (Data.Typeable.Internal.Typeable a, Michelson.Typed.Scope.ConstantScope a) => Michelson.FailPattern.ConstantScope' a -- | Static analysis of Michelson code. module Michelson.Analyzer data AnalyzerRes AnalyzerRes :: !HashMap MText Word -> !HashMap ByteString Word -> !HashMap MText Word -> AnalyzerRes -- | All string constants and number of their occurrences. [arConstStrings] :: AnalyzerRes -> !HashMap MText Word -- | All bytes constants and number of their occurrences. [arConstBytes] :: AnalyzerRes -> !HashMap ByteString Word -- | Which strings are used as error tags and how many times. There is no -- notion of "error tag" in Michelson, so we use a heuristic to find out -- whether a string is an error tag. Specifically, we consider three -- patterns: 1. A constant string is pushed and then there is -- FAILWITH immediately. 2. A constant string is pushed, followed -- by PAIR instruction and then FAILWITH. 3. A constant -- pair is pushed where the first item is a string and then there is -- `FAILWITH. [arErrorTags] :: AnalyzerRes -> !HashMap MText Word -- | Statically analyze an instruction. Typed representation is used -- because it's easier to analyze. It means that we can't analyze -- ill-typed contracts, but hopefully it's not a serious limitation. analyze :: Instr inp out -> AnalyzerRes instance GHC.Classes.Eq Michelson.Analyzer.AnalyzerRes instance GHC.Show.Show Michelson.Analyzer.AnalyzerRes instance Formatting.Buildable.Buildable Michelson.Analyzer.AnalyzerRes instance GHC.Base.Semigroup Michelson.Analyzer.AnalyzerRes instance GHC.Base.Monoid Michelson.Analyzer.AnalyzerRes -- | Type families from Polymorphic lifted to Haskell types. module Lorentz.Polymorphic -- | Lifted MemOpKey. class (MemOp (ToT c), ToT (MemOpKeyHs c) ~ 'Tc (MemOpKey (ToT c))) => MemOpHs c where { type family MemOpKeyHs c :: Type; } -- | Lifted MapOp. class (MapOp (ToT c), ToT (MapOpInpHs c) ~ MapOpInp (ToT c), ToT (MapOpResHs c ()) ~ MapOpRes (ToT c) (ToT ())) => MapOpHs c where { type family MapOpInpHs c :: Type; type family MapOpResHs c :: Type -> Type; } -- | Lifted IterOp. class (IterOp (ToT c), ToT (IterOpElHs c) ~ IterOpEl (ToT c)) => IterOpHs c where { type family IterOpElHs c :: Type; } -- | Lifted SizeOp. -- -- This could be just a constraint alias, but to avoid T types -- appearance in error messages we make a full type class with concrete -- instances. class SizeOp (ToT c) => SizeOpHs c -- | Lifted UpdOp. class (UpdOp (ToT c), ToT (UpdOpKeyHs c) ~ 'Tc (UpdOpKey (ToT c)), ToT (UpdOpParamsHs c) ~ UpdOpParams (ToT c)) => UpdOpHs c where { type family UpdOpKeyHs c :: Type; type family UpdOpParamsHs c :: Type; } -- | Lifted GetOp. class (GetOp (ToT c), ToT (GetOpKeyHs c) ~ 'Tc (GetOpKey (ToT c)), ToT (GetOpValHs c) ~ GetOpVal (ToT c)) => GetOpHs c where { type family GetOpKeyHs c :: Type; type family GetOpValHs c :: Type; } -- | Lifted ConcatOp. class ConcatOp (ToT c) => ConcatOpHs c -- | Lifted SliceOp. class SliceOp (ToT c) => SliceOpHs c -- | Lifted EDivOp. class (EDivOp (ToCT n) (ToCT m), IsComparable n, IsComparable m, ToT (EDivOpResHs n m) ~ 'Tc (EDivOpRes (ToCT n) (ToCT m)), ToT (EModOpResHs n m) ~ 'Tc (EModOpRes (ToCT n) (ToCT m))) => EDivOpHs n m where { type family EDivOpResHs n m :: Type; type family EModOpResHs n m :: Type; } -- | A useful property which holds for reasonable MapOp instances. -- -- It's a separate thing from MapOpHs because it mentions -- b type parameter. type family IsoMapOpRes c b instance Lorentz.Polymorphic.EDivOpHs GHC.Integer.Type.Integer GHC.Integer.Type.Integer instance Lorentz.Polymorphic.EDivOpHs GHC.Integer.Type.Integer GHC.Natural.Natural instance Lorentz.Polymorphic.EDivOpHs GHC.Natural.Natural GHC.Integer.Type.Integer instance Lorentz.Polymorphic.EDivOpHs GHC.Natural.Natural GHC.Natural.Natural instance Lorentz.Polymorphic.EDivOpHs Tezos.Core.Mutez Tezos.Core.Mutez instance Lorentz.Polymorphic.EDivOpHs Tezos.Core.Mutez GHC.Natural.Natural instance Lorentz.Polymorphic.SliceOpHs Michelson.Text.MText instance Lorentz.Polymorphic.SliceOpHs Data.ByteString.Internal.ByteString instance Lorentz.Polymorphic.ConcatOpHs Michelson.Text.MText instance Lorentz.Polymorphic.ConcatOpHs Data.ByteString.Internal.ByteString instance Michelson.Typed.Haskell.Value.IsComparable k => Lorentz.Polymorphic.GetOpHs (Data.Map.Internal.Map k v) instance Michelson.Typed.Haskell.Value.IsComparable k => Lorentz.Polymorphic.GetOpHs (Michelson.Typed.Haskell.Value.BigMap k v) instance Michelson.Typed.Haskell.Value.IsComparable k => Lorentz.Polymorphic.UpdOpHs (Data.Map.Internal.Map k v) instance Michelson.Typed.Haskell.Value.IsComparable k => Lorentz.Polymorphic.UpdOpHs (Michelson.Typed.Haskell.Value.BigMap k v) instance Michelson.Typed.Haskell.Value.IsComparable a => Lorentz.Polymorphic.UpdOpHs (Data.Set.Internal.Set a) instance Lorentz.Polymorphic.SizeOpHs Michelson.Text.MText instance Lorentz.Polymorphic.SizeOpHs Data.ByteString.Internal.ByteString instance Lorentz.Polymorphic.SizeOpHs (Data.Set.Internal.Set a) instance Lorentz.Polymorphic.SizeOpHs [a] instance Lorentz.Polymorphic.SizeOpHs (Data.Map.Internal.Map k v) instance Michelson.Typed.Haskell.Value.IsComparable k => Lorentz.Polymorphic.IterOpHs (Data.Map.Internal.Map k v) instance Lorentz.Polymorphic.IterOpHs [e] instance Michelson.Typed.Haskell.Value.IsComparable e => Lorentz.Polymorphic.IterOpHs (Data.Set.Internal.Set e) instance Michelson.Typed.Haskell.Value.IsComparable k => Lorentz.Polymorphic.MapOpHs (Data.Map.Internal.Map k v) instance Lorentz.Polymorphic.MapOpHs [e] instance Michelson.Typed.Haskell.Value.IsComparable e => Lorentz.Polymorphic.MemOpHs (Data.Set.Internal.Set e) instance Michelson.Typed.Haskell.Value.IsComparable k => Lorentz.Polymorphic.MemOpHs (Data.Map.Internal.Map k v) instance Michelson.Typed.Haskell.Value.IsComparable k => Lorentz.Polymorphic.MemOpHs (Michelson.Typed.Haskell.Value.BigMap k v) -- | Scope-related constraints used in Lorentz. module Lorentz.Constraints -- | Constraint applied to parameter type. type NiceParameter a = (KnownValue a, ProperParameterBetterErrors (ToT a)) type NiceStorage a = (KnownValue a, ProperStorageBetterErrors (ToT a)) type NiceConstant a = (KnownValue a, ProperConstantBetterErrors (ToT a)) type NicePackedValue a = (KnownValue a, ProperPackedValBetterErrors (ToT a)) type NiceUnpackedValue a = (KnownValue a, ProperUnpackedValBetterErrors (ToT a)) type NiceFullPackedValue a = (NicePackedValue a, NiceUnpackedValue a) type NicePrintedValue a = (KnownValue a, ProperPrintedValBetterErrors (ToT a)) niceParameterEvi :: forall a. NiceParameter a :- ParameterScope (ToT a) niceStorageEvi :: forall a. NiceStorage a :- StorageScope (ToT a) niceConstantEvi :: forall a. NiceConstant a :- ConstantScope (ToT a) nicePackedValueEvi :: forall a. NicePackedValue a :- PackedValScope (ToT a) niceUnpackedValueEvi :: forall a. NiceUnpackedValue a :- UnpackedValScope (ToT a) nicePrintedValueEvi :: forall a. NicePrintedValue a :- PrintedValScope (ToT a) class (IsoValue a, HasNoNestedBigMaps (ToT a)) => CanHaveBigMap a -- | Gathers constraints, commonly required for values. class (IsoValue a, Typeable (ToT a), SingI (ToT a)) => KnownValue a class (IsoValue a, Typeable (ToCT a), SingI (ToCT a)) => KnownCValue a -- | Ensure given type does not contain "operation". class (IsoValue a, ForbidOp (ToT a)) => NoOperation a class (IsoValue a, ForbidContract (ToT a)) => NoContractType a class (IsoValue a, ForbidBigMap (ToT a)) => NoBigMap a -- | From a Dict, takes a value in an environment where the instance -- witnessed by the Dict is in scope, and evaluates it. -- -- Essentially a deconstruction of a Dict into its -- continuation-style form. -- -- Can also be used to deconstruct an entailment, a :- b, -- using a context a. -- --
--   withDict :: Dict c -> (c => r) -> r
--   withDict :: a => (a :- c) -> (c => r) -> r
--   
withDict :: HasDict c e => e -> (c -> r) -> r instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Scope.HasNoNestedBigMaps (Michelson.Typed.Haskell.Value.ToT a)) => Lorentz.Constraints.CanHaveBigMap a instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Scope.ForbidBigMap (Michelson.Typed.Haskell.Value.ToT a)) => Lorentz.Constraints.NoBigMap a instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Scope.ForbidContract (Michelson.Typed.Haskell.Value.ToT a)) => Lorentz.Constraints.NoContractType a instance (Michelson.Typed.Haskell.Value.IsoValue a, Michelson.Typed.Scope.ForbidOp (Michelson.Typed.Haskell.Value.ToT a)) => Lorentz.Constraints.NoOperation a instance (Michelson.Typed.Haskell.Value.IsoValue a, Data.Typeable.Internal.Typeable (Michelson.Typed.Haskell.Value.ToCT a), Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.ToCT a)) => Lorentz.Constraints.KnownCValue a instance (Michelson.Typed.Haskell.Value.IsoValue a, Data.Typeable.Internal.Typeable (Michelson.Typed.Haskell.Value.ToT a), Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.ToT a)) => Lorentz.Constraints.KnownValue a -- | Re-exports typed Value, CValue, some core types, some helpers and -- defines aliases for constructors of typed values. module Lorentz.Value type Value = Value' Instr -- | Isomorphism between Michelson values and plain Haskell types. -- -- Default implementation of this typeclass converts ADTs to Michelson -- "pair"s and "or"s. class IsoValue a where { -- | Type function that converts a regular Haskell type into a T -- type. type family ToT a :: T; type ToT a = GValueType (Rep a); } -- | Converts a Haskell structure into Value representation. toVal :: IsoValue a => a -> Value (ToT a) -- | Converts a Haskell structure into Value representation. toVal :: (IsoValue a, Generic a, GIsoValue (Rep a), ToT a ~ GValueType (Rep a)) => a -> Value (ToT a) -- | Converts a Value into Haskell type. fromVal :: IsoValue a => Value (ToT a) -> a -- | Converts a Value into Haskell type. fromVal :: (IsoValue a, Generic a, GIsoValue (Rep a), ToT a ~ GValueType (Rep a)) => Value (ToT a) -> a -- | Isomorphism between Michelson primitive values and plain Haskell -- types. class IsoCValue a where { -- | Type function that converts a regular Haskell type into a comparable -- type (which has kind CT). type family ToCT a :: CT; } -- | Converts a single Haskell value into CVal representation. toCVal :: IsoCValue a => a -> CValue (ToCT a) -- | Converts a CVal value into a single Haskell value. fromCVal :: IsoCValue a => CValue (ToCT a) -> a -- | Representation of comparable value in Michelson language. -- -- By specification, we're allowed to compare only following types: int, -- nat, string, bytes, mutez, bool, key_hash, timestamp, address. -- -- Only these values can be used as map keys or set elements. data CValue t [CvInt] :: Integer -> CValue 'CInt [CvNat] :: Natural -> CValue 'CNat [CvString] :: MText -> CValue 'CString [CvBytes] :: ByteString -> CValue 'CBytes [CvMutez] :: Mutez -> CValue 'CMutez [CvBool] :: Bool -> CValue 'CBool [CvKeyHash] :: KeyHash -> CValue 'CKeyHash [CvTimestamp] :: Timestamp -> CValue 'CTimestamp [CvAddress] :: EpAddress -> CValue 'CAddress -- | Invariant: Jn# and Jp# are used iff value doesn't fit in -- S# -- -- Useful properties resulting from the invariants: -- -- data Integer -- | Type representing arbitrary-precision non-negative integers. -- --
--   >>> 2^100 :: Natural
--   1267650600228229401496703205376
--   
-- -- Operations whose result would be negative throw -- (Underflow :: ArithException), -- --
--   >>> -1 :: Natural
--   *** Exception: arithmetic underflow
--   
data Natural -- | Michelson string value. -- -- This is basically a mere text with limits imposed by the language: -- http://tezos.gitlab.io/zeronet/whitedoc/michelson.html#constants -- Although, this document seems to be not fully correct, and thus we -- applied constraints deduced empirically. -- -- You construct an item of this type using one of the following ways: -- -- -- --
--   >>> [mt|Some text|]
--   MTextUnsafe { unMText = "Some text" }
--   
-- -- data MText data Bool False :: Bool True :: Bool -- | A space-efficient representation of a Word8 vector, supporting -- many efficient operations. -- -- A ByteString contains 8-bit bytes, or by using the operations -- from Data.ByteString.Char8 it can be interpreted as containing -- 8-bit characters. data ByteString -- | Data type corresponding to address structure in Tezos. data Address -- | Address with optional entrypoint name attached to it. TODO: come up -- with better name? data EpAddress EpAddress :: Address -> EpName -> EpAddress -- | Address itself [eaAddress] :: EpAddress -> Address -- | Entrypoint name (might be empty) [eaEntryPoint] :: EpAddress -> EpName -- | Mutez is a wrapper over integer data type. 1 mutez is 1 token (μTz). data Mutez -- | Time in the real world. Use the functions below to convert it to/from -- Unix time in seconds. data Timestamp -- | Identifier of a network (babylonnet, mainnet, test network or other). -- Evaluated as hash of the genesis block. -- -- The only operation supported for this type is packing. Use case: -- multisig contract, for instance, now includes chain ID into signed -- data "in order to add extra replay protection between the main chain -- and the test chain". data ChainId -- | Blake2b_160 hash of a public key. data KeyHash -- | Public cryptographic key used by Tezos. There are three cryptographic -- curves each represented by its own constructor. data PublicKey -- | Cryptographic signatures used by Tezos. Constructors correspond to -- PublicKey constructors. -- -- Tezos distinguishes signatures for different curves. For instance, -- ed25519 signatures and secp256k1 signatures are printed differently -- (have different prefix). However, signatures are packed without -- information about the curve. For this purpose there is a generic -- signature which only stores bytes and doesn't carry information about -- the curve. Apparently unpacking from bytes always produces such -- signature. Unpacking from string produces a signature with curve -- information. data Signature -- | A set of values a. data Set a -- | A Map from keys k to values a. data Map k a newtype BigMap k v BigMap :: Map k v -> BigMap k v [unBigMap] :: BigMap k v -> Map k v type Operation = Operation' Instr -- | The Maybe type encapsulates an optional value. A value of type -- Maybe a either contains a value of type a -- (represented as Just a), or it is empty (represented -- as Nothing). Using Maybe is a good way to deal with -- errors or exceptional cases without resorting to drastic measures such -- as error. -- -- The Maybe type is also a monad. It is a simple kind of error -- monad, where all errors are represented by Nothing. A richer -- error monad can be built using the Either type. data Maybe a Nothing :: Maybe a Just :: a -> Maybe a type List = [] -- | Since Contract name is used to designate contract code, lets -- call analogy of TContract type as follows. data ContractRef (arg :: Type) ContractRef :: Address -> SomeEntryPointCall arg -> ContractRef [crAddress] :: ContractRef -> Address [crEntryPoint] :: ContractRef -> SomeEntryPointCall arg -- | Address associated with the contract of given type. -- -- Places where ContractAddr can appear are now severely -- limited, this type gives you type-safety of ContractAddr but -- still can be used everywhere. -- -- This may be refer to specific entrypoint of the contract, in such case -- type parameter p stands for argument of that entrypoint like -- in ContractAddr. -- -- You still cannot be sure that the referred contract exists though. newtype FutureContract p FutureContract :: EpAddress -> FutureContract p [futureContractAddress] :: FutureContract p -> EpAddress type EntryPointCall param arg = EntryPointCallT (ToT param) (ToT arg) type SomeEntryPointCall arg = SomeEntryPointCallT (ToT arg) -- | Safely create Mutez. -- -- This is recommended way to create Mutez from a numeric -- literal; you can't construct all valid Mutez values using -- this function but for small values it works neat. -- -- Warnings displayed when trying to construct invalid Natural or -- Word literal are hardcoded for these types in GHC -- implementation, so we can only exploit these existing rules. toMutez :: Word32 -> Mutez -- | QuasyQuoter for constructing Michelson strings. -- -- Validity of result will be checked at compile time. Note: -- -- mt :: QuasiQuoter timestampFromSeconds :: Integer -> Timestamp timestampFromUTCTime :: UTCTime -> Timestamp -- | Quote a value of type Timestamp in -- yyyy-mm-ddThh:mm:ss[.sss]Z format. -- --
--   >>> formatTimestamp [timestampQuote| 2019-02-21T16:54:12.2344523Z |]
--   "2019-02-21T16:54:12Z"
--   
-- -- Inspired by 'time-quote' library. timestampQuote :: QuasiQuoter -- | Replace type argument of ContractAddr with isomorphic one. coerceContractRef :: ToT a ~ ToT b => ContractRef a -> ContractRef b -- | Turn future contract into actual contract. embodyFutureContract :: forall arg. (NiceParameter arg, HasCallStack) => FutureContract arg -> ContractRef arg -- | Convert something to Address in Haskell world. -- -- Use this when you want to access state of the contract and are not -- interested in calling it. class ToAddress a toAddress :: ToAddress a => a -> Address -- | Convert something to ContractRef in Haskell world. class ToContractRef (cp :: Type) (contract :: Type) toContractRef :: (ToContractRef cp contract, HasCallStack) => contract -> ContractRef cp -- | Convert something from ContractAddr in Haskell world. class FromContractRef (cp :: Type) (contract :: Type) fromContractAddr :: FromContractRef cp contract => ContractRef cp -> contract convertContractRef :: forall cp contract2 contract1. (ToContractRef cp contract1, FromContractRef cp contract2) => contract1 -> contract2 -- | A class for types with a default value. class Default a -- | The default value for this type. def :: Default a => a instance forall k (p :: k). Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Value.FutureContract p) instance forall k (p :: k). GHC.Generics.Generic (Lorentz.Value.FutureContract p) instance (cp Data.Type.Equality.~ cp') => Lorentz.Value.FromContractRef cp (Michelson.Typed.Haskell.Value.ContractRef cp') instance (cp Data.Type.Equality.~ cp') => Lorentz.Value.FromContractRef cp (Lorentz.Value.FutureContract cp') instance Lorentz.Value.FromContractRef cp Michelson.Typed.EntryPoints.EpAddress instance Lorentz.Value.FromContractRef cp Tezos.Address.Address instance (cp Data.Type.Equality.~ cp') => Lorentz.Value.ToContractRef cp (Michelson.Typed.Haskell.Value.ContractRef cp') instance (Lorentz.Constraints.NiceParameter cp, cp Data.Type.Equality.~ cp') => Lorentz.Value.ToContractRef cp (Lorentz.Value.FutureContract cp') instance Lorentz.Constraints.NiceParameter cp => Lorentz.Value.ToContractRef cp Michelson.Typed.EntryPoints.EpAddress instance Lorentz.Constraints.NiceParameter cp => Lorentz.Value.ToContractRef cp Tezos.Address.Address instance Lorentz.Value.ToAddress Tezos.Address.Address instance Lorentz.Value.ToAddress Michelson.Typed.EntryPoints.EpAddress instance forall k (cp :: k). Lorentz.Value.ToAddress (Lorentz.Value.FutureContract cp) instance Lorentz.Value.ToAddress (Michelson.Typed.Haskell.Value.ContractRef cp) -- | Type families from Arith lifted to Haskell types. module Lorentz.Arith -- | Lifted AithOp. class (ArithOp aop (ToCT n) (ToCT m), IsComparable n, IsComparable m, Typeable (ToCT n), Typeable (ToCT m), ToT (ArithResHs aop n m) ~ 'Tc (ArithRes aop (ToCT n) (ToCT m))) => ArithOpHs (aop :: Type) (n :: Type) (m :: Type) where { type family ArithResHs aop n m :: Type; } class (Typeable (ToCT n), IsComparable n, CompareOp (ToCT n)) => CompareOpHs n -- | Lifted UnaryAithOp. class (UnaryArithOp aop (ToCT n), IsComparable n, Typeable (ToCT n), ToT (UnaryArithResHs aop n) ~ 'Tc (UnaryArithRes aop (ToCT n))) => UnaryArithOpHs (aop :: Type) (n :: Type) where { type family UnaryArithResHs aop n :: Type; } instance (n Data.Type.Equality.~ m, Lorentz.Arith.CompareOpHs n) => Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Compare n m instance Lorentz.Arith.CompareOpHs GHC.Types.Bool instance Lorentz.Arith.CompareOpHs Tezos.Address.Address instance Lorentz.Arith.CompareOpHs Michelson.Typed.EntryPoints.EpAddress instance Lorentz.Arith.CompareOpHs GHC.Natural.Natural instance Lorentz.Arith.CompareOpHs GHC.Integer.Type.Integer instance Lorentz.Arith.CompareOpHs Michelson.Text.MText instance Lorentz.Arith.CompareOpHs Data.ByteString.Internal.ByteString instance Lorentz.Arith.CompareOpHs Tezos.Core.Timestamp instance Lorentz.Arith.CompareOpHs Tezos.Core.Mutez instance Lorentz.Arith.CompareOpHs Tezos.Crypto.KeyHash instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Abs GHC.Integer.Type.Integer instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Neg GHC.Integer.Type.Integer instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Neg GHC.Natural.Natural instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Not GHC.Integer.Type.Integer instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Not GHC.Natural.Natural instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Not GHC.Types.Bool instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Eq' GHC.Integer.Type.Integer instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Neq GHC.Integer.Type.Integer instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Lt GHC.Integer.Type.Integer instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Gt GHC.Integer.Type.Integer instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Le GHC.Integer.Type.Integer instance Lorentz.Arith.UnaryArithOpHs Michelson.Typed.Arith.Ge GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Add GHC.Natural.Natural GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Add GHC.Integer.Type.Integer GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Add GHC.Natural.Natural GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Add GHC.Integer.Type.Integer GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Add Tezos.Core.Timestamp GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Add GHC.Integer.Type.Integer Tezos.Core.Timestamp instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Add Tezos.Core.Mutez Tezos.Core.Mutez instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Sub GHC.Natural.Natural GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Sub GHC.Integer.Type.Integer GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Sub GHC.Natural.Natural GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Sub GHC.Integer.Type.Integer GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Sub Tezos.Core.Timestamp GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Sub Tezos.Core.Timestamp Tezos.Core.Timestamp instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Sub Tezos.Core.Mutez Tezos.Core.Mutez instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Mul GHC.Natural.Natural GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Mul GHC.Integer.Type.Integer GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Mul GHC.Natural.Natural GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Mul GHC.Integer.Type.Integer GHC.Integer.Type.Integer instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Mul GHC.Natural.Natural Tezos.Core.Mutez instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Mul Tezos.Core.Mutez GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Or GHC.Natural.Natural GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Or GHC.Types.Bool GHC.Types.Bool instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.And GHC.Integer.Type.Integer GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.And GHC.Natural.Natural GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.And GHC.Types.Bool GHC.Types.Bool instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Xor GHC.Natural.Natural GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Xor GHC.Types.Bool GHC.Types.Bool instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Lsl GHC.Natural.Natural GHC.Natural.Natural instance Lorentz.Arith.ArithOpHs Michelson.Typed.Arith.Lsr GHC.Natural.Natural GHC.Natural.Natural -- | Packing utilities. module Lorentz.Pack lPackValue :: forall a. NicePackedValue a => a -> ByteString lUnpackValue :: forall a. NiceUnpackedValue a => ByteString -> Either UnpackError a -- | Foundation of Lorentz development. module Lorentz.Base -- | Alias for instruction which hides inner types representation via -- T. newtype (inp :: [Type]) :-> (out :: [Type]) LorentzInstr :: RemFail Instr (ToTs inp) (ToTs out) -> (:->) [unLorentzInstr] :: (:->) -> RemFail Instr (ToTs inp) (ToTs out) infixr 1 :-> -- | Alias for :->, seems to make signatures more readable -- sometimes. -- -- Let's someday decide which one of these two should remain. type (%>) = (:->) infixr 1 %> type (&) (a :: Type) (b :: [Type]) = a : b infixr 2 & (#) :: (a :-> b) -> (b :-> c) -> a :-> c infixl 8 # pattern I :: Instr (ToTs inp) (ToTs out) -> inp :-> out pattern FI :: (forall out'. Instr (ToTs inp) out') -> inp :-> out iGenericIf :: (forall s'. Instr (ToTs a) s' -> Instr (ToTs b) s' -> Instr (ToTs c) s') -> (a :-> s) -> (b :-> s) -> c :-> s iAnyCode :: (inp :-> out) -> Instr (ToTs inp) (ToTs out) iNonFailingCode :: HasCallStack => (inp :-> out) -> Instr (ToTs inp) (ToTs out) iMapAnyCode :: (forall o'. Instr (ToTs i1) o' -> Instr (ToTs i2) o') -> (i1 :-> o) -> i2 :-> o -- | Parse textual representation of a Michelson value and turn it into -- corresponding Haskell value. -- -- Note: it won't work in some complex cases, e. g. if there is a lambda -- which uses an instruction which depends on current contract's type. -- Obviously it can not work, because we don't have any information about -- a contract to which this value belongs (there is no such contract at -- all). parseLorentzValue :: forall v. (IsoValue v, SingI (ToT v), Typeable (ToT v)) => Text -> Either ParseLorentzError v -- | Lorentz version of transformStrings. transformStringsLorentz :: Bool -> (MText -> MText) -> (inp :-> out) -> inp :-> out -- | Lorentz version of transformBytes. transformBytesLorentz :: Bool -> (ByteString -> ByteString) -> (inp :-> out) -> inp :-> out optimizeLorentz :: (inp :-> out) -> inp :-> out optimizeLorentzWithConf :: OptimizerConf -> (inp :-> out) -> inp :-> out type ContractOut st = '[([Operation], st)] type Contract cp st = '[(cp, st)] :-> ContractOut st data SomeContract [SomeContract] :: (NiceParameter cp, NiceStorage st) => Contract cp st -> SomeContract type Lambda i o = '[i] :-> '[o] instance GHC.Classes.Eq Lorentz.Base.ParseLorentzError instance GHC.Show.Show Lorentz.Base.ParseLorentzError instance GHC.Classes.Eq (inp Lorentz.Base.:-> out) instance GHC.Show.Show (inp Lorentz.Base.:-> out) instance Formatting.Buildable.Buildable Lorentz.Base.ParseLorentzError instance GHC.Base.Semigroup (s Lorentz.Base.:-> s) instance GHC.Base.Monoid (s Lorentz.Base.:-> s) -- | Stack zipping. -- -- This module provides functions for flattening stacks into tuples. -- -- Also here we define an instance which turns any instruction, not only -- lambdas, into a valid value. module Lorentz.Zip -- | Zipping stack into tuple and back. class ZipInstr (s :: [Type]) where { -- | A type which contains the whole stack zipped. type family ZippedStack s :: Type; } -- | Fold given stack into single value. zipInstr :: ZipInstr s => s :-> '[ZippedStack s] -- | Unfold given stack from a single value. unzipInstr :: ZipInstr s => '[ZippedStack s] :-> s -- | Require several stacks to comply ZipInstr constraint. type ZipInstrs ss = Each '[ZipInstr] ss -- | Flatten both ends of instruction stack. zippingStack :: ZipInstrs [inp, out] => (inp :-> out) -> Lambda (ZippedStack inp) (ZippedStack out) -- | Unflatten both ends of instruction stack. unzippingStack :: ZipInstrs [inp, out] => Lambda (ZippedStack inp) (ZippedStack out) -> inp :-> out instance Lorentz.Zip.ZipInstr '[] instance Lorentz.Zip.ZipInstr '[a] instance Lorentz.Zip.ZipInstr ((a, b) : s) => Lorentz.Zip.ZipInstr (a : b : s) instance (Lorentz.Zip.ZipInstr inp, Lorentz.Zip.ZipInstr out) => Michelson.Typed.Haskell.Value.IsoValue (inp Lorentz.Base.:-> out) module Lorentz.Ext stackRef :: forall (gn :: Nat) st n. (n ~ ToPeano gn, SingI n, KnownPeano n, RequireLongerThan st n) => PrintComment st printComment :: PrintComment (ToTs s) -> s :-> s testAssert :: (Typeable (ToTs out), HasCallStack) => Text -> PrintComment (ToTs inp) -> (inp :-> (Bool & out)) -> inp :-> inp stackType :: forall s. s :-> s module Lorentz.EntryPoints -- | Which entrypoints given parameter declares. class NiceParameter p => ParameterEntryPoints p parameterEntryPoints :: ParameterEntryPoints p => ParameterEntryPointsSplit p -- | Implementation of parameterEntryPoints. newtype ParameterEntryPointsSplit p ParameterEntryPointsSplit :: Notes (ToT p) -> ParameterEntryPointsSplit p -- | Parameter annotations which declare necessary entrypoints. [pesNotes] :: ParameterEntryPointsSplit p -> Notes (ToT p) mapParameterEntryPoints :: ToT a ~ ToT b => (a -> b) -> ParameterEntryPointsSplit a -> ParameterEntryPointsSplit b -- | No entrypoints declared, parameter type will serve as argument type of -- the only existing entrypoint. pepNone :: SingI (ToT p) => ParameterEntryPointsSplit p -- | Fits for case when your contract exposes multiple entrypoints via -- having sum type as its parameter. -- -- In particular, this will attach field annotations to immediate -- parameter "arms" which will be named as corresponding constructor -- names. pepPlain :: PesEntryPointsC 'False cp st => ParameterEntryPointsSplit cp -- | Similar to pesEntryPoints, but for case of parameter being -- defined as several nested datatypes. -- -- In particular, this will traverse sum types recursively, stopping at -- Michelson primitives (like Natural) and constructors with -- number of fields different from one. pepRecursive :: PesEntryPointsC 'True cp st => ParameterEntryPointsSplit cp instance (Lorentz.EntryPoints.GHasTypeAnn x, GHC.TypeLits.KnownSymbol ctor) => Lorentz.EntryPoints.GEntryPointsNotes 'GHC.Types.False ep (GHC.Generics.C1 ('GHC.Generics.MetaCons ctor _1 _2) x) instance (Lorentz.EntryPoints.GHasTypeAnn x, GHC.TypeLits.KnownSymbol ctor) => Lorentz.EntryPoints.GEntryPointsNotes 'GHC.Types.True 'Lorentz.EntryPoints.EPLeaf (GHC.Generics.C1 ('GHC.Generics.MetaCons ctor _1 _2) x) instance (Lorentz.EntryPoints.GHasTypeAnn (GHC.Generics.Rep a), Michelson.Typed.Haskell.Value.GValueType (GHC.Generics.Rep a) Data.Type.Equality.~ Michelson.Typed.Haskell.Value.ToT a) => Lorentz.EntryPoints.HasTypeAnn a instance Lorentz.EntryPoints.GHasTypeAnn GHC.Generics.U1 instance Lorentz.EntryPoints.GHasTypeAnn x => Lorentz.EntryPoints.GHasTypeAnn (GHC.Generics.M1 i0 i1 x) instance (Lorentz.EntryPoints.GHasTypeAnn x, Lorentz.EntryPoints.GHasTypeAnn y) => Lorentz.EntryPoints.GHasTypeAnn (x GHC.Generics.:+: y) instance (Lorentz.EntryPoints.GHasTypeAnn x, Lorentz.EntryPoints.GHasTypeAnn y) => Lorentz.EntryPoints.GHasTypeAnn (x GHC.Generics.:*: y) instance Lorentz.EntryPoints.HasTypeAnn x => Lorentz.EntryPoints.GHasTypeAnn (GHC.Generics.Rec0 x) instance (Lorentz.EntryPoints.HasTypeAnn a, GHC.TypeLits.KnownSymbol name) => Lorentz.EntryPoints.HasTypeAnn (Named.Internal.NamedF Data.Functor.Identity.Identity a name) instance (Lorentz.EntryPoints.HasTypeAnn (GHC.Maybe.Maybe a), GHC.TypeLits.KnownSymbol name) => Lorentz.EntryPoints.HasTypeAnn (Named.Internal.NamedF GHC.Maybe.Maybe a name) instance Lorentz.EntryPoints.HasTypeAnn a => Lorentz.EntryPoints.HasTypeAnn (GHC.Maybe.Maybe a) instance Lorentz.EntryPoints.HasTypeAnn GHC.Integer.Type.Integer instance Lorentz.EntryPoints.HasTypeAnn GHC.Natural.Natural instance Lorentz.EntryPoints.HasTypeAnn Michelson.Text.MText instance Lorentz.EntryPoints.HasTypeAnn GHC.Types.Bool instance Lorentz.EntryPoints.HasTypeAnn Data.ByteString.Internal.ByteString instance Lorentz.EntryPoints.HasTypeAnn Tezos.Core.Mutez instance Lorentz.EntryPoints.HasTypeAnn Tezos.Address.Address instance Lorentz.EntryPoints.HasTypeAnn Michelson.Typed.EntryPoints.EpAddress instance Lorentz.EntryPoints.HasTypeAnn Tezos.Crypto.KeyHash instance Lorentz.EntryPoints.HasTypeAnn Tezos.Core.Timestamp instance Lorentz.EntryPoints.HasTypeAnn Tezos.Crypto.PublicKey instance Lorentz.EntryPoints.HasTypeAnn Tezos.Crypto.Signature instance Lorentz.EntryPoints.HasTypeAnn a => Lorentz.EntryPoints.HasTypeAnn (Michelson.Typed.Haskell.Value.ContractRef a) instance Lorentz.EntryPoints.HasTypeAnn v => Lorentz.EntryPoints.HasTypeAnn (Data.Map.Internal.Map k v) instance Lorentz.EntryPoints.HasTypeAnn v => Lorentz.EntryPoints.HasTypeAnn (Michelson.Typed.Haskell.Value.BigMap k v) instance (Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.ToCT v), Data.Typeable.Internal.Typeable (Michelson.Typed.Haskell.Value.ToCT v)) => Lorentz.EntryPoints.HasTypeAnn (Data.Set.Internal.Set v) instance Lorentz.EntryPoints.HasTypeAnn a => Lorentz.EntryPoints.HasTypeAnn [a] instance Lorentz.EntryPoints.HasTypeAnn Michelson.Typed.Aliases.Operation instance (Lorentz.EntryPoints.HasTypeAnn (Lorentz.Zip.ZippedStack i), Lorentz.EntryPoints.HasTypeAnn (Lorentz.Zip.ZippedStack o)) => Lorentz.EntryPoints.HasTypeAnn (i Lorentz.Base.:-> o) instance (Lorentz.EntryPoints.EntryPointsNotes deep ep a, Michelson.Typed.Haskell.Value.IsGenericIsoValue a) => Lorentz.EntryPoints.GEntryPointsNotes deep ep (GHC.Generics.Rec0 a) instance Lorentz.EntryPoints.GEntryPointsNotes deep ep x => Lorentz.EntryPoints.GEntryPointsNotes deep ep (GHC.Generics.D1 i x) instance (Lorentz.EntryPoints.GEntryPointsNotes deep epx x, Lorentz.EntryPoints.GEntryPointsNotes deep epy y) => Lorentz.EntryPoints.GEntryPointsNotes deep ('Lorentz.EntryPoints.EPNode epx epy) (x GHC.Generics.:+: y) instance (ep Data.Type.Equality.~ 'Lorentz.EntryPoints.EPNode epx epy, Lorentz.EntryPoints.GEntryPointsNotes 'GHC.Types.True ep x) => Lorentz.EntryPoints.GEntryPointsNotes 'GHC.Types.True ('Lorentz.EntryPoints.EPNode epx epy) (GHC.Generics.C1 ('GHC.Generics.MetaCons ctor _1 _2) x) instance Lorentz.EntryPoints.GEntryPointsNotes deep ep x => Lorentz.EntryPoints.GEntryPointsNotes deep ep (GHC.Generics.S1 i x) instance Lorentz.EntryPoints.GEntryPointsNotes deep 'Lorentz.EntryPoints.EPLeaf GHC.Generics.U1 instance (Data.Typeable.Internal.Typeable (Michelson.Typed.Haskell.Value.GValueType x), Data.Typeable.Internal.Typeable (Michelson.Typed.Haskell.Value.GValueType y), Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.GValueType x), Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.GValueType y)) => Lorentz.EntryPoints.GEntryPointsNotes deep 'Lorentz.EntryPoints.EPLeaf (x GHC.Generics.:*: y) instance Lorentz.EntryPoints.ParameterEntryPoints () module Lorentz.Run -- | For use outside of Lorentz. compileLorentz :: (inp :-> out) -> Instr (ToTs inp) (ToTs out) -- | Version of compileLorentz specialized to instruction -- corresponding to contract code. compileLorentzContract :: forall cp st. (NiceParameter cp, NiceStorage st, ParameterEntryPoints cp) => Contract cp st -> FullContract (ToT cp) (ToT st) -- | Interpret a Lorentz instruction, for test purposes. interpretLorentzInstr :: (IsoValuesStack inp, IsoValuesStack out) => ContractEnv -> (inp :-> out) -> Rec Identity inp -> Either MichelsonFailed (Rec Identity out) -- | Like interpretLorentzInstr, but works on lambda rather than -- arbitrary instruction. interpretLorentzLambda :: (IsoValue inp, IsoValue out) => ContractEnv -> Lambda inp out -> inp -> Either MichelsonFailed out -- | Lorentz version of analyzer. analyzeLorentz :: (inp :-> out) -> AnalyzerRes -- | Printing lorentz contracts. module Lorentz.Print -- | Pretty-print a Haskell value as Michelson one. printLorentzValue :: forall v. NicePrintedValue v => Bool -> v -> LText -- | Pretty-print a Lorentz contract into Michelson code. printLorentzContract :: forall cp st. (NiceParameter cp, NiceStorage st, ParameterEntryPoints cp) => Bool -> Contract cp st -> LText module Lorentz.TestScenario -- | Type that represents test scenario for Lorentz contract. Simply put, -- it is sequence of pairs (sender, parameter). Using -- this sequence we can perform transfers to the desired contract. type TestScenario param = [(Address, param)] -- | Function to get textual representation of TestScenario, each -- Parameter is printed as a raw Michelson value. This representation can -- later be used in order to run test scenario on real network. -- -- The format for a single contract call is the following: # `printed -- Lorentz parameter` (actually comment) `sender address` `printed raw -- Michelson parameter` showTestScenario :: (Buildable param, NicePrintedValue param) => TestScenario param -> Text instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.TestScenario.Parameter instance GHC.Generics.Generic Lorentz.TestScenario.Parameter module Lorentz.Instr nop :: s :-> s drop :: (a & s) :-> s -- | Drop top n elements from the stack. dropN :: forall (n :: Nat) (s :: [Type]). (SingI (ToPeano n), KnownPeano (ToPeano n), RequireLongerOrSameLength (ToTs s) (ToPeano n), Drop (ToPeano n) (ToTs s) ~ ToTs (Drop (ToPeano n) s)) => s :-> Drop (ToPeano n) s dup :: (a & s) :-> (a & (a & s)) swap :: (a & (b & s)) :-> (b & (a & s)) -- | Version of dig which uses Peano number. It is inteded for -- internal usage in Lorentz. digPeano :: forall (n :: Peano) inp out a. ConstraintDIGLorentz n inp out a => inp :-> out dig :: forall (n :: Nat) inp out a. ConstraintDIGLorentz (ToPeano n) inp out a => inp :-> out dug :: forall (n :: Nat) inp out a. ConstraintDUGLorentz (ToPeano n) inp out a => inp :-> out push :: forall t s. NiceConstant t => t -> s :-> (t & s) some :: (a & s) :-> (Maybe a & s) none :: forall a s. KnownValue a => s :-> (Maybe a & s) unit :: s :-> (() & s) ifNone :: (s :-> s') -> ((a & s) :-> s') -> (Maybe a & s) :-> s' pair :: (a & (b & s)) :-> ((a, b) & s) car :: ((a, b) & s) :-> (a & s) cdr :: ((a, b) & s) :-> (b & s) left :: forall a b s. KnownValue b => (a & s) :-> (Either a b & s) right :: forall a b s. KnownValue a => (b & s) :-> (Either a b & s) ifLeft :: ((a & s) :-> s') -> ((b & s) :-> s') -> (Either a b & s) :-> s' nil :: KnownValue p => s :-> (List p & s) cons :: (a & (List a & s)) :-> (List a & s) size :: SizeOpHs c => (c & s) :-> (Natural & s) emptySet :: KnownCValue e => s :-> (Set e & s) emptyMap :: (KnownCValue k, KnownValue v) => s :-> (Map k v & s) emptyBigMap :: (KnownCValue k, KnownValue v) => s :-> (BigMap k v & s) map :: (MapOpHs c, IsoMapOpRes c b, HasCallStack) => ((MapOpInpHs c & s) :-> (b & s)) -> (c & s) :-> (MapOpResHs c b & s) iter :: (IterOpHs c, HasCallStack) => ((IterOpElHs c & s) :-> s) -> (c & s) :-> s mem :: MemOpHs c => (MemOpKeyHs c & (c & s)) :-> (Bool & s) get :: GetOpHs c => (GetOpKeyHs c & (c & s)) :-> (Maybe (GetOpValHs c) & s) update :: UpdOpHs c => (UpdOpKeyHs c & (UpdOpParamsHs c & (c & s))) :-> (c & s) -- | Helper instruction. -- -- Checks whether given key present in the storage and fails if it is. -- This instruction leaves stack intact. failingWhenPresent :: forall c k s v st e. (MemOpHs c, k ~ MemOpKeyHs c, KnownValue e, st ~ (k & (v & (c & s)))) => (forall s0. (k : s0) :-> (e : s0)) -> st :-> st -- | Like update, but throw an error on attempt to overwrite -- existing entry. updateNew :: forall c k s e. (UpdOpHs c, MemOpHs c, k ~ UpdOpKeyHs c, k ~ MemOpKeyHs c, KnownValue e) => (forall s0. (k : s0) :-> (e : s0)) -> (k & (UpdOpParamsHs c & (c & s))) :-> (c & s) if_ :: (s :-> s') -> (s :-> s') -> (Bool & s) :-> s' ifCons :: ((a & (List a & s)) :-> s') -> (s :-> s') -> (List a & s) :-> s' loop :: (s :-> (Bool & s)) -> (Bool & s) :-> s loopLeft :: ((a & s) :-> (Either a b & s)) -> (Either a b & s) :-> (b & s) lambda :: (ZipInstrs [i, o], KnownValue (ZippedStack i), KnownValue (ZippedStack o)) => (i :-> o) -> s :-> ((i :-> o) & s) exec :: (a & (Lambda a b & s)) :-> (b & s) -- | Similar to exec but works for lambdas with arbitrary size of -- input and output. -- -- Note that this instruction has its arguments flipped, lambda goes -- first. This seems to be the only reasonable way to achieve good -- inference. execute :: forall i o s. Each [KnownList, ZipInstr] [i, o] => ((i :-> o) : (i ++ s)) :-> (o ++ s) apply :: forall a b c s. NiceConstant a => (a & (Lambda (a, b) c & s)) :-> (Lambda b c & s) dip :: forall a s s'. HasCallStack => (s :-> s') -> (a & s) :-> (a & s') type ConstraintDIPNLorentz (n :: Peano) (inp :: [Type]) (out :: [Type]) (s :: [Type]) (s' :: [Type]) = (ConstraintDIPN n (ToTs inp) (ToTs out) (ToTs s) (ToTs s'), ConstraintDIPN' Type n inp out s s') -- | Version of dipN which uses Peano number. It is inteded for -- internal usage in Lorentz. dipNPeano :: forall (n :: Peano) (inp :: [Type]) (out :: [Type]) (s :: [Type]) (s' :: [Type]). ConstraintDIPNLorentz n inp out s s' => (s :-> s') -> inp :-> out dipN :: forall (n :: Nat) (inp :: [Type]) (out :: [Type]) (s :: [Type]) (s' :: [Type]). ConstraintDIPNLorentz (ToPeano n) inp out s s' => (s :-> s') -> inp :-> out failWith :: KnownValue a => (a & s) :-> t cast :: KnownValue a => (a & s) :-> (a & s) pack :: forall a s. NicePackedValue a => (a & s) :-> (ByteString & s) unpack :: forall a s. NiceUnpackedValue a => (ByteString & s) :-> (Maybe a & s) concat :: ConcatOpHs c => (c & (c & s)) :-> (c & s) concat' :: ConcatOpHs c => (List c & s) :-> (c & s) slice :: SliceOpHs c => (Natural & (Natural & (c & s))) :-> (Maybe c & s) isNat :: (Integer & s) :-> (Maybe Natural & s) add :: ArithOpHs Add n m => (n & (m & s)) :-> (ArithResHs Add n m & s) sub :: ArithOpHs Sub n m => (n & (m & s)) :-> (ArithResHs Sub n m & s) rsub :: ArithOpHs Sub n m => (m & (n & s)) :-> (ArithResHs Sub n m & s) mul :: ArithOpHs Mul n m => (n & (m & s)) :-> (ArithResHs Mul n m & s) ediv :: EDivOpHs n m => (n & (m & s)) :-> (Maybe (EDivOpResHs n m, EModOpResHs n m) & s) abs :: UnaryArithOpHs Abs n => (n & s) :-> (UnaryArithResHs Abs n & s) neg :: UnaryArithOpHs Neg n => (n & s) :-> (UnaryArithResHs Neg n & s) lsl :: ArithOpHs Lsl n m => (n & (m & s)) :-> (ArithResHs Lsl n m & s) lsr :: ArithOpHs Lsr n m => (n & (m & s)) :-> (ArithResHs Lsr n m & s) or :: ArithOpHs Or n m => (n & (m & s)) :-> (ArithResHs Or n m & s) and :: ArithOpHs And n m => (n & (m & s)) :-> (ArithResHs And n m & s) xor :: ArithOpHs Xor n m => (n & (m & s)) :-> (ArithResHs Xor n m & s) not :: UnaryArithOpHs Not n => (n & s) :-> (UnaryArithResHs Not n & s) compare :: ArithOpHs Compare n n => (n & (n & s)) :-> (ArithResHs Compare n n & s) eq0 :: UnaryArithOpHs Eq' n => (n & s) :-> (UnaryArithResHs Eq' n & s) neq0 :: UnaryArithOpHs Neq n => (n & s) :-> (UnaryArithResHs Neq n & s) lt0 :: UnaryArithOpHs Lt n => (n & s) :-> (UnaryArithResHs Lt n & s) gt0 :: UnaryArithOpHs Gt n => (n & s) :-> (UnaryArithResHs Gt n & s) le0 :: UnaryArithOpHs Le n => (n & s) :-> (UnaryArithResHs Le n & s) ge0 :: UnaryArithOpHs Ge n => (n & s) :-> (UnaryArithResHs Ge n & s) int :: (Natural & s) :-> (Integer & s) self :: forall p s. NiceParameter p => s :-> (ContractRef p & s) contract :: forall p s. NiceParameter p => (Address & s) :-> (Maybe (ContractRef p) & s) transferTokens :: forall p s. NiceParameter p => (p & (Mutez & (ContractRef p & s))) :-> (Operation & s) setDelegate :: (Maybe KeyHash & s) :-> (Operation & s) createContract :: forall p g s. (NiceStorage g, ParameterEntryPoints p) => Contract p g -> (Maybe KeyHash & (Mutez & (g & s))) :-> (Operation & (Address & s)) implicitAccount :: (KeyHash & s) :-> (ContractRef () & s) now :: s :-> (Timestamp & s) amount :: s :-> (Mutez & s) balance :: s :-> (Mutez & s) checkSignature :: (PublicKey & (Signature & (ByteString & s))) :-> (Bool & s) sha256 :: (ByteString & s) :-> (ByteString & s) sha512 :: (ByteString & s) :-> (ByteString & s) blake2B :: (ByteString & s) :-> (ByteString & s) hashKey :: (PublicKey & s) :-> (KeyHash & s) -- | Warning: STEPS_TO_QUOTA instruction is deprecated in Michelson -- 005 stepsToQuota :: s :-> (Natural & s) -- | Warning: Using source is considered a bad practice. Consider -- using sender instead until further investigation source :: s :-> (Address & s) sender :: s :-> (Address & s) address :: (ContractRef a & s) :-> (Address & s) chainId :: s :-> (ChainId & s) -- | Execute given instruction on truncated stack. -- -- This instruction requires you to specify the piece of stack to -- truncate as type argument. framed :: forall s i o. (KnownList i, KnownList o) => (i :-> o) -> (i ++ s) :-> (o ++ s) class LorentzFunctor (c :: Type -> Type) lmap :: (LorentzFunctor c, KnownValue b) => ((a : s) :-> (b : s)) -> (c a : s) :-> (c b : s) -- | Retain the value only if it is not zero. nonZero :: NonZero t => (t : s) :-> (Maybe t : s) instance Lorentz.Instr.NonZero GHC.Integer.Type.Integer instance Lorentz.Instr.NonZero GHC.Natural.Natural instance Lorentz.Instr.LorentzFunctor GHC.Maybe.Maybe -- | Referenced-by-type versions of some instructions. -- -- They allow to "dip" into stack or copy elements of stack referring -- them by type. Their use is justified, because in most cases there is -- only one element of each type of stack, and in cases when this does -- not hold (e.g. entry point with multiple parameters of the same type), -- it might be a good idea to wrap those types into a newtype or to use -- primitives from named package. -- -- This module is experimental, i.e. everything here should work but may -- be removed in favor of better development practices. -- -- Each instruction is followed with usage example. module Lorentz.Referenced -- | Duplicate an element of stack referring it by type. -- -- If stack contains multiple entries of this type, compile error is -- raised. dupT :: forall a st. DupT st a st => st :-> (a : st) -- | Dip repeatedly until element of the given type is on top of the stack. -- -- If stack contains multiple entries of this type, compile error is -- raised. dipT :: forall a inp dinp dout out. DipT inp a inp dinp dout out => (dinp :-> dout) -> inp :-> out -- | Remove element with the given type from the stack. dropT :: forall a inp dinp dout out. (DipT inp a inp dinp dout out, dinp ~ (a : dout)) => inp :-> out instance ((TypeError ...), dipInp Data.Type.Equality.~ (TypeError ...), out Data.Type.Equality.~ (TypeError ...)) => Lorentz.Referenced.DipT origSt a '[] dipInp dipOut out instance (Data.Type.Bool.If (Util.Type.IsElem a st) (TypeError ...) (() :: Constraint), dipInp Data.Type.Equality.~ (a : st), dipOut Data.Type.Equality.~ out) => Lorentz.Referenced.DipT origSt a (a : st) dipInp dipOut out instance (Lorentz.Referenced.DipT origSt a st dipInp dipOut out, out1 Data.Type.Equality.~ (b : out)) => Lorentz.Referenced.DipT origSt a (b : st) dipInp dipOut out1 instance (TypeError ...) => Lorentz.Referenced.DupT origSt a '[] instance Data.Type.Bool.If (Util.Type.IsElem a st) (TypeError ...) (() :: Constraint) => Lorentz.Referenced.DupT origSt a (a : st) instance Lorentz.Referenced.DupT origSt a st => Lorentz.Referenced.DupT origSt a (b : st) -- | Common primitives. module Lorentz.Common -- | Single entrypoint of a contract. -- -- Note that we cannot make it return [[Operation], store] -- because such entrypoint should've been followed by pair, and -- this is not possible if entrypoint implementation ends with -- failWith. type Entrypoint param store = '[param, store] :-> ContractOut store -- | Version of Entrypoint which accepts no argument. type Entrypoint_ store = '[store] :-> ContractOut store -- | Identity transformations between different Haskell types. module Lorentz.Coercions -- | Whether two types have the same Michelson representation. type Coercible_ a b = ToT a ~ ToT b -- | Convert between values of types that have the same representation. coerce_ :: Coercible_ a b => (a & s) :-> (b & s) gcoerce_ :: Coercible_ (t a) (t b) => (t a : s) :-> (t b : s) -- | Convert between two stacks via failing. fakeCoerce :: s1 :-> s2 -- | Specialized version of coerce_ to unwrap a haskell newtype. coerceUnwrap :: Coercible_ newtyp (Unwrapped newtyp) => (newtyp : s) :-> (Unwrapped newtyp : s) -- | Specialized version of coerce_ to wrap into a haskell newtype. coerceWrap :: Coercible_ newtyp (Unwrapped newtyp) => (Unwrapped newtyp : s) :-> (newtyp : s) -- | Lift given value to a named value. toNamed :: Label name -> (a : s) :-> (NamedF Identity a name : s) -- | Unpack named value. fromNamed :: Label name -> (NamedF Identity a name : s) :-> (a : s) -- | Make up a FutureContract. futureContract :: (Address : s) :-> (FutureContract p : s) -- | Get address referred by FutureContract. unFutureContract :: (FutureContract p : s) :-> (Address : s) -- | Wrapped provides isomorphisms to wrap and unwrap newtypes or -- data types with one constructor. class Wrapped s where { type family Unwrapped s :: Type; } -- | An isomorphism between s and a. -- -- If your type has a Generic instance, _Wrapped' will -- default to _GWrapped', and you can choose to not override it -- with your own definition. _Wrapped' :: Wrapped s => Iso' s (Unwrapped s) -- | This module contains implementation of Extensible values. -- -- Extensible values are an alternative representation of -- sum-types for Michelson. Instead of representing them as nested -- options, we treat them as (Natural, ByteString) pair, where the first -- element of the pair represents the constructor index, while the second -- is a packed argument. -- -- With such a representation sum types can be easily upgraded: it is -- possible to add new elements to the sum type, and the representation -- would not change. -- -- However, such representation essentially limits the applicability of -- the values. This module does not provide Michelson-level function to -- unwrap the value because it would require traversing all the possible -- options in the contract code. While this is possible, it is very -- inefficient. Up to this moment, we have not come up with a decent -- reason to allow such behavior, so Extensible types are write-only in -- Michelson code. They can be unwrapped off-chain with -- fromExtVal. -- -- In order to preserve previous values during migrations, users should -- ONLY APPEND items to the underlying sum type. Changing, reordering and -- deleting items is not allowed and would lead to compatibility -- breakage. Currently, this restriction in not enforced. Only -- no-argument and one-argument constructors are supported. -- -- GOOD: -- `Extensible GoodSumTypeV1` is backwards compatible -- with -- `Extensible GoodSumTypeV2` data GoodSumTypeV1 = A Natural | B data -- GoodSumTypeV2 = A Natural | B | C MText -- -- BAD: -- `Extensible BadSumTypeV1` is NOT backwards compatible -- with -- `Extensible BadSumTypeV2` data BadSumTypeV1 = A | B data BadSumTypeV2 -- = A Natural | B | C MText module Lorentz.Extensible newtype Extensible x Extensible :: (Natural, ByteString) -> Extensible x -- | Errors related to fromExtVal conversion data ExtConversionError ConstructorIndexNotFound :: Natural -> ExtConversionError ArgumentUnpackFailed :: ExtConversionError type ExtVal x = (Generic x, GExtVal x (Rep x)) -- | Information to be provided for documenting some Extensible -- x. class Typeable x => ExtensibleHasDoc x -- | Implementation for typeDocName of the corresponding -- Extensible. extensibleDocName :: ExtensibleHasDoc x => Proxy x -> Text -- | Implementation for typeDocDependencies of the corresponding -- Extensible. extensibleDocDependencies :: ExtensibleHasDoc x => Proxy x -> [SomeTypeWithDoc] -- | Implementation for typeDocDependencies of the corresponding -- Extensible. extensibleDocDependencies :: (ExtensibleHasDoc x, Generic x, GTypeHasDoc (Rep x)) => Proxy x -> [SomeTypeWithDoc] -- | Overall description of this type. extensibleDocMdDescription :: ExtensibleHasDoc x => Markdown -- | Converts a value from a Haskell representation to its extensible -- Michelson representation (i.e. (Natural, Bytestring) pair). toExtVal :: ExtVal a => a -> Extensible a -- | Converts a value from an extensible Michelson representation to its -- Haskell sum-type representation. Fails if the Michelson representation -- points to a nun-existent constructor, or if we failed to unpack the -- argument. fromExtVal :: ExtVal a => Extensible a -> Either ExtConversionError a -- | Wraps an argument on top of the stack into an Extensible -- representation wrapExt :: forall t (n :: Nat) name field s. WrapExtC t n name field s => Label ("c" `AppendSymbol` name) -> AppendCtorField field s :-> (Extensible t : s) type WrapExtC t n name field s = ( 'Ctor n name field ~ LookupCtor name (EnumerateCtors (GetCtors t)), WrapExt field, KnownNat n) instance GHC.Show.Show Lorentz.Extensible.ExtConversionError instance GHC.Classes.Eq Lorentz.Extensible.ExtConversionError instance forall k (x :: k). Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Extensible.Extensible x) instance forall k (x :: k). GHC.Show.Show (Lorentz.Extensible.Extensible x) instance forall k (x :: k). GHC.Classes.Eq (Lorentz.Extensible.Extensible x) instance forall k (x :: k). GHC.Generics.Generic (Lorentz.Extensible.Extensible x) instance (GHC.TypeNats.KnownNat pos, GHC.TypeLits.KnownSymbol name, Michelson.Typed.Haskell.Doc.TypeHasDoc param, param Data.Type.Equality.~ Michelson.Typed.Haskell.Instr.Sum.ExtractCtorField field) => Lorentz.Extensible.DocumentCtor ('Lorentz.Extensible.Ctor pos name field) instance (Lorentz.Extensible.ExtensibleHasDoc x, Util.Type.ReifyList Lorentz.Extensible.DocumentCtor (Lorentz.Extensible.EnumerateCtors (Lorentz.Extensible.GetCtors x))) => Michelson.Typed.Haskell.Doc.TypeHasDoc (Lorentz.Extensible.Extensible x) instance forall k (t :: k) (x :: * -> *) (i :: GHC.Generics.Meta). Lorentz.Extensible.GExtVal t x => Lorentz.Extensible.GExtVal t (GHC.Generics.D1 i x) instance ('Lorentz.Extensible.Ctor n name 'Michelson.Typed.Haskell.Instr.Sum.NoFields Data.Type.Equality.~ Lorentz.Extensible.LookupCtor name (Lorentz.Extensible.EnumerateCtors (Lorentz.Extensible.GetCtors t)), GHC.TypeNats.KnownNat n) => Lorentz.Extensible.GExtVal t (GHC.Generics.C1 ('GHC.Generics.MetaCons name _1 _2) GHC.Generics.U1) instance (Lorentz.Constraints.NiceFullPackedValue param, 'Lorentz.Extensible.Ctor n name ('Michelson.Typed.Haskell.Instr.Sum.OneField param) Data.Type.Equality.~ Lorentz.Extensible.LookupCtor name (Lorentz.Extensible.EnumerateCtors (Lorentz.Extensible.GetCtors t)), GHC.TypeNats.KnownNat n) => Lorentz.Extensible.GExtVal t (GHC.Generics.C1 ('GHC.Generics.MetaCons name _1 _2) (GHC.Generics.S1 _3 (GHC.Generics.Rec0 param))) instance forall k (t :: k) (x :: * -> *) (y :: * -> *). (Lorentz.Extensible.GExtVal t x, Lorentz.Extensible.GExtVal t y) => Lorentz.Extensible.GExtVal t (x GHC.Generics.:+: y) instance Formatting.Buildable.Buildable Lorentz.Extensible.ExtConversionError instance Lorentz.Constraints.NicePackedValue param => Lorentz.Extensible.WrapExt ('Michelson.Typed.Haskell.Instr.Sum.OneField param) instance Lorentz.Extensible.WrapExt 'Michelson.Typed.Haskell.Instr.Sum.NoFields module Lorentz.ADT -- | Allows field access and modification. type HasField dt fname = (InstrGetFieldC dt fname, InstrSetFieldC dt fname) -- | Like HasField, but allows constrainting field type. type HasFieldOfType dt fname fieldTy = (HasField dt fname, GetFieldType dt fname ~ fieldTy) -- | Shortcut for multiple HasFieldOfType constraints. type family HasFieldsOfType (dt :: Type) (fs :: [NamedField]) :: Constraint -- | A pair of field name and type. data NamedField NamedField :: Symbol -> Type -> NamedField type n := ty = 'NamedField n ty infixr 0 := -- | Extract a field of a datatype replacing the value of this datatype -- with the extracted field. -- -- For this and the following functions you have to specify field name -- which is either record name or name attached with (:!) -- operator. toField :: forall dt name st. InstrGetFieldC dt name => Label name -> (dt & st) :-> (GetFieldType dt name & st) -- | Like toField, but leaves field named. toFieldNamed :: forall dt name st. InstrGetFieldC dt name => Label name -> (dt & st) :-> ((name :! GetFieldType dt name) & st) -- | Extract a field of a datatype, leaving the original datatype on stack. getField :: forall dt name st. InstrGetFieldC dt name => Label name -> (dt & st) :-> (GetFieldType dt name & (dt : st)) -- | Like getField, but leaves field named. getFieldNamed :: forall dt name st. InstrGetFieldC dt name => Label name -> (dt & st) :-> ((name :! GetFieldType dt name) & (dt : st)) -- | Set a field of a datatype. setField :: forall dt name st. InstrSetFieldC dt name => Label name -> (GetFieldType dt name : (dt : st)) :-> (dt : st) -- | Apply given modifier to a datatype field. modifyField :: forall dt name st. (InstrGetFieldC dt name, InstrSetFieldC dt name) => Label name -> (forall st0. (GetFieldType dt name : st0) :-> (GetFieldType dt name : st0)) -> (dt & st) :-> (dt & st) -- | Make up a datatype. You provide a pack of individual fields -- constructors. -- -- Each element of the accepted record should be an instruction wrapped -- with fieldCtor function. This instruction will have access to -- the stack at the moment of calling construct. Instructions -- have to output fields of the built datatype, one per instruction; -- instructions order is expected to correspond to the order of fields in -- the datatype. construct :: forall dt st. (InstrConstructC dt, RMap (ConstructorFieldTypes dt)) => Rec (FieldConstructor st) (ConstructorFieldTypes dt) -> st :-> (dt & st) -- | Version of construct which accepts tuple of field constructors. constructT :: forall dt fctors st. (InstrConstructC dt, RMap (ConstructorFieldTypes dt), fctors ~ Rec (FieldConstructor st) (ConstructorFieldTypes dt), RecFromTuple fctors) => IsoRecTuple fctors -> st :-> (dt & st) -- | Lift an instruction to field constructor. fieldCtor :: HasCallStack => (st :-> (f & st)) -> FieldConstructor st f -- | Wrap entry in constructor. Useful for sum types. wrap_ :: forall dt name st. InstrWrapC dt name => Label name -> AppendCtorField (GetCtorField dt name) st :-> (dt & st) -- | Pattern match on the given sum type. -- -- You have to provide a Rec containing case branches. To -- construct a case branch use /-> operator. case_ :: forall dt out inp. (InstrCaseC dt inp out, RMap (CaseClauses dt)) => Rec (CaseClauseL inp out) (CaseClauses dt) -> (dt & inp) :-> out -- | Like case_, accepts a tuple of clauses, which may be more -- convenient. -- -- If user is experiencing problems with wierd errors about tuples while -- using this function, he should take look at Instances and -- ensure that his tuple isn't bigger than generated instances, if so, he -- should probably extend number of generated instances. caseT :: forall dt out inp clauses. CaseTC dt out inp clauses => IsoRecTuple clauses -> (dt & inp) :-> out -- | Wrap entry in constructor. Useful for sum types. unwrapUnsafe_ :: forall dt name st. InstrUnwrapC dt name => Label name -> (dt & st) :-> (CtorOnlyField name dt : st) type CaseTC dt out inp clauses = (InstrCaseC dt inp out, RMap (CaseClauses dt), RecFromTuple clauses, clauses ~ Rec (CaseClauseL inp out) (CaseClauses dt)) -- | Provides "case" arrow which works on different wrappers for clauses. class CaseArrow name body clause | clause -> name, clause -> body -- | Lift an instruction to case clause. -- -- You should write out constructor name corresponding to the clause -- explicitly. Prefix constructor name with "c" letter, otherwise your -- label will not be recognized by Haskell parser. Passing constructor -- name can be circumvented but doing so is not recomended as mentioning -- contructor name improves readability and allows avoiding some -- mistakes. (/->) :: CaseArrow name body clause => Label name -> body -> clause infixr 0 /-> -- | Lorentz analogy of CaseClause, it works on plain Type -- types. data CaseClauseL (inp :: [Type]) (out :: [Type]) (param :: CaseClauseParam) [CaseClauseL] :: (AppendCtorField x inp :-> out) -> CaseClauseL inp out ( 'CaseClauseParam ctor x) -- | Constraint for instrConstruct. type InstrConstructC dt = (IsoValue dt, Generic dt, GInstrConstruct (Rep dt), GValueType (Rep dt) ~ ToT dt) -- | Types of all fields in a datatype. type ConstructorFieldTypes dt = GFieldTypes (Rep dt) -- | A record is parameterized by a universe u, an interpretation -- f and a list of rows rs. The labels or indices of -- the record are given by inhabitants of the kind u; the type -- of values at any label r :: u is given by its interpretation -- f r :: *. data Rec (a :: u -> Type) (b :: [u]) :: forall u. () => u -> Type -> [u] -> Type [RNil] :: forall u (a :: u -> Type) (b :: [u]). () => Rec a ([] :: [u]) [:&] :: forall u (a :: u -> Type) (b :: [u]) (r :: u) (rs :: [u]). () => !a r -> !Rec a rs -> Rec a (r : rs) infixr 7 :& -- | Infix notation for the type of a named parameter. type (:!) (name :: Symbol) a = NamedF Identity a name -- | Infix notation for the type of an optional named parameter. type (:?) (name :: Symbol) a = NamedF Maybe a name -- | arg unwraps a named parameter with the specified name. One way -- to use it is to match on arguments with -XViewPatterns: -- --
--   fn (arg #t -> t) (arg #f -> f) = ...
--   
-- -- This way, the names of parameters can be inferred from the patterns: -- no type signature for fn is required. In case a type -- signature for fn is provided, the parameters must come in the -- same order: -- --
--   fn :: "t" :! Integer -> "f" :! Integer -> ...
--   fn (arg #t -> t) (arg #f -> f) = ... -- ok
--   fn (arg #f -> f) (arg #t -> t) = ... -- does not typecheck
--   
arg :: () => Name name -> (name :! a) -> a -- | A variation of arg for optional arguments. Requires a default -- value to handle the case when the optional argument was omitted: -- --
--   fn (argDef #answer 42 -> ans) = ...
--   
-- -- In case you want to get a value wrapped in Maybe instead, use -- argF or ArgF. argDef :: () => Name name -> a -> (name :? a) -> a -- | argF is similar to arg: it unwraps a named parameter -- with the specified name. The difference is that the result of -- argF is inside an arity wrapper, which is Identity for -- normal parameters and Maybe for optional parameters. argF :: () => Name name -> NamedF f a name -> f a instance (name Data.Type.Equality.~ GHC.TypeLits.AppendSymbol "c" ctor, body Data.Type.Equality.~ (Michelson.Typed.Haskell.Instr.Sum.AppendCtorField x inp Lorentz.Base.:-> out)) => Lorentz.ADT.CaseArrow name body (Lorentz.ADT.CaseClauseL inp out ('Michelson.Typed.Haskell.Instr.Sum.CaseClauseParam ctor x)) module Lorentz.Doc -- | Put a document item. doc :: DocItem di => di -> s :-> s -- | Group documentation built in the given piece of code into block -- dedicated to one thing, e.g. to one entry point. docGroup :: DocGrouping -> (inp :-> out) -> inp :-> out buildLorentzDoc :: (inp :-> out) -> ContractDoc renderLorentzDoc :: (inp :-> out) -> LText -- | Give a name to given contract. Apply it to the whole contract code. contractName :: Text -> (inp :-> out) -> inp :-> out -- | Leave only instructions related to documentation. -- -- This function is useful when your method executes a lambda coming from -- outside, but you know its properties and want to propagate its -- documentation to your contract code. cutLorentzNonDoc :: (inp :-> out) -> s :-> s -- | A piece of markdown document. -- -- This is opposed to Text type, which in turn is not supposed to -- contain markup elements. type Markdown = Builder -- | A piece of documentation describing one property of a thing, be it a -- name or description of a contract, or an error throwable by given -- endpoint. -- -- Items of the same type appear close to each other in a rendered -- documentation and form a section. -- -- Doc items are later injected into a contract code via a dedicated -- nop-like instruction. Normally doc items which belong to one section -- appear in resulting doc in the same order in which they appeared in -- the contract. -- -- While documentation framework grows, this typeclass acquires more and -- more methods for fine tuning of existing rendering logic because we -- don't want to break backward compatibility, hope one day we will make -- everything concise :( E.g. all rendering and reording stuff could be -- merged in one method, and we could have several template -- implementations for it which would allow user to specify only stuff -- relevant to his case. class (Typeable d, DOrd d, KnownNat (DocItemPosition d)) => DocItem d where { -- | Position of this item in the resulting documentation; the smaller the -- value, the higher the section with this element will be placed. -- -- Documentation structure is not necessarily flat. If some doc item -- consolidates a whole documentation block within it, this block will -- have its own placement of items independent from outer parts of the -- doc. type family DocItemPosition d = (pos :: Nat) | pos -> d; -- | Defines where given doc item should be put. There are two options: 1. -- Inline right here (default behaviour); 2. Put into definitions -- section. -- -- Note that we require all doc items with "in definitions" placement to -- have Eq and Ord instances which comply the following -- law: if two documentation items describe the same entity or property, -- they should be considered equal. type family DocItemPlacement d :: DocItemPlacementKind; type DocItemPlacement d = 'DocItemInlined; } -- | When multiple items of the same type belong to one section, how this -- section will be called. -- -- If not provided, section will contain just untitled content. docItemSectionName :: DocItem d => Maybe Text -- | Description of a section. -- -- Can be used to mention some common things about all elements of this -- section. Markdown syntax is permitted here. docItemSectionDescription :: DocItem d => Maybe Markdown -- | How to render section name. -- -- Takes effect only if section name is set. docItemSectionNameStyle :: DocItem d => DocSectionNameStyle -- | Defines a function which constructs an unique identifier of given doc -- item, if it has been decided to put the doc item into definitions -- section. -- -- Identifier should be unique both among doc items of the same type and -- items of other types. Thus, consider using "typeId-contentId" pattern. docItemRef :: DocItem d => d -> DocItemRef (DocItemPlacement d) -- | Defines a function which constructs an unique identifier of given doc -- item, if it has been decided to put the doc item into definitions -- section. -- -- Identifier should be unique both among doc items of the same type and -- items of other types. Thus, consider using "typeId-contentId" pattern. docItemRef :: (DocItem d, DocItemPlacement d ~ 'DocItemInlined) => d -> DocItemRef (DocItemPlacement d) -- | Render given doc item to Markdown, preferably one line, optionally -- with header. -- -- Accepts the smallest allowed level of header. (Using smaller value -- than provided one will interfere with existing headers thus delivering -- mess). docItemToMarkdown :: DocItem d => HeaderLevel -> d -> Markdown -- | All doc items which this doc item refers to. -- -- They will automatically be put to definitions as soon as given doc -- item is detected. docItemDependencies :: DocItem d => d -> [SomeDocDefinitionItem] -- | This function accepts doc items put under the same section in the -- order in which they appeared in the contract and returns their new -- desired order. It's also fine to use this function for filtering or -- merging doc items. -- -- Default implementation * leaves inlined items as is; * for items put -- to definitions, lexicographically sorts them by their id. docItemsOrder :: DocItem d => [d] -> [d] -- | Get doc item position at term-level. docItemPosition :: forall d. DocItem d => DocItemPos -- | Some unique identifier of a doc item. -- -- All doc items which should be refer-able need to have this identifier. newtype DocItemId DocItemId :: Text -> DocItemId -- | Where do we place given doc item. data DocItemPlacementKind -- | Placed in the document content itself. DocItemInlined :: DocItemPlacementKind -- | Placed in dedicated definitions section; can later be referenced. DocItemInDefinitions :: DocItemPlacementKind -- | Defines an identifier which given doc item can be referenced with. data DocItemRef (p :: DocItemPlacementKind) [DocItemRef] :: DocItemId -> DocItemRef 'DocItemInDefinitions [DocItemNoRef] :: DocItemRef 'DocItemInlined -- | How to render section name. data DocSectionNameStyle -- | Suitable for block name. DocSectionNameBig :: DocSectionNameStyle -- | Suitable for subsection title within block. DocSectionNameSmall :: DocSectionNameStyle -- | Hides some documentation item. data SomeDocItem [SomeDocItem] :: DocItem d => d -> SomeDocItem -- | Hides some documentation item which is put to "definitions" section. data SomeDocDefinitionItem [SomeDocDefinitionItem] :: (DocItem d, DocItemPlacement d ~ 'DocItemInDefinitions) => d -> SomeDocDefinitionItem -- | A part of documentation to be grouped. Essentially incapsulates -- DocBlock. newtype SubDoc SubDoc :: DocBlock -> SubDoc -- | A function which groups a piece of doc under one doc item. type DocGrouping = SubDoc -> SomeDocItem -- | Keeps documentation gathered for some piece of contract code. -- -- Used for building documentation of a contract. data ContractDoc ContractDoc :: DocBlock -> DocBlock -> Set SomeDocDefinitionItem -> Set DocItemId -> ContractDoc -- | All inlined doc items. [cdContents] :: ContractDoc -> DocBlock -- | Definitions used in document. -- -- Usually you put some large and repetitive descriptions here. This -- differs from the document content in that it contains sections which -- are always at top-level, disregard the nesting. -- -- All doc items which define docItemId method go here, and only -- they. [cdDefinitions] :: ContractDoc -> DocBlock -- | We remember all already declared entries to avoid cyclic dependencies -- in documentation items discovery. [cdDefinitionsSet] :: ContractDoc -> Set SomeDocDefinitionItem -- | We remember all already used identifiers. (Documentation naturally -- should not declare multiple items with the same identifier because -- that would make references to the respective anchors ambiguous). [cdDefinitionIds] :: ContractDoc -> Set DocItemId -- | Description of something. data DDescription DDescription :: Markdown -> DDescription -- | Specify version if given contract. data DVersion DVersion :: Natural -> DVersion -- | Specify version if given contract. data DGitRevision DGitRevision :: GitRepoSettings -> Text -> Text -> DGitRevision [dgrRepoSettings] :: DGitRevision -> GitRepoSettings [dgrCommitSha] :: DGitRevision -> Text [dgrCommitDate] :: DGitRevision -> Text -- | Repository settings for DGitRevision. newtype GitRepoSettings GitRepoSettings :: (Text -> Text) -> GitRepoSettings -- | By commit sha make up a url to that commit in remote repository. [grsMkGitRevision] :: GitRepoSettings -> Text -> Text -- | Make DGitRevision. -- --
--   >>> :t $mkDGitRevision
--   GitRepoSettings -> DGitRevision
--   
mkDGitRevision :: Q Exp morleyRepoSettings :: GitRepoSettings data DComment DComment :: Text -> DComment -- | Doc element with description of a type. data DType [DType] :: TypeHasDoc a => Proxy a -> DType -- | Make a reference to doc item in definitions. docDefinitionRef :: (DocItem d, DocItemPlacement d ~ 'DocItemInDefinitions) => Markdown -> d -> Markdown -- | Render given contract documentation to markdown document. contractDocToMarkdown :: ContractDoc -> LText -- | Render documentation for SubDoc. subDocToMarkdown :: HeaderLevel -> SubDoc -> Markdown -- | Description for a Haskell type appearing in documentation. class Typeable a => TypeHasDoc a -- | Name of type as it appears in definitions section. -- -- Each type must have its own unique name because it will be used in -- identifier for references. -- -- Default definition derives name from Generics. If it does not fit, -- consider defining this function manually. (We tried using Data -- for this, but it produces names including module names which is not do -- we want). typeDocName :: TypeHasDoc a => Proxy a -> Text -- | Name of type as it appears in definitions section. -- -- Each type must have its own unique name because it will be used in -- identifier for references. -- -- Default definition derives name from Generics. If it does not fit, -- consider defining this function manually. (We tried using Data -- for this, but it produces names including module names which is not do -- we want). typeDocName :: (TypeHasDoc a, Generic a, KnownSymbol (GenericTypeName a)) => Proxy a -> Text -- | Explanation of a type. Markdown formatting is allowed. typeDocMdDescription :: TypeHasDoc a => Markdown -- | How reference to this type is rendered, in Markdown. -- -- Examples: * Integer, * Maybe -- (). -- -- Consider using one of the following functions as default -- implementation; which one to use depends on number of type arguments -- in your type: * homomorphicTypeDocMdReference * -- poly1TypeDocMdReference * poly2TypeDocMdReference -- -- If none of them fits your purposes precisely, consider using -- customTypeDocMdReference. typeDocMdReference :: TypeHasDoc a => Proxy a -> WithinParens -> Markdown -- | How reference to this type is rendered, in Markdown. -- -- Examples: * Integer, * Maybe -- (). -- -- Consider using one of the following functions as default -- implementation; which one to use depends on number of type arguments -- in your type: * homomorphicTypeDocMdReference * -- poly1TypeDocMdReference * poly2TypeDocMdReference -- -- If none of them fits your purposes precisely, consider using -- customTypeDocMdReference. typeDocMdReference :: (TypeHasDoc a, Typeable a, IsHomomorphic a) => Proxy a -> WithinParens -> Markdown -- | All types which this type directly contains. -- -- Used in automatic types discovery. typeDocDependencies :: TypeHasDoc a => Proxy a -> [SomeTypeWithDoc] -- | All types which this type directly contains. -- -- Used in automatic types discovery. typeDocDependencies :: (TypeHasDoc a, Generic a, GTypeHasDoc (Rep a)) => Proxy a -> [SomeTypeWithDoc] -- | For complex types - their immediate Haskell representation. -- -- For primitive types set this to Nothing. -- -- For homomorphic types use homomorphicTypeDocHaskellRep -- implementation. -- -- For polymorhpic types consider using concreteTypeDocHaskellRep -- as implementation. -- -- Modifier haskellRepNoFields can be used to hide names of -- fields, beneficial for newtypes. -- -- Another modifier called haskellRepStripFieldPrefix can be used -- for datatypes to leave only meaningful part of name in every field. typeDocHaskellRep :: TypeHasDoc a => TypeDocHaskellRep a -- | For complex types - their immediate Haskell representation. -- -- For primitive types set this to Nothing. -- -- For homomorphic types use homomorphicTypeDocHaskellRep -- implementation. -- -- For polymorhpic types consider using concreteTypeDocHaskellRep -- as implementation. -- -- Modifier haskellRepNoFields can be used to hide names of -- fields, beneficial for newtypes. -- -- Another modifier called haskellRepStripFieldPrefix can be used -- for datatypes to leave only meaningful part of name in every field. typeDocHaskellRep :: (TypeHasDoc a, Generic a, GTypeHasDoc (Rep a), IsHomomorphic a) => TypeDocHaskellRep a -- | Final michelson representation of a type. -- -- For homomorphic types use homomorphicTypeDocMichelsonRep -- implementation. -- -- For polymorhpic types consider using -- concreteTypeDocMichelsonRep as implementation. typeDocMichelsonRep :: TypeHasDoc a => TypeDocMichelsonRep a -- | Final michelson representation of a type. -- -- For homomorphic types use homomorphicTypeDocMichelsonRep -- implementation. -- -- For polymorhpic types consider using -- concreteTypeDocMichelsonRep as implementation. typeDocMichelsonRep :: (TypeHasDoc a, SingI (ToT a), IsHomomorphic a) => TypeDocMichelsonRep a -- | Data hides some type implementing TypeHasDoc. data SomeTypeWithDoc [SomeTypeWithDoc] :: TypeHasDoc td => Proxy td -> SomeTypeWithDoc -- | Require two types to be built from the same type constructor. -- -- E.g. HaveCommonTypeCtor (Maybe Integer) (Maybe Natural) is -- defined, while HaveCmmonTypeCtor (Maybe Integer) [Integer] is -- not. class HaveCommonTypeCtor a b -- | Require this type to be homomorphic. class IsHomomorphic a -- | Implement typeDocDependencies via getting all immediate fields -- of a datatype. -- -- Note: this will not include phantom types, I'm not sure yet how this -- scenario should be handled (@martoon). genericTypeDocDependencies :: forall a. (Generic a, GTypeHasDoc (Rep a)) => Proxy a -> [SomeTypeWithDoc] -- | Render a reference to a type which consists of type constructor (you -- have to provide name of this type constructor and documentation for -- the whole type) and zero or more type arguments. customTypeDocMdReference :: (Text, DType) -> [DType] -> WithinParens -> Markdown -- | Derive typeDocMdReference, for homomorphic types only. homomorphicTypeDocMdReference :: forall (t :: Type). (Typeable t, TypeHasDoc t, IsHomomorphic t) => Proxy t -> WithinParens -> Markdown -- | Derive typeDocMdReference, for polymorphic type with one type -- argument, like Maybe Integer. poly1TypeDocMdReference :: forall t (r :: Type) (a :: Type). (r ~ t a, Typeable t, Each '[TypeHasDoc] [r, a], IsHomomorphic t) => Proxy r -> WithinParens -> Markdown -- | Derive typeDocMdReference, for polymorphic type with two type -- arguments, like Lambda Integer Natural. poly2TypeDocMdReference :: forall t (r :: Type) (a :: Type) (b :: Type). (r ~ t a b, Typeable t, Each '[TypeHasDoc] [r, a, b], IsHomomorphic t) => Proxy r -> WithinParens -> Markdown -- | Implement typeDocHaskellRep for a homomorphic type. -- -- Note that it does not require your type to be of IsHomomorphic -- instance, which can be useful for some polymorhpic types which, for -- documentation purposes, we want to consider homomorphic. Example: -- Operation is in fact polymorhpic, but we don't want this fact -- to be reflected in the documentation. homomorphicTypeDocHaskellRep :: forall a. (Generic a, GTypeHasDoc (Rep a)) => TypeDocHaskellRep a -- | Implement typeDocHaskellRep on example of given concrete type. -- -- This is a best effort attempt to implement typeDocHaskellRep -- for polymorhpic types, as soon as there is no simple way to preserve -- type variables when automatically deriving Haskell representation of a -- type. concreteTypeDocHaskellRep :: forall a b. (Typeable a, IsoValue a, Generic a, GTypeHasDoc (Rep a), HaveCommonTypeCtor b a) => TypeDocHaskellRep b -- | Version of concreteTypeDocHaskellRep which does not ensure -- whether the type for which representation is built is any similar to -- the original type which you implement a TypeHasDoc instance -- for. concreteTypeDocHaskellRepUnsafe :: forall a b. (Typeable a, IsoValue a, Generic a, GTypeHasDoc (Rep a)) => TypeDocHaskellRep b -- | Erase fields from Haskell datatype representation. -- -- Use this when rendering fields names is undesired. haskellRepNoFields :: TypeDocHaskellRep a -> TypeDocHaskellRep a -- | Cut fields prefixes which we use according to the style guide. -- -- E.g. cmMyField field will be transformed to myField. haskellRepStripFieldPrefix :: HasCallStack => TypeDocHaskellRep a -> TypeDocHaskellRep a -- | Implement typeDocMichelsonRep for homomorphic type. homomorphicTypeDocMichelsonRep :: forall a. SingI (ToT a) => TypeDocMichelsonRep a -- | Implement typeDocMichelsonRep on example of given concrete -- type. -- -- This function exists for the same reason as -- concreteTypeDocHaskellRep. concreteTypeDocMichelsonRep :: forall a b. (Typeable a, SingI (ToT a), HaveCommonTypeCtor b a) => TypeDocMichelsonRep b -- | Version of concreteTypeDocHaskellRepUnsafe which does not -- ensure whether the type for which representation is built is any -- similar to the original type which you implement a TypeHasDoc -- instance for. concreteTypeDocMichelsonRepUnsafe :: forall a b. (Typeable a, SingI (ToT a)) => TypeDocMichelsonRep b instance Universum.TypeOps.Each '[Data.Typeable.Internal.Typeable, Util.Type.ReifyList Michelson.Typed.Haskell.Doc.TypeHasDoc] '[i, o] => Michelson.Typed.Haskell.Doc.TypeHasDoc (i Lorentz.Base.:-> o) -- | UStore definition and common type-level stuff. module Lorentz.UStore.Types -- | Gathers multple fields and BigMaps under one object. -- -- Type argument of this datatype stands for a "store template" - a -- datatype with one constructor and multiple fields, each containing an -- object of type UStoreFieldExt or |~> and -- corresponding to single virtual field or BigMap respectively. -- It's also possible to parameterize it with a larger type which is a -- product of types satisfying the above property. newtype UStore (a :: Type) UStore :: BigMap ByteString ByteString -> UStore [unUStore] :: UStore -> BigMap ByteString ByteString -- | Describes one virtual big map in the storage. newtype k |~> v UStoreSubMap :: Map k v -> (|~>) k v [unUStoreSubMap] :: (|~>) k v -> Map k v -- | Describes plain field in the storage. newtype UStoreFieldExt (m :: UStoreMarkerType) (v :: Type) UStoreField :: v -> UStoreFieldExt [unUStoreField] :: UStoreFieldExt -> v -- | Just a plain field used as data. type UStoreField = UStoreFieldExt UMarkerPlainField -- | Specific kind used to designate markers for UStoreFieldExt. -- -- We suggest that fields may serve different purposes and so annotated -- with special markers accordingly. See example below. -- -- This kind is implemented like that because we want markers to differ -- from all other types in kind; herewith UStoreMarkerType is -- still an open kind (has potentially infinite number of inhabitants). type UStoreMarkerType = UStoreMarker -> Type data UMarkerPlainField :: UStoreMarkerType -- | Allows to specify format of key under which fields of this type are -- stored. Useful to avoid collisions. class KnownUStoreMarker (marker :: UStoreMarkerType) where { -- | Display type-level information about UStore field with given marker -- and field value type. Used for error messages. type family ShowUStoreField marker v :: ErrorMessage; type ShowUStoreField marker v = 'Text "field of type " :<>: 'ShowType v; } -- | By field name derive key under which field should be stored. mkFieldMarkerUKey :: (KnownUStoreMarker marker, KnownSymbol name) => Label name -> ByteString -- | By field name derive key under which field should be stored. mkFieldMarkerUKey :: (KnownUStoreMarker marker, KnownSymbol name) => Label name -> ByteString -- | Shortcut for mkFieldMarkerUKey which accepts not marker but -- store type and name of entry. mkFieldUKey :: forall (store :: Type) name. (KnownSymbol name, KnownUStoreMarker (GetUStoreFieldMarker store name)) => Label name -> ByteString -- | Get type of submap key. type GetUStoreKey store name = MSKey (GetUStore name store) -- | Get type of submap value. type GetUStoreValue store name = MSValue (GetUStore name store) -- | Get type of plain field. This ignores marker with field type. type GetUStoreField store name = FSValue (GetUStore name store) -- | Get kind of field. type GetUStoreFieldMarker store name = FSMarker (GetUStore name store) -- | Collect all fields with the given marker. type PickMarkedFields marker template = GPickMarkedFields marker (Rep template) -- | What was found on lookup by constructor name. -- -- This keeps either type arguments of |~> or -- UStoreFieldExt. data ElemSignature MapSignature :: Type -> Type -> ElemSignature FieldSignature :: UStoreMarkerType -> Type -> ElemSignature -- | Get map signature from the constructor with a given name. type GetUStore name a = MERequireFound name a (GLookupStore name (Rep a)) type family MSKey (ms :: ElemSignature) :: Type type family MSValue (ms :: ElemSignature) :: Type type family FSValue (ms :: ElemSignature) :: Type type family FSMarker (ms :: ElemSignature) :: UStoreMarkerType instance GHC.Classes.Eq v => GHC.Classes.Eq (Lorentz.UStore.Types.UStoreFieldExt m v) instance GHC.Show.Show v => GHC.Show.Show (Lorentz.UStore.Types.UStoreFieldExt m v) instance Data.Default.Class.Default (k Lorentz.UStore.Types.|~> v) instance (GHC.Classes.Eq k, GHC.Classes.Eq v) => GHC.Classes.Eq (k Lorentz.UStore.Types.|~> v) instance (GHC.Show.Show k, GHC.Show.Show v) => GHC.Show.Show (k Lorentz.UStore.Types.|~> v) instance Lorentz.Polymorphic.UpdOpHs (Lorentz.UStore.Types.UStore a) instance Lorentz.Polymorphic.GetOpHs (Lorentz.UStore.Types.UStore a) instance Lorentz.Polymorphic.MemOpHs (Lorentz.UStore.Types.UStore a) instance Michelson.Typed.Haskell.Value.IsoValue (Lorentz.UStore.Types.UStore a) instance GHC.Base.Monoid (Lorentz.UStore.Types.UStore a) instance GHC.Base.Semigroup (Lorentz.UStore.Types.UStore a) instance Data.Default.Class.Default (Lorentz.UStore.Types.UStore a) instance GHC.Generics.Generic (Lorentz.UStore.Types.UStore a) instance GHC.Show.Show (Lorentz.UStore.Types.UStore a) instance GHC.Classes.Eq (Lorentz.UStore.Types.UStore a) instance Lorentz.UStore.Types.KnownUStoreMarker Lorentz.UStore.Types.UMarkerPlainField instance Data.Typeable.Internal.Typeable template => Michelson.Typed.Haskell.Doc.TypeHasDoc (Lorentz.UStore.Types.UStore template) module Lorentz.UStore.Migration.Diff -- | Information about single field of UStore. type FieldInfo = (Symbol, Type) -- | What should happen with a particular UStoreItem. data DiffKind ToAdd :: DiffKind ToDel :: DiffKind -- | Single piece of a diff. type DiffItem = (DiffKind, FieldInfo) -- | Make up a migration diff between given old and new UStore -- templates. type BuildDiff oldTemplate newTemplate = LiftToDiff 'ToAdd (LinearizeUStore newTemplate // LinearizeUStore oldTemplate) ++ LiftToDiff 'ToDel (LinearizeUStore oldTemplate // LinearizeUStore newTemplate) -- | Renders human-readable message describing given diff. type ShowDiff diff = 'Text "Migration is incomplete, remaining diff:" :$$: ShowDiffItems diff -- | Helper type family which dumps error message about remaining diff if -- such is present. type family RequireEmptyDiff (diff :: [DiffItem]) :: Constraint -- | Get information about all fields of UStore template in a list. -- -- In particular, this recursivelly traverses template and retrives names -- and types of fields. Semantic wrappers like UStoreFieldExt and -- |~> in field types are returned as-is. type LinearizeUStore a = GLinearizeUStore (Rep a) data LinearizeUStoreF (template :: Type) :: Exp [FieldInfo] -- | Get only field names of UStore template. type family AllUStoreFieldsF (template :: Type) :: Exp [Symbol] -- | Cover the respective part of diff. Maybe fail if such action is not -- required. -- -- This type is very similar to DiffKind, but we still use another -- type as 1. Their kinds will differ - no chance to mix up anything. 2. -- One day there might appear more complex actions. data DiffCoverage DcAdd :: DiffCoverage DcRemove :: DiffCoverage -- | Apply given diff coverage, returning type of affected field and -- modified diff. type family CoverDiff (cover :: DiffCoverage) (field :: Symbol) (diff :: [DiffItem]) :: (Type, [DiffItem]) -- | Apply multiple coverage steps. type family CoverDiffMany (diff :: [DiffItem]) (covers :: [DiffCoverageItem]) :: [DiffItem] -- | Composability helper for UStore. module Lorentz.UStore.Lift -- | Lift an UStore to another UStore which contains all the -- entries of the former under given field. -- -- This function is not intended for use in migrations, only in normal -- entry points. -- -- Note that this function ensures that template of resulting store does -- not contain inner nested templates with duplicated fields, otherwise -- UStore invariants could get broken. liftUStore :: (Generic template, RequireAllUniqueFields template) => Label name -> (UStore (GetFieldType template name) : s) :-> (UStore template : s) -- | Unlift an UStore to a smaller UStore which is part of -- the former. -- -- This function is not intended for use in migrations, only in normal -- entry points. -- -- Surprisingly, despite smaller UStore may have extra entries, -- this function is safe when used in contract code. Truly, all getters -- and setters are still safe to use. Also, there is no way for the -- resulting small UStore to leak outside of the contract since -- the only place where big_map can appear is contract storage, -- so this small UStore can be either dropped or lifted back via -- liftUStore to appear as part of the new contract's state. -- -- When this function is run as part of standalone instructions sequence, -- not as part of contract code (e.g. in tests), you may get an -- UStore with entries not inherent to it. unliftUStore :: Generic template => Label name -> (UStore template : s) :-> (UStore (GetFieldType template name) : s) type UStoreFieldsAreUnique template = AllUnique (UStoreFields template) instance GHC.Generics.Generic Lorentz.UStore.Lift.MyStoreTemplateBig instance GHC.Generics.Generic Lorentz.UStore.Lift.MyStoreTemplate -- | Basic migration primitives. -- -- All primitives in one scheme: -- -- MigrationBlocks (batched migrations writing) /| || muBlock // || -- mkUStoreBatchedMigration // || // || MUStore || UStore template value -- (simple migration writing) || (storage initialization) \ || // \ || // -- mkUStoreMigration \ || // fillUStore | / |/ UStoreMigration (whole -- migration) || \ || \ migrationToScript || \ compileMigration || \ -- MigrationBatching || \ (way to slice migration) || \ // || \ // || | -- |/ || UStoreMigrationCompiled || (sliced migration) || // \ || -- migrationToScripts \ buildMigrationPlan || // \ migrationStagesNum || -- // \ ... / |/ | MigrationScript Information about migration (part of -- migration which (migration plan, stages number...) fits into Tezos -- transaction) module Lorentz.UStore.Migration.Base -- | Absolutely empty storage. type InitUStore = UStore () -- | Dummy template for UStore, use this when you want to forget -- exact template and make type of store homomorphic. data SomeUTemplate -- | UStore with hidden template. type UStore_ = UStore SomeUTemplate toUStore_ :: UStore template -> UStore_ fromUStore_ :: UStore_ -> UStore template -- | Code of migration for UStore. -- -- Invariant: preferably should fit into op size / gas limits (quite -- obvious). Often this stands for exactly one stage of migration (one -- Tezos transaction). newtype MigrationScript MigrationScript :: Lambda UStore_ UStore_ -> MigrationScript [unMigrationScript] :: MigrationScript -> Lambda UStore_ UStore_ maNameL :: Lens' MigrationAtom Text maScriptL :: Lens' MigrationAtom MigrationScript maActionsDescL :: Lens' MigrationAtom [DMigrationActionDesc] -- | Minimal possible piece of migration script. -- -- Different atoms can be arbitrarily reordered and separated across -- migration stages, but each single atom is treated as a whole. -- -- Splitting migration into atoms is responsibility of migration writer. data MigrationAtom MigrationAtom :: Text -> MigrationScript -> [DMigrationActionDesc] -> MigrationAtom [maName] :: MigrationAtom -> Text [maScript] :: MigrationAtom -> MigrationScript [maActionsDesc] :: MigrationAtom -> [DMigrationActionDesc] -- | Keeps information about migration between UStores with two -- given templates. Note that it is polymorphic over whole storage types, -- not their templates, for convenience (so that there is no need to -- export the template). data UStoreMigration (oldStore :: Type) (newStore :: Type) [UStoreMigration] :: (oldStore ~ UStore oldTemplate, newStore ~ UStore newTemplate) => [MigrationAtom] -> UStoreMigration oldStore newStore -- | Alias for UStoreMigration which accepts UStore templates as -- type arguments. type UStoreMigrationT ot nt = UStoreMigration (UStore ot) (UStore nt) -- | A bunch of migration atoms produced by migration writer. newtype MigrationBlocks (oldTemplate :: Type) (newTemplate :: Type) (preRemDiff :: [DiffItem]) (preTouched :: [Symbol]) (postRemDiff :: [DiffItem]) (postTouched :: [Symbol]) MigrationBlocks :: [MigrationAtom] -> MigrationBlocks -- | Wrapper over UStore which is currently being migrated. -- -- In type-level arguments it keeps -- -- newtype MUStore (oldTemplate :: Type) (newTemplate :: Type) (remDiff :: [DiffItem]) (touched :: [Symbol]) MUStoreUnsafe :: UStore oldTemplate -> MUStore -- | Turn Migration into a whole piece of code for transforming -- storage. -- -- This is not want you'd want to use for contract deployment because of -- gas and operation size limits that Tezos applies to transactions. migrationToLambda :: UStoreMigrationT oldTemplate newTemplate -> Lambda (UStore oldTemplate) (UStore newTemplate) -- | Modify all code in migration. mapMigrationCode :: (forall i o. (i :-> o) -> i :-> o) -> UStoreMigration os ns -> UStoreMigration os ns -- | Safe way to create migration scripts for UStore. -- -- You have to supply a code which would transform MUStore, -- coverring required diff step-by-step. All basic instructions work, -- also use migrate* functions from this module to operate with -- MUStore. -- -- This method produces a whole migration, it cannot be splitted in -- batches. In case if your migration is too big to be applied within a -- single transaction, use mkUStoreBatchedMigration. mkUStoreMigration :: Lambda (MUStore oldTempl newTempl (BuildDiff oldTempl newTempl) '[]) (MUStore oldTempl newTempl '[] _1) -> UStoreMigrationT oldTempl newTempl -- | Get migration script in case of simple (non-batched) migration. migrationToScript :: UStoreMigration ot nt -> MigrationScript -- | Way of distributing migration atoms among batches. -- -- This also participates in describing migration plan and should contain -- information which would clarify to a user why migration is splitted -- such a way. Objects of type batchInfo stand for information -- corresponding to a batch and may include e.g. names of taken actions -- and gas consumption. -- -- Type argument structure stands for container where batches -- will be put to and is usually a list ('[]'). -- -- When writing an instance of this datatype, you should tend to produce -- as few batches as possible because Tezos transaction execution -- overhead is quite high; though these batches should still preferably -- fit into gas limit. -- -- Note that we never fail here because reaching perfect consistency with -- Tezos gas model is beyond dreams for now, even if our model predicts -- that some migration atom cannot be fit into gas limit, Tezos node can -- think differently and accept the migration. If your batching function -- can make predictions about fitting into gas limit, consider including -- this information in batchInfo type. -- -- See batching implementations in -- Lorentz.UStore.Migration.Batching module. data MigrationBatching (structure :: Type -> Type) (batchInfo :: Type) MigrationBatching :: ([MigrationAtom] -> structure (batchInfo, MigrationScript)) -> MigrationBatching -- | Put each migration atom to a separate batch. -- -- In most cases this is not what you want, but may be useful if e.g. you -- write your migration manually. mbBatchesAsIs :: MigrationBatching [] Text -- | Put the whole migration into one batch. mbNoBatching :: MigrationBatching Identity Text -- | Compile migration for use in production. compileMigration :: MigrationBatching t batchInfo -> UStoreMigration ot nt -> UStoreMigrationCompiled t batchInfo -- | Migration script splitted in batches. -- -- This is an intermediate form of migration content and needed because -- compiling UStoreMigration is a potentially heavyweight -- operation, and after compilation is performed you may need to get -- various information like number of migration steps, migration script, -- migration plan and other. newtype UStoreMigrationCompiled (structure :: Type -> Type) (batchInfo :: Type) UStoreMigrationCompiled :: structure (batchInfo, MigrationScript) -> UStoreMigrationCompiled [compiledMigrationContent] :: UStoreMigrationCompiled -> structure (batchInfo, MigrationScript) -- | Version of mkUStoreMigration which allows splitting migration -- in batches. -- -- Here you supply a sequence of migration blocks which then are -- automatically distributed among migration stages. mkUStoreBatchedMigration :: MigrationBlocks oldTempl newTempl (BuildDiff oldTempl newTempl) '[] '[] _1 -> UStoreMigrationT oldTempl newTempl -- | Get migration scripts, each to be executed in separate Tezos -- transaction. migrationToScripts :: Traversable t => UStoreMigrationCompiled t batchInfo -> t MigrationScript -- | Get migration scripts as list. migrationToScriptsList :: Traversable t => UStoreMigrationCompiled t batchInfo -> [MigrationScript] -- | Get information about each batch. migrationToInfo :: Traversable t => UStoreMigrationCompiled t batchInfo -> t batchInfo -- | Number of stages in migration. migrationStagesNum :: Traversable t => UStoreMigrationCompiled t batchInfo -> Int -- | Render migration plan. buildMigrationPlan :: (Traversable t, Buildable batchInfo) => UStoreMigrationCompiled t batchInfo -> Builder -- | Manually perform a piece of migration. manualWithUStore :: forall ustore template. ustore ~ UStore template => ('[ustore] :-> '[ustore]) -> MigrationScript -- | Merge several migration scripts. Used in manual migrations. -- -- This function is generally unsafe because resulting migration script -- can fail to fit into operation size limit. manualConcatMigrationScripts :: [MigrationScript] -> MigrationScript -- | An action on storage entry. data DMigrationActionType -- | Some sort of addition: "init", "set", "overwrite", e.t.c. DAddAction :: Text -> DMigrationActionType -- | Removal. DDelAction :: DMigrationActionType -- | Describes single migration action. -- -- In most cases it is possible to derive reasonable description for -- migration atom automatically, this datatype exactly carries this -- information. data DMigrationActionDesc DMigrationActionDesc :: DMigrationActionType -> Text -> T -> DMigrationActionDesc -- | Action on field, e.g. "set", "remove", "overwrite". [manAction] :: DMigrationActionDesc -> DMigrationActionType -- | Name of affected field of UStore. [manField] :: DMigrationActionDesc -> Text -- | Type of affected field of UStore in new storage version. [manFieldType] :: DMigrationActionDesc -> T -- | Add description of action, it will be used in rendering migration plan -- and some batching implementations. attachMigrationActionName :: (KnownSymbol fieldName, SingI (ToT fieldTy)) => DMigrationActionType -> Label fieldName -> Proxy fieldTy -> s :-> s -- | Create migration atom from code. -- -- This is an internal function, should not be used for writing -- migrations. formMigrationAtom :: Maybe Text -> Lambda UStore_ UStore_ -> MigrationAtom instance Michelson.Typed.Haskell.Value.IsoValue (Lorentz.UStore.Migration.Base.MUStore oldTemplate newTemplate remDiff touched) instance GHC.Generics.Generic (Lorentz.UStore.Migration.Base.MUStore oldTemplate newTemplate remDiff touched) instance GHC.Show.Show Lorentz.UStore.Migration.Base.MigrationAtom instance GHC.Show.Show Lorentz.UStore.Migration.Base.DMigrationActionDesc instance GHC.Show.Show Lorentz.UStore.Migration.Base.DMigrationActionType instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.UStore.Migration.Base.MigrationScript instance GHC.Generics.Generic Lorentz.UStore.Migration.Base.MigrationScript instance GHC.Show.Show Lorentz.UStore.Migration.Base.MigrationScript instance Michelson.Doc.DocItem Lorentz.UStore.Migration.Base.DMigrationActionDesc instance Formatting.Buildable.Buildable Lorentz.UStore.Migration.Base.DMigrationActionType instance Control.Lens.Wrapped.Wrapped Lorentz.UStore.Migration.Base.MigrationScript instance Michelson.Typed.Haskell.Doc.TypeHasDoc Lorentz.UStore.Migration.Base.MigrationScript -- | Different approaches to batching. -- -- For now we do not support perfect batching because operation size -- evaluation (as well as gas consumption evaluation) is not implemented -- yet. The only non-trivial batching implementation we provide is -- mbSeparateLambdas. module Lorentz.UStore.Migration.Batching -- | Type of batch. data SlBatchType -- | Addition of any type of data. SlbtData :: SlBatchType -- | Addition of code. SlbtLambda :: SlBatchType -- | Several joined actions of different types. SlbtCustom :: SlBatchType -- | No information to chooseType about batching. This means that the given -- action does not contain DMigrationActionDesc. SlbtUnknown :: SlBatchType data SlBatchInfo SlBatchInfo :: SlBatchType -> [Text] -> SlBatchInfo [slbiType] :: SlBatchInfo -> SlBatchType [slbiActions] :: SlBatchInfo -> [Text] -- | Puts all data updates in one batch, and all lambdas in separate -- batches, one per batch. -- -- The reason for such behaviour is that in production contracts amount -- of changed data (be it in contract initialization or contract upgrade) -- is small, while stored entrypoints are huge and addition of even one -- entrypoint often barely fits into gas limit. mbSeparateLambdas :: MigrationBatching [] SlBatchInfo instance GHC.Classes.Eq Lorentz.UStore.Migration.Batching.SlBatchType instance GHC.Show.Show Lorentz.UStore.Migration.Batching.SlBatchType instance Formatting.Buildable.Buildable Lorentz.UStore.Migration.Batching.SlBatchInfo -- | Utilities for declaring and documenting entry points. module Lorentz.EntryPoints.Doc -- | Gathers information about single entry point. -- -- We assume that entry points might be of different kinds, which is -- designated by phantom type parameter. For instance, you may want to -- have several groups of entry points corresponding to various parts of -- a contract - specifying different kind type argument for each -- of those groups will allow you defining different DocItem -- instances with appropriate custom descriptions for them. data DEntryPoint (kind :: Type) DEntryPoint :: Text -> SubDoc -> DEntryPoint -- | Default value for DEntryPoint type argument. data PlainEntryPointsKind -- | Default implementation of docItemToMarkdown for entry points. diEntryPointToMarkdown :: HeaderLevel -> DEntryPoint level -> Markdown -- | Describes argument of an entry point. data DEntryPointArg DEntryPointArg :: Maybe DType -> [ParamBuildingStep] -> DEntryPointArg -- | Argument of the entry point. Pass Nothing if no argument is -- required. [epaArg] :: DEntryPointArg -> Maybe DType -- | Describes a way to lift an entry point argument into full parameter -- which can be passed to the contract. -- -- Steps are supposed to be applied in the order in which they are given. -- E.g. suppose that an entry point is called as Run (Service1 -- arg); then the first step should describe wrapping into -- Service1 constructor, and the second step should be about -- wrapping into Run constructor. [epaBuilding] :: DEntryPointArg -> [ParamBuildingStep] -- | Pick a type documentation from CtorField. class DeriveCtorFieldDoc (cf :: CtorField) deriveCtorFieldDoc :: DeriveCtorFieldDoc cf => Maybe DType -- | Describes a parameter building step. -- -- This can be wrapping into (Haskell) constructor, or a more complex -- transformation. data ParamBuildingStep ParamBuildingStep :: Markdown -> (CurrentParam -> Markdown) -> (CurrentParam -> Markdown) -> ParamBuildingStep -- | Plain english description of this step. [pbsEnglish] :: ParamBuildingStep -> Markdown -- | How to construct parameter in Haskell code. [pbsHaskell] :: ParamBuildingStep -> CurrentParam -> Markdown -- | How to construct parameter working on raw Michelson. [pbsMichelson] :: ParamBuildingStep -> CurrentParam -> Markdown -- | Go over contract code and update every occurrence of -- DEntryPointArg documentation item, adding the given step to its -- "how to build parameter" description. clarifyParamBuildingSteps :: ParamBuildingStep -> (inp :-> out) -> inp :-> out mkDEntryPointArgSimple :: forall t. TypeHasDoc t => DEntryPointArg -- | Like caseT, to be used for pattern-matching on parameter. -- -- Modifies documentation accordingly. Including description of -- entrypoints' arguments, thus for them you will need to supply -- TypeHasDoc instance. entryCase :: forall dt entryPointKind out inp clauses. (CaseTC dt out inp clauses, DocumentEntryPoints entryPointKind dt) => Proxy entryPointKind -> IsoRecTuple clauses -> (dt & inp) :-> out instance Lorentz.EntryPoints.Doc.GDocumentEntryPoints kind x => Lorentz.EntryPoints.Doc.GDocumentEntryPoints kind (GHC.Generics.D1 i x) instance (Lorentz.EntryPoints.Doc.GDocumentEntryPoints kind x, Lorentz.EntryPoints.Doc.GDocumentEntryPoints kind y, Util.Type.RSplit (Michelson.Typed.Haskell.Instr.Sum.GCaseClauses x) (Michelson.Typed.Haskell.Instr.Sum.GCaseClauses y)) => Lorentz.EntryPoints.Doc.GDocumentEntryPoints kind (x GHC.Generics.:+: y) instance ('Michelson.Typed.Haskell.Instr.Sum.CaseClauseParam ctor cf Data.Type.Equality.~ Michelson.Typed.Haskell.Instr.Sum.GCaseBranchInput ctor x, GHC.TypeLits.KnownSymbol ctor, Michelson.Doc.DocItem (Lorentz.EntryPoints.Doc.DEntryPoint kind), Lorentz.EntryPoints.Doc.DeriveCtorFieldDoc cf) => Lorentz.EntryPoints.Doc.GDocumentEntryPoints kind (GHC.Generics.C1 ('GHC.Generics.MetaCons ctor _1 _2) x) instance Lorentz.EntryPoints.Doc.DeriveCtorFieldDoc 'Michelson.Typed.Haskell.Instr.Sum.NoFields instance Michelson.Typed.Haskell.Doc.TypeHasDoc ty => Lorentz.EntryPoints.Doc.DeriveCtorFieldDoc ('Michelson.Typed.Haskell.Instr.Sum.OneField ty) instance Michelson.Doc.DocItem Lorentz.EntryPoints.Doc.DEntryPointArg instance Michelson.Doc.DocItem (Lorentz.EntryPoints.Doc.DEntryPoint Lorentz.EntryPoints.Doc.PlainEntryPointsKind) module Lorentz.Errors -- | Haskell type representing error. class (Typeable e, ErrorHasDoc e) => IsError e -- | Converts a Haskell error into Value representation. errorToVal :: IsError e => e -> (forall t. ErrorScope t => Value t -> r) -> r -- | Converts a Value into Haskell error. errorFromVal :: (IsError e, Typeable t, SingI t) => Value t -> Either Text e -- | Implementation of errorToVal via IsoValue. isoErrorToVal :: (KnownError e, IsoValue e) => e -> (forall t. ErrorScope t => Value t -> r) -> r -- | Implementation of errorFromVal via IsoValue. isoErrorFromVal :: (Typeable t, Typeable (ToT e), IsoValue e) => Value t -> Either Text e class ErrorHasDoc e -- | Name of error as it appears in the corresponding section title. errorDocName :: ErrorHasDoc e => Text -- | What should happen for this error to be raised. errorDocMdCause :: ErrorHasDoc e => Markdown -- | Brief version of errorDocMdCause. -- -- This will appear along with the error when mentioned in entrypoint -- description. By default, the first sentence of the full description is -- used. errorDocMdCauseInEntrypoint :: ErrorHasDoc e => Markdown -- | How this error is represented in Haskell. errorDocHaskellRep :: ErrorHasDoc e => Markdown -- | Error class. errorDocClass :: ErrorHasDoc e => ErrorClass -- | Which definitions documentation for this error mentions. errorDocDependencies :: ErrorHasDoc e => [SomeDocDefinitionItem] -- | Implementation of typeDocMdDescription (of TypeHasDoc -- typeclass) for Haskell types which sole purpose is to be error. typeDocMdDescriptionReferToError :: forall e. IsError e => Markdown -- | Use this type as replacement for () when you really -- want to leave error cause unspecified. data UnspecifiedError UnspecifiedError :: UnspecifiedError -- | Fail with the given Haskell value. failUsing :: forall e s t. IsError e => e -> s :-> t -- | Fail, providing a reference to the place in the code where this -- function is called. -- -- Like error in Haskell code, this instruction is for internal -- errors only. failUnexpected :: MText -> s :-> t -- | Declares a custom error, defining error name - error argument -- relation. -- -- If your error is supposed to carry no argument, then provide -- (). -- -- Note that this relation is defined globally rather than on -- per-contract basis, so define errors accordingly. If your error has -- argument specific to your contract, call it such that error name -- reflects its belonging to this contract. type family ErrorArg (tag :: Symbol) :: Type -- | Material custom error. -- -- Use this in pattern matches against error (e.g. in tests). data CustomError (tag :: Symbol) CustomError :: Label tag -> ErrorArg tag -> CustomError [ceTag] :: CustomError -> Label tag [ceArg] :: CustomError -> ErrorArg tag -- | Fail with given custom error. failCustom :: forall tag err s any. (err ~ ErrorArg tag, CustomErrorHasDoc tag, KnownError err) => Label tag -> (err : s) :-> any -- | Specialization of failCustom for no-arg errors. failCustom_ :: forall tag s any notVoidError. (TypeErrorUnless (ErrorArg tag == ()) notVoidError, CustomErrorHasDoc tag, notVoidError ~ ( 'Text "Expected no-arg error, but given error requires argument of type " :<>: 'ShowType (ErrorArg tag))) => Label tag -> s :-> any -- | Error class on how the error should be handled by the client. data ErrorClass -- | Normal expected error. Examples: "insufficient balance", "wallet does -- not exist". ErrClassActionException :: ErrorClass -- | Invalid argument passed to entrypoint. Examples: your entrypoint -- accepts an enum represented as nat, and unknown value is -- provided. This includes more complex cases which involve multiple -- entrypoints. E.g. API provides iterator interface, middleware should -- care about using it hiding complex details and exposing a simpler API -- to user; then an attempt to request non-existing element would also -- correspond to an error from this class. ErrClassBadArgument :: ErrorClass -- | Unexpected error. Most likely it means that there is a bug in the -- contract or the contract has been deployed incorrectly. ErrClassContractInternal :: ErrorClass -- | It's possible to leave error class unspecified. ErrClassUnknown :: ErrorClass class (KnownSymbol tag, TypeHasDoc (ErrorArg tag), IsError (CustomError tag)) => CustomErrorHasDoc tag -- | What should happen for this error to be raised. customErrDocMdCause :: CustomErrorHasDoc tag => Markdown -- | Brief version of customErrDocMdCause. This will appear along -- with the error when mentioned in entrypoint description. -- -- By default, the first sentence of the full description is used. customErrDocMdCauseInEntrypoint :: CustomErrorHasDoc tag => Markdown -- | Error class. -- -- By default this returns "unknown error" class; though you should -- provide explicit implementation in order to avoid a warning. customErrClass :: CustomErrorHasDoc tag => ErrorClass -- | Clarification of error argument meaning. -- -- Provide when it's not obvious, e.g. argument is not named with -- :!. -- -- NOTE: This should not be an entire sentence, rather just the -- semantic backbone. -- -- Bad: * Error argument stands for the previous value of -- approval. -- -- Good: * the previous value of approval * pair, first -- argument of which is one thing, and the second is another customErrArgumentSemantics :: CustomErrorHasDoc tag => Maybe Markdown -- | Mentions that contract uses given error. data DError [DError] :: IsError e => Proxy e -> DError -- | Documentation for custom errors. -- -- Mentions that entrypoint throws given error. data DThrows [DThrows] :: IsError e => Proxy e -> DThrows -- | Implementation of errorToVal for custom errors. -- | Deprecated: Datatype error declarations has been deprecated customErrorToVal :: (LooseSumC e, HasCallStack) => e -> (forall t. ErrorScope t => Value t -> r) -> r -- | Implementation of errorFromVal for custom errors. -- -- This function is deprecated. -- | Deprecated: Datatype error declarations has been deprecated customErrorFromVal :: forall t e. (SingI t, LooseSumC e) => Value t -> Either Text e -- | Fail with given error, picking argument for error from the top of the -- stack. -- -- If your error constructor does not carry an argument, use -- failUsing function instead. Consider the following practice: -- once error datatype for your contract is defined, create a -- specialization of this function to the error type. -- -- This function is deprecated. -- | Deprecated: Datatype error declarations has been deprecated failUsingArg :: forall err name fieldTy s s'. FailUsingArg err name fieldTy s s' -- | Signature of userFailWith. type FailUsingArg e name fieldTy s s' = (KnownSymbol name, IsError e, IsoValue fieldTy, CtorHasOnlyField name e fieldTy, Each [Typeable, SingI] '[ToT fieldTy], HasCallStack) => Label name -> fieldTy : s :-> s' -- | Prompt an error message saying that IsoValue is not applicable -- for this type. type family CustomErrorNoIsoValue a -- | Derive IsError instance for given type. -- -- This will also forbid deriving IsoValue instance for that type -- to avoid having multiple different Michelson representations. -- | Deprecated: Datatype error declarations has been deprecated deriveCustomError :: Name -> Q [Dec] -- | This is to be included on top of Errors section of the -- generated documentation. errorsDocumentation :: Markdown instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.Errors.UnspecifiedError instance GHC.Generics.Generic Lorentz.Errors.UnspecifiedError instance GHC.Classes.Eq (Lorentz.Errors.ErrorArg tag) => GHC.Classes.Eq (Lorentz.Errors.CustomError tag) instance GHC.Show.Show (Lorentz.Errors.ErrorArg tag) => GHC.Show.Show (Lorentz.Errors.CustomError tag) instance GHC.Classes.Eq Lorentz.Errors.DThrows instance Michelson.Doc.DocItem Lorentz.Errors.DThrows instance GHC.Classes.Eq Lorentz.Errors.DError instance GHC.Classes.Ord Lorentz.Errors.DError instance Michelson.Doc.DocItem Lorentz.Errors.DError instance (Lorentz.Errors.CustomErrorHasDoc tag, Lorentz.Errors.KnownError (Lorentz.Errors.ErrorArg tag), Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Errors.ErrorArg tag)) => Lorentz.Errors.IsError (Lorentz.Errors.CustomError tag) instance (Lorentz.Errors.CustomErrorHasDoc tag, Data.Singletons.Internal.SingI (Michelson.Typed.Haskell.Value.ToT (Lorentz.Errors.ErrorArg tag))) => Lorentz.Errors.ErrorHasDoc (Lorentz.Errors.CustomError tag) instance Lorentz.Errors.IsError Michelson.Text.MText instance (TypeError ...) => Lorentz.Errors.IsError () instance Lorentz.Errors.IsError Lorentz.Errors.UnspecifiedError instance (Data.Typeable.Internal.Typeable arg, Lorentz.Errors.IsError (Lorentz.Errors.CustomError tag), Util.TypeLits.TypeErrorUnless (arg Data.Type.Equality.== ()) notVoidError, arg Data.Type.Equality.~ Lorentz.Errors.ErrorArg tag, notVoidError Data.Type.Equality.~ ('GHC.TypeLits.Text "This error requires argument of type " 'GHC.TypeLits.:<>: 'GHC.TypeLits.ShowType (Lorentz.Errors.ErrorArg tag))) => Lorentz.Errors.IsError (arg -> Lorentz.Errors.CustomError tag) instance Lorentz.Errors.ErrorHasDoc Michelson.Text.MText instance (TypeError ...) => Lorentz.Errors.ErrorHasDoc () instance Lorentz.Errors.ErrorHasDoc Lorentz.Errors.UnspecifiedError instance Lorentz.Errors.ErrorHasDoc (Lorentz.Errors.CustomError tag) => Lorentz.Errors.ErrorHasDoc (arg -> Lorentz.Errors.CustomError tag) instance Formatting.Buildable.Buildable Lorentz.Errors.ErrorClass instance (TypeError ...) => Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Errors.CustomError tag) instance GHC.Classes.Eq (Lorentz.Errors.ErrorArg tag) => GHC.Classes.Eq (() -> Lorentz.Errors.CustomError tag) instance GHC.Show.Show (Lorentz.Errors.ErrorArg tag) => GHC.Show.Show (() -> Lorentz.Errors.CustomError tag) -- | Common Michelson macros defined using Lorentz syntax. module Lorentz.Macro type IfCmpXConstraints a op = (Typeable a, ArithOpHs Compare a a, UnaryArithOpHs op (ArithResHs Compare a a), UnaryArithResHs op (ArithResHs Compare a a) ~ Bool) eq :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Eq' (ArithResHs Compare n n) & s) neq :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Neq (ArithResHs Compare n n) & s) lt :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Lt (ArithResHs Compare n n) & s) gt :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Gt (ArithResHs Compare n n) & s) le :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Le (ArithResHs Compare n n) & s) ge :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Ge (ArithResHs Compare n n) & s) ifEq0 :: IfCmp0Constraints a Eq' => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifGe0 :: IfCmp0Constraints a Ge => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifGt0 :: IfCmp0Constraints a Gt => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifLe0 :: IfCmp0Constraints a Le => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifLt0 :: IfCmp0Constraints a Lt => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifNeq0 :: IfCmp0Constraints a Neq => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifEq :: IfCmpXConstraints a Eq' => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifGe :: IfCmpXConstraints a Ge => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifGt :: IfCmpXConstraints a Gt => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifLe :: IfCmpXConstraints a Le => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifLt :: IfCmpXConstraints a Lt => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifNeq :: IfCmpXConstraints a Neq => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' -- | Analog of the FAIL macro in Michelson. Its usage is discouraged -- because it doesn't carry any information about failure. -- | Warning: fail_ remains in code fail_ :: a :-> c assert :: IsError err => err -> (Bool & s) :-> s assertEq0 :: (IfCmp0Constraints a Eq', IsError err) => err -> (a & s) :-> s assertNeq0 :: (IfCmp0Constraints a Neq, IsError err) => err -> (a & s) :-> s assertLt0 :: (IfCmp0Constraints a Lt, IsError err) => err -> (a & s) :-> s assertGt0 :: (IfCmp0Constraints a Gt, IsError err) => err -> (a & s) :-> s assertLe0 :: (IfCmp0Constraints a Le, IsError err) => err -> (a & s) :-> s assertGe0 :: (IfCmp0Constraints a Ge, IsError err) => err -> (a & s) :-> s assertEq :: (IfCmpXConstraints a Eq', IsError err) => err -> (a & (a & s)) :-> s assertNeq :: (IfCmpXConstraints a Neq, IsError err) => err -> (a & (a & s)) :-> s assertLt :: (IfCmpXConstraints a Lt, IsError err) => err -> (a & (a & s)) :-> s assertGt :: (IfCmpXConstraints a Gt, IsError err) => err -> (a & (a & s)) :-> s assertLe :: (IfCmpXConstraints a Le, IsError err) => err -> (a & (a & s)) :-> s assertGe :: (IfCmpXConstraints a Ge, IsError err) => err -> (a & (a & s)) :-> s assertNone :: IsError err => err -> (Maybe a & s) :-> s assertSome :: IsError err => err -> (Maybe a & s) :-> (a & s) assertLeft :: IsError err => err -> (Either a b & s) :-> (a & s) assertRight :: IsError err => err -> (Either a b & s) :-> (b & s) assertUsing :: IsError a => a -> (Bool & s) :-> s -- | Custom Lorentz macro that drops element with given index (starting -- from 0) from the stack. dropX :: forall (n :: Nat) a inp out s s'. (ConstraintDIPNLorentz (ToPeano n) inp out s s', s ~ (a : s')) => inp :-> out -- | Duplicate the top of the stack n times. -- -- For example, `cloneX @3` has type `a & s :-> a & a & a -- & a & s`. cloneX :: forall (n :: Nat) a s. CloneX (ToPeano n) a s => (a & s) :-> CloneXT (ToPeano n) a s -- | DUU+P macro. For example, `duupX @3` is DUUUP, it -- puts the 3-rd (starting from 1) element to the top of the stack. Note -- that it is implemented differently for `n ≤ 2` and for `n > 2`. In -- the latter case it is implemented using dipN, dig and -- dup. In the former case it uses specialized versions. There is -- also a minor difference with the implementation of `DUU*P` in -- Michelson. They implement DUUUUP as `DIP 3 { DUP }; DIG 4`. -- We implement it as `DIP 3 { DUP }; DIG 3`. These are equivalent. Our -- version is supposedly cheaper, at least it should be packed more -- efficiently due to the way numbers are packed. duupX :: forall (n :: Nat) a (s :: [Type]) (s1 :: [Type]) (tail :: [Type]). (ConstraintDuupXLorentz (ToPeano (n - 1)) s a s1 tail, DuupX (ToPeano n) s a s1 tail) => s :-> (a : s) -- | Version of framed which accepts number of elements on input -- stack which should be preserved. -- -- You can treat this macro as calling a Michelson function with given -- number of arguments. framedN :: forall n nNat s i i' o o'. (nNat ~ ToPeano n, i' ~ Take nNat i, s ~ Drop nNat i, i ~ (i' ++ s), o ~ (o' ++ s), KnownList i', KnownList o') => (i' :-> o') -> i :-> o caar :: (((a, b1), b2) & s) :-> (a & s) cadr :: (((a, b1), b2) & s) :-> (b1 & s) cdar :: ((a1, (a2, b)) & s) :-> (a2 & s) cddr :: ((a1, (a2, b)) & s) :-> (b & s) ifRight :: ((b & s) :-> s') -> ((a & s) :-> s') -> (Either a b & s) :-> s' ifSome :: ((a & s) :-> s') -> (s :-> s') -> (Maybe a & s) :-> s' mapCar :: ((a & s) :-> (a1 & s)) -> ((a, b) & s) :-> ((a1, b) & s) mapCdr :: ((b & ((a, b) & s)) :-> (b1 & ((a, b) & s))) -> ((a, b) & s) :-> ((a, b1) & s) papair :: (a & (b & (c & s))) :-> (((a, b), c) & s) ppaiir :: (a & (b & (c & s))) :-> ((a, (b, c)) & s) unpair :: ((a, b) & s) :-> (a & (b & s)) setCar :: ((a, b1) & (b2 & s)) :-> ((b2, b1) & s) setCdr :: ((a, b1) & (b2 & s)) :-> ((a, b2) & s) -- | Insert given element into set. -- -- This is a separate function from updateMap because stacks -- they operate with differ in length. setInsert :: IsComparable e => (e & (Set e & s)) :-> (Set e & s) -- | Insert given element into map. mapInsert :: (MapInstrs map, IsComparable k) => (k : (v : (map k v : s))) :-> (map k v : s) -- | Insert given element into set, ensuring that it does not overwrite any -- existing entry. -- -- As first argument accepts container name. setInsertNew :: (IsComparable e, KnownValue err) => (forall s0. (e : s0) :-> (err : s0)) -> (e & (Set e & s)) :-> (Set e & s) -- | Insert given element into map, ensuring that it does not overwrite any -- existing entry. -- -- As first argument accepts container name (for error message). mapInsertNew :: (MapInstrs map, IsComparable k, KnownValue e) => (forall s0. (k : s0) :-> (e : s0)) -> (k : (v : (map k v : s))) :-> (map k v : s) -- | Delete element from the map. deleteMap :: forall k v s. (MapInstrs map, IsComparable k, KnownValue k, KnownValue v) => (k : (map k v : s)) :-> (map k v : s) -- | Delete given element from the set. setDelete :: IsComparable e => (e & (Set e & s)) :-> (Set e & s) -- | view type synonym as described in A1. data View (a :: Type) (r :: Type) View :: a -> ContractRef r -> View [viewParam] :: View -> a [viewCallbackTo] :: View -> ContractRef r -- | void type synonym as described in A1. data Void_ (a :: Type) (b :: Type) Void_ :: a -> Lambda b b -> Void_ -- | Entry point argument. [voidParam] :: Void_ -> a -- | Type of result reported via failWith. [voidResProxy] :: Void_ -> Lambda b b -- | Newtype over void result type used in tests to distinguish successful -- void result from other errors. -- -- Usage example: lExpectFailWith (== VoidResult roleMaster)` -- -- This error is special - it can contain arguments of different types -- depending on entrypoint which raises it. newtype VoidResult r VoidResult :: r -> VoidResult r [unVoidResult] :: VoidResult r -> r view_ :: NiceParameter r => (forall s0. ((a, storage) & s0) :-> (r : s0)) -> (View a r & (storage & s)) :-> ((List Operation, storage) & s) -- | Polymorphic version of View constructor. mkView :: ToContractRef r contract => a -> contract -> View a r void_ :: forall a b s s' anything. (IsError (VoidResult b), KnownValue b) => ((a & s) :-> (b & s')) -> (Void_ a b & s) :-> anything mkVoid :: forall b a. a -> Void_ a b buildView :: (a -> Builder) -> View a r -> Builder buildViewTuple :: TupleF a => View a r -> Builder -- | Push a value of contract type. -- -- Doing this via push instruction is not possible, so we need to -- perform extra actions here. -- -- Aside from contract value itself you will need to specify -- which error to throw in case this value is not valid. pushContractRef :: NiceParameter arg => (forall s0. (Address : s) :-> s0) -> ContractRef arg -> s :-> (ContractRef arg : s) -- | Turn FutureContract into actual contract. -- -- This requires contracts lookup and may fail. pickFutureContract :: NiceParameter p => (FutureContract p : s) :-> (Maybe (ContractRef p) : s) instance GHC.Classes.Eq r => GHC.Classes.Eq (Lorentz.Macro.VoidResult r) instance GHC.Generics.Generic (Lorentz.Macro.VoidResult r) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Macro.Void_ a b) instance GHC.Generics.Generic (Lorentz.Macro.Void_ a b) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Macro.View a r) instance GHC.Generics.Generic (Lorentz.Macro.View a r) instance GHC.Show.Show a => GHC.Show.Show (Lorentz.Macro.View a r) instance GHC.Classes.Eq a => GHC.Classes.Eq (Lorentz.Macro.View a r) instance (Michelson.Typed.Haskell.Doc.TypeHasDoc r, Lorentz.Errors.IsError (Lorentz.Macro.VoidResult r)) => Michelson.Typed.Haskell.Doc.TypeHasDoc (Lorentz.Macro.VoidResult r) instance (Data.Typeable.Internal.Typeable r, Lorentz.Constraints.NiceConstant r, Lorentz.Errors.ErrorHasDoc (Lorentz.Macro.VoidResult r)) => Lorentz.Errors.IsError (Lorentz.Macro.VoidResult r) instance Michelson.Typed.Haskell.Doc.TypeHasDoc r => Lorentz.Errors.ErrorHasDoc (Lorentz.Macro.VoidResult r) instance Lorentz.Errors.CustomErrorNoIsoValue (Lorentz.Macro.VoidResult r) => Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Macro.VoidResult r) instance Universum.TypeOps.Each '[Data.Typeable.Internal.Typeable, Michelson.Typed.Haskell.Doc.TypeHasDoc] '[a, r] => Michelson.Typed.Haskell.Doc.TypeHasDoc (Lorentz.Macro.Void_ a r) instance Formatting.Buildable.Buildable a => Formatting.Buildable.Buildable (Lorentz.Macro.Void_ a b) instance Universum.TypeOps.Each '[Data.Typeable.Internal.Typeable, Michelson.Typed.Haskell.Doc.TypeHasDoc] '[a, r] => Michelson.Typed.Haskell.Doc.TypeHasDoc (Lorentz.Macro.View a r) instance Formatting.Buildable.Buildable a => Formatting.Buildable.Buildable (Lorentz.Macro.View a r) instance Formatting.Buildable.Buildable (Lorentz.Macro.View () r) instance Lorentz.Macro.MapInstrs Data.Map.Internal.Map instance Lorentz.Macro.MapInstrs Michelson.Typed.Haskell.Value.BigMap instance forall k1 k2 (s :: [*]) a (xs :: [*]) (s1 :: k2) (tail :: k1). (s Data.Type.Equality.~ (a : xs)) => Lorentz.Macro.DuupX ('Data.Vinyl.TypeLevel.S 'Data.Vinyl.TypeLevel.Z) s a s1 tail instance forall k1 k2 b a (xs :: [*]) (s1 :: k2) (tail :: k1). Lorentz.Macro.DuupX ('Data.Vinyl.TypeLevel.S ('Data.Vinyl.TypeLevel.S 'Data.Vinyl.TypeLevel.Z)) (b : a : xs) a s1 tail instance Lorentz.Macro.ConstraintDuupXLorentz ('Data.Vinyl.TypeLevel.S ('Data.Vinyl.TypeLevel.S n)) s a s1 tail => Lorentz.Macro.DuupX ('Data.Vinyl.TypeLevel.S ('Data.Vinyl.TypeLevel.S ('Data.Vinyl.TypeLevel.S n))) s a s1 tail instance Lorentz.Macro.CloneX 'Data.Vinyl.TypeLevel.Z a s instance Lorentz.Macro.CloneX n a s => Lorentz.Macro.CloneX ('Data.Vinyl.TypeLevel.S n) a s -- | Instructions to work with UStore. module Lorentz.UStore.Instr -- | Put an empty UStore onto the stack. This function is generally -- unsafe: if store template contains a UStoreFieldExt, the -- resulting UStore is not immediately usable. If you are sure -- that UStore contains only submaps, feel free to just use the -- result of this function. Otherwise you must set all fields. unsafeEmptyUStore :: forall store s. s :-> (UStore store : s) ustoreMem :: forall store name s. KeyAccessC store name => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (Bool : s) ustoreGet :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (Maybe (GetUStoreValue store name) : s) ustoreUpdate :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (Maybe (GetUStoreValue store name) : (UStore store : s))) :-> (UStore store : s) ustoreInsert :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (GetUStoreValue store name : (UStore store : s))) :-> (UStore store : s) -- | Insert a key-value pair, but fail if it will overwrite some existing -- entry. ustoreInsertNew :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (forall s0 any. (GetUStoreKey store name : s0) :-> any) -> (GetUStoreKey store name : (GetUStoreValue store name : (UStore store : s))) :-> (UStore store : s) ustoreDelete :: forall store name s. KeyAccessC store name => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (UStore store : s) -- | Like toField, but for UStore. -- -- This may fail only if UStore was made up incorrectly during -- contract initialization. ustoreToField :: forall store name s. FieldAccessC store name => Label name -> (UStore store : s) :-> (GetUStoreField store name : s) -- | Like getField, but for UStore. -- -- This may fail only if UStore was made up incorrectly during -- contract initialization. ustoreGetField :: forall store name s. FieldAccessC store name => Label name -> (UStore store : s) :-> (GetUStoreField store name : (UStore store : s)) -- | Like setField, but for UStore. ustoreSetField :: forall store name s. FieldAccessC store name => Label name -> (GetUStoreField store name : (UStore store : s)) :-> (UStore store : s) -- | Remove a field from UStore, for internal purposes only. ustoreRemoveFieldUnsafe :: forall store name s. FieldAccessC store name => Label name -> (UStore store : s) :-> (UStore store : s) -- | This constraint can be used if a function needs to work with -- big store, but needs to know only about some submap(s) of it. -- -- It can use all UStore operations for a particular name, key and value -- without knowing whole template. type HasUStore name key value store = (KeyAccessC store name, ValueAccessC store name, GetUStoreKey store name ~ key, GetUStoreValue store name ~ value) -- | This constraint can be used if a function needs to work with -- big store, but needs to know only about some field of it. type HasUField name ty store = (FieldAccessC store name, GetUStoreField store name ~ ty) -- | Write down all sensisble constraints which given store -- satisfies and apply them to constrained. -- -- This store should have |~> and UStoreFieldExt fields -- in its immediate fields, no deep inspection is performed. type HasUStoreForAllIn store constrained = (Generic store, GHasStoreForAllIn constrained (Rep store)) packSubMapUKey :: forall (field :: Symbol) k s. (KnownSymbol field, NicePackedValue k) => (k : s) :-> (ByteString : s) instance GHC.Generics.Generic Lorentz.UStore.Instr.MyStoreTemplateBig instance GHC.Generics.Generic Lorentz.UStore.Instr.MyStoreTemplate3 instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.UStore.Instr.MyNatural instance Michelson.Typed.Haskell.Value.IsoCValue Lorentz.UStore.Instr.MyNatural instance GHC.Generics.Generic Lorentz.UStore.Instr.MyStoreTemplate2 instance GHC.Generics.Generic Lorentz.UStore.Instr.MyStoreTemplate instance Lorentz.UStore.Types.KnownUStoreMarker Lorentz.UStore.Instr.Marker1 -- | Elemental building blocks for migrations. module Lorentz.UStore.Migration.Blocks -- | Get the old version of storage. -- -- This can be applied only in the beginning of migration. -- -- In fact this function is not very useful, all required operations -- should be available for MUStore, but leaving it here just in -- case. mustoreToOld :: RequireBeInitial touched => (MUStore oldTemplate newTemplate remDiff touched : s) :-> (UStore oldTemplate : s) class MigrationFinishCheckPosition a -- | Put this in the end of migration script to get a human-readable -- message about remaining diff which yet should be covered. Use of this -- function in migration is fully optional. -- -- This function is not part of mkUStoreMigration for the sake of -- proper error messages ordering, during development you probably want -- errors in migration script to be located earlier in code than errors -- about not fully covered diff (if you used to fix errors in the same -- order in which they appear). migrationFinish :: MigrationFinishCheckPosition a => a -- | Cast field or submap pretending that its value fits to the new type. -- -- Useful when type of field, e.g. lambda or set of lambdas, is -- polymorphic over storage type. migrateCoerceUnsafe :: forall field oldTempl newTempl diff touched newDiff newDiff0 _1 _2 s. ('(_1, newDiff0) ~ CoverDiff 'DcRemove field diff, '(_2, newDiff) ~ CoverDiff 'DcAdd field newDiff0) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (MUStore oldTempl newTempl newDiff touched : s) -- | Get a field present in old version of UStore. migrateGetField :: forall field oldTempl newTempl diff touched fieldTy s. (HasUField field fieldTy oldTempl, RequireUntouched field (field `IsElem` touched)) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) -- | Add a field which was not present before. This covers one addition -- from the diff and any removals of field with given name. -- -- This function cannot overwrite existing field with the same name, if -- this is necessary use migrateOverwriteField which would declare -- removal explicitly. migrateAddField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcAdd field diff, HasUField field fieldTy newTempl) => Label field -> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Remove a field which should not be present in new version of storage. -- This covers one removal from the diff. -- -- In fact, this action could be performed automatically, but since -- removal is a destructive operation, being explicit about it seems like -- a good thing. migrateRemoveField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcRemove field diff, HasUField field fieldTy oldTempl) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Get and remove a field from old version of UStore. -- -- You probably want to use this more often than plain -- migrateRemoveField. migrateExtractField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcRemove field diff, HasUField field fieldTy oldTempl, RequireUntouched field (field `IsElem` touched)) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (fieldTy : (MUStore oldTempl newTempl newDiff (field : touched) : s)) -- | Remove field and write new one in place of it. -- -- This is semantically equivalent to dip (migrateRemoveField label) -- >> migrateAddField label, but is cheaper. migrateOverwriteField :: forall field oldTempl newTempl diff touched fieldTy oldFieldTy marker oldMarker newDiff newDiff0 s. ('(UStoreFieldExt oldMarker oldFieldTy, newDiff0) ~ CoverDiff 'DcRemove field diff, '(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcAdd field newDiff0, HasUField field fieldTy newTempl) => Label field -> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Modify field which should stay in new version of storage. This does -- not affect remaining diff. migrateModifyField :: forall field oldTempl newTempl diff touched fieldTy s. (HasUField field fieldTy oldTempl, HasUField field fieldTy newTempl) => Label field -> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) :-> (MUStore oldTempl newTempl diff touched : s) -- | Define a migration atom. -- -- It will be named automatically according to the set of actions it -- performs (via DMigrationActionDescs). This may be want you want -- for small sequences of actions, but for complex ones consider using -- muBlockNamed. Names are used in rendering migration plan. muBlock :: ('[MUStore o n d1 t1] :-> '[MUStore o n d2 t2]) -> MigrationBlocks o n d1 t1 d2 t2 -- | Define a migration atom with given name. -- -- Name will be used when rendering migration plan. muBlockNamed :: Text -> ('[MUStore o n d1 t1] :-> '[MUStore o n d2 t2]) -> MigrationBlocks o n d1 t1 d2 t2 -- | Composition of migration blocks. (<-->) :: MigrationBlocks o n d1 t1 d2 t2 -> MigrationBlocks o n d2 t2 d3 t3 -> MigrationBlocks o n d1 t1 d3 t3 infixl 2 <--> -- | This is $ operator with priority higher than <-->. -- -- It allows you writing -- --
--   mkUStoreBatchedMigration =
--     muBlock $: do
--       migrateAddField ...
--     --
--     muBlock $: do
--       migrateRemoveField ...
--   
-- -- Alternatively, BlockArguments extension can be used. ($:) :: (a -> b) -> a -> b infixr 7 $: instance (i Data.Type.Equality.~ (Lorentz.UStore.Migration.Base.MUStore oldTempl newTempl diff touched : s), o Data.Type.Equality.~ (Lorentz.UStore.Migration.Base.MUStore oldTempl newTempl '[] touched : s), Lorentz.UStore.Migration.Diff.RequireEmptyDiff diff) => Lorentz.UStore.Migration.Blocks.MigrationFinishCheckPosition (i Lorentz.Base.:-> o) instance (Lorentz.UStore.Migration.Diff.RequireEmptyDiff d1, t1 Data.Type.Equality.~ t2) => Lorentz.UStore.Migration.Blocks.MigrationFinishCheckPosition (Lorentz.UStore.Migration.Base.MigrationBlocks o n d1 t1 '[] t2) -- | Type-safe migrations of UStore. -- -- This implements imperative approach to migration when we make user -- write a code of migration and track whether all new fields were indeed -- added and all unnecessary fields were removed. -- -- You can find migration examples in tests. -- --

How to write your simple migration

-- --
    --
  1. Start with migration template:
    migration ::
    --   UStoreMigration V1.Storage V2.Storage migration =
    --   mkUStoreMigration $ do -- migration code to be put here
    --   migrationFinish 
    You will be prompted with a list of -- fields which should be added or removed.
  2. --
-- --
    --
  1. Add/remove necessary fields using migrateAddField, -- migrateExtractField and other instructions. They allow you to -- operate with MUStore — it is similar to UStore but -- used within mkUStoreMigration to track migration progress.
  2. --
  3. Use migrationToScript or migrationToTestScript to -- turn UStoreMigration into something useful.
  4. --
-- -- Note that here you will get a solid MigrationScript, thus -- migration has to fit into single Tezos transaction. If that's an -- issue, see the next section. -- --

How to write batched migration

-- --
    --
  1. Insert migration template.It looks like:
    migration ::
    --   UStoreMigration V1.Storage V2.Storage migration =
    --   mkUStoreBatchedMigration $ -- place for migration blocks
    --   migrationFinish 
  2. --
-- --
    --
  1. Fill migration code with blocks -- like
    mkUStoreBatchedMigration $ muBlock $: do
    --   -- code for block 1 <--> muBlock $: do --
    --   code for block 2 <--> migrationFinish
    --   
    Migration blocks have to be the smallest actions which can -- safely be mixed and splitted accross migration stages.
  2. --
  3. Compile migration with compileBatchedMigration.Here you -- have to supply batching implementation. Alternatives -- include
  4. --
  5. Get the required information about -- migration.
  6. --
-- --

Manual migrations

-- -- If for some reasons you need to define migration manually, you can use -- functions from Manual migrations section of -- Lorentz.UStore.Migration.Base. module Lorentz.UStore.Migration -- | Conversion between UStore in Haskell and Michelson -- representation. module Lorentz.UStore.Haskell -- | UStore content represented as key-value pairs. type UStoreContent = [(ByteString, ByteString)] -- | Given template can be converted to UStore value. class (Generic template, GUStoreConversible (Rep template)) => UStoreConversible template -- | Make UStore from separate big_maps and fields. mkUStore :: UStoreConversible template => template -> UStore template -- | Decompose UStore into separate big_maps and fields. -- -- Since this function needs to UNPACK content of -- UStore to actual keys and values, you have to provide -- UnpackEnv. -- -- Along with resulting value, you get a list of UStore entries -- which were not recognized as belonging to any submap or field -- according to UStore's template - this should be empty unless -- UStore invariants were violated. ustoreDecompose :: forall template. UStoreConversible template => UStore template -> Either Text (UStoreContent, template) -- | Like ustoreDecompose, but requires all entries from -- UStore to be recognized. ustoreDecomposeFull :: forall template. UStoreConversible template => UStore template -> Either Text template -- | Make migration script which initializes UStore from scratch. fillUStore :: UStoreConversible template => template -> UStoreMigrationT () template -- | Fill UStore with entries from the given template as part of -- simple migration. -- -- Sometimes you already have some fields initialized and -- fillUStore does not suit, then in case if your UStore template -- is a nested structure you can use sub-templates to initialize the -- corresponding parts of UStore. -- -- For batched migrations see fillUStoreMigrationBlock. migrateFillUStore :: (UStoreConversible template, allFieldsExp ~ AllUStoreFieldsF template, newDiff ~ FillingNewDiff template diff, newTouched ~ FillingNewTouched template touched, PatternMatchL newDiff, PatternMatchL newTouched) => template -> Lambda (MUStore oldTempl newTempl diff touched) (MUStore oldTempl newTempl newDiff newTouched) -- | Version of migrateFillUStore for batched migrations. -- -- Each field write will be placed to a separate batch. fillUStoreMigrationBlock :: (UStoreConversible template, allFieldsExp ~ AllUStoreFieldsF template, newDiff ~ FillingNewDiff template diff, newTouched ~ FillingNewTouched template touched, PatternMatchL newDiff, PatternMatchL newTouched) => template -> MigrationBlocks oldTempl newTempl diff touched newDiff newTouched instance GHC.Generics.Generic Lorentz.UStore.Haskell.MyStoreTemplateBig instance GHC.Generics.Generic Lorentz.UStore.Haskell.MyStoreTemplate instance (GHC.Generics.Generic template, Lorentz.UStore.Haskell.GUStoreConversible (GHC.Generics.Rep template)) => Lorentz.UStore.Haskell.UStoreConversible template instance Lorentz.UStore.Haskell.UStoreConversible template => Lorentz.UStore.Haskell.GUStoreConversible (GHC.Generics.S1 i (GHC.Generics.Rec0 template)) instance Lorentz.UStore.Haskell.GUStoreConversible x => Lorentz.UStore.Haskell.GUStoreConversible (GHC.Generics.D1 i x) instance Lorentz.UStore.Haskell.GUStoreConversible x => Lorentz.UStore.Haskell.GUStoreConversible (GHC.Generics.C1 i x) instance (TypeError ...) => Lorentz.UStore.Haskell.GUStoreConversible (x GHC.Generics.:+: y) instance (TypeError ...) => Lorentz.UStore.Haskell.GUStoreConversible GHC.Generics.V1 instance (Lorentz.UStore.Haskell.GUStoreConversible x, Lorentz.UStore.Haskell.GUStoreConversible y) => Lorentz.UStore.Haskell.GUStoreConversible (x GHC.Generics.:*: y) instance Lorentz.UStore.Haskell.GUStoreConversible GHC.Generics.U1 instance (Lorentz.Constraints.NiceFullPackedValue k, Lorentz.Constraints.NiceFullPackedValue v, GHC.TypeLits.KnownSymbol fieldName, GHC.Classes.Ord k) => Lorentz.UStore.Haskell.GUStoreConversible (GHC.Generics.S1 ('GHC.Generics.MetaSel ('GHC.Maybe.Just fieldName) _1 _2 _3) (GHC.Generics.Rec0 (k Lorentz.UStore.Types.|~> v))) instance (Lorentz.Constraints.NiceFullPackedValue v, Lorentz.UStore.Types.KnownUStoreMarker m, GHC.TypeLits.KnownSymbol fieldName) => Lorentz.UStore.Haskell.GUStoreConversible (GHC.Generics.S1 ('GHC.Generics.MetaSel ('GHC.Maybe.Just fieldName) _1 _2 _3) (GHC.Generics.Rec0 (Lorentz.UStore.Types.UStoreFieldExt m v))) module Lorentz.UParam -- | Encapsulates parameter for one of entry points. It keeps entry point -- name and corresponding argument serialized. -- -- In Haskell world, we keep an invariant of that contained value relates -- to one of entry points from entries list. newtype UParam (entries :: [EntryPointKind]) UParamUnsafe :: (MText, ByteString) -> UParam -- | An entry point is described by two types: its name and type of -- argument. type EntryPointKind = (Symbol, Type) -- | A convenient alias for type-level name-something pair. type (n :: Symbol) ?: (a :: k) = '(n, a) -- | Construct a UParam safely. mkUParam :: (KnownSymbol name, NicePackedValue a, LookupEntryPoint name entries ~ a, RequireUniqueEntryPoints entries) => Label name -> a -> UParam entries -- | This type can store any value that satisfies a certain constraint. data ConstrainedSome (c :: Type -> Constraint) [ConstrainedSome] :: c a => a -> ConstrainedSome c -- | This class is needed to implement unpackUParam. class UnpackUParam (c :: Type -> Constraint) entries -- | Turn UParam into a Haskell value. Since we don't know its type -- in compile time, we have to erase it using ConstrainedSome. The -- user of this function can require arbitrary constraint to hold -- (depending on how they want to use the result). unpackUParam :: UnpackUParam c entries => UParam entries -> Either EntryPointLookupError (MText, ConstrainedSome c) -- | Implementations of some entry points. -- -- Note that this thing inherits properties of Rec, e.g. you can -- Data.Vinyl.Core.rappend implementations for two entry point -- sets when assembling scattered parts of a contract. type EntryPointsImpl inp out entries = Rec (CaseClauseU inp out) entries -- | An action invoked when user-provided entry point is not found. type UParamFallback inp out = ((MText, ByteString) : inp) :-> out data EntryPointLookupError NoSuchEntryPoint :: MText -> EntryPointLookupError ArgumentUnpackFailed :: EntryPointLookupError -- | Make up a "case" over entry points. class CaseUParam (entries :: [EntryPointKind]) -- | Pattern-match on given UParam entries. -- -- You have to provide all case branches and a fallback action on case -- when entry point is not found. caseUParam :: (CaseUParam entries, RequireUniqueEntryPoints entries) => Rec (CaseClauseU inp out) entries -> UParamFallback inp out -> (UParam entries : inp) :-> out -- | Like caseUParam, but accepts a tuple of clauses, not a -- Rec. caseUParamT :: forall entries inp out clauses. (clauses ~ Rec (CaseClauseU inp out) entries, RecFromTuple clauses, CaseUParam entries) => IsoRecTuple clauses -> UParamFallback inp out -> (UParam entries : inp) :-> out -- | Default implementation for UParamFallback, simply reports an -- error. uparamFallbackFail :: UParamFallback inp out -- | Get type of entry point argument by its name. type family LookupEntryPoint (name :: Symbol) (entries :: [EntryPointKind]) :: Type -- | Ensure that given entry points do no contain duplicated names. type family RequireUniqueEntryPoints (entries :: [EntryPointKind]) :: Constraint -- | Make up UParam from ADT sum. -- -- Entry points template will consist of (constructorName, -- constructorFieldType) pairs. Each constructor is expected to have -- exactly one field. uparamFromAdt :: UParamLinearize up => up -> UParam (UParamLinearized up) -- | Constraint required by uparamFromAdt. type UParamLinearize p = (Generic p, GUParamLinearize (Rep p)) -- | Entry points template derived from given ADT sum. type UParamLinearized p = GUParamLinearized (Rep p) -- | Note that calling given entrypoints involves constructing -- UParam. pbsUParam :: forall ctorName. KnownSymbol ctorName => ParamBuildingStep -- | Helper instruction which extracts content of UParam. unwrapUParam :: (UParam entries : s) :-> ((MText, ByteString) : s) instance GHC.Show.Show Lorentz.UParam.EntryPointLookupError instance GHC.Classes.Eq Lorentz.UParam.EntryPointLookupError instance GHC.Generics.Generic Lorentz.UParam.EntryPointLookupError instance Michelson.Typed.Haskell.Value.IsoValue (Lorentz.UParam.UParam entries) instance GHC.Show.Show (Lorentz.UParam.UParam entries) instance GHC.Classes.Eq (Lorentz.UParam.UParam entries) instance GHC.Generics.Generic (Lorentz.UParam.UParam entries) instance Lorentz.UParam.GUParamLinearize x => Lorentz.UParam.GUParamLinearize (GHC.Generics.D1 i x) instance (Lorentz.UParam.GUParamLinearize x, Lorentz.UParam.GUParamLinearize y) => Lorentz.UParam.GUParamLinearize (x GHC.Generics.:+: y) instance (GHC.TypeLits.KnownSymbol name, Lorentz.Constraints.NicePackedValue a) => Lorentz.UParam.GUParamLinearize (GHC.Generics.C1 ('GHC.Generics.MetaCons name _1 _2) (GHC.Generics.S1 si (GHC.Generics.Rec0 a))) instance (TypeError ...) => Lorentz.UParam.GUParamLinearize (GHC.Generics.C1 i GHC.Generics.U1) instance (TypeError ...) => Lorentz.UParam.GUParamLinearize (GHC.Generics.C1 i (x GHC.Generics.:*: y)) instance Lorentz.UParam.CaseUParam '[] instance (GHC.TypeLits.KnownSymbol name, Lorentz.UParam.CaseUParam entries, Lorentz.Constraints.NiceUnpackedValue arg) => Lorentz.UParam.CaseUParam ((name Lorentz.UParam.?: arg) : entries) instance Lorentz.UParam.UnpackUParam c '[] instance (GHC.TypeLits.KnownSymbol name, Lorentz.UParam.UnpackUParam c entries, Lorentz.Constraints.NiceUnpackedValue arg, c arg) => Lorentz.UParam.UnpackUParam c ((name Lorentz.UParam.?: arg) : entries) instance Formatting.Buildable.Buildable Lorentz.UParam.EntryPointLookupError instance (name Data.Type.Equality.~ name', body Data.Type.Equality.~ ((arg : inp) Lorentz.Base.:-> out)) => Lorentz.ADT.CaseArrow name' body (Lorentz.UParam.CaseClauseU inp out '(name, arg)) instance GHC.Show.Show (Lorentz.UParam.ConstrainedSome GHC.Show.Show) instance Formatting.Buildable.Buildable (Lorentz.UParam.ConstrainedSome Formatting.Buildable.Buildable) instance Data.Typeable.Internal.Typeable interface => Michelson.Typed.Haskell.Doc.TypeHasDoc (Lorentz.UParam.UParam interface) instance Formatting.Buildable.Buildable (Lorentz.Errors.CustomError "uparamNoSuchEntryPoint") instance Formatting.Buildable.Buildable (Lorentz.Errors.CustomError "uparamArgumentUnpackFailed") instance Lorentz.Errors.CustomErrorHasDoc "uparamNoSuchEntryPoint" instance Lorentz.Errors.CustomErrorHasDoc "uparamArgumentUnpackFailed" -- | Contract which remembers all parameters it has been called with. -- -- Useful to save return values of View entry points. module Lorentz.Test.Consumer -- | Remembers parameters it was called with, last goes first. contractConsumer :: Contract cp [cp] -- | This module provides storage interfaces. module Lorentz.StoreClass -- | Provides operations on fields for storage. class StoreHasField store fname ftype | store fname -> ftype storeFieldOps :: StoreHasField store fname ftype => StoreFieldOps store fname ftype -- | Datatype containing the full implementation of StoreHasField -- typeclass. -- -- We use this grouping because in most cases implementation will be -- chosen among the default ones, and initializing all methods at once is -- simpler and more consistent. (One can say that we are trying to -- emulate benefits of DerivingVia extension.) data StoreFieldOps store fname ftype StoreFieldOps :: (forall s. Label fname -> (store : s) :-> (ftype : s)) -> (forall s. Label fname -> (ftype : (store : s)) :-> (store : s)) -> StoreFieldOps store fname ftype [sopToField] :: StoreFieldOps store fname ftype -> forall s. Label fname -> (store : s) :-> (ftype : s) [sopSetField] :: StoreFieldOps store fname ftype -> forall s. Label fname -> (ftype : (store : s)) :-> (store : s) -- | Provides operations on fields for storage. class StoreHasSubmap store mname key value | store mname -> key value storeSubmapOps :: StoreHasSubmap store mname key value => StoreSubmapOps store mname key value -- | Datatype containing the full implementation of StoreHasField -- typeclass. -- -- We use this grouping because in most cases implementation will be -- chosen among the default ones, and initializing all methods at once is -- simpler and more consistent. (One can say that we are trying to -- emulate DerivingVia extension.) data StoreSubmapOps store mname key value StoreSubmapOps :: (forall s. Label mname -> (key : (store : s)) :-> (Bool : s)) -> (forall s. Label mname -> (key : (store : s)) :-> (Maybe value : s)) -> (forall s. Label mname -> (key : (Maybe value : (store : s))) :-> (store : s)) -> (forall s. Maybe (Label mname -> (key : (store : s)) :-> (store : s))) -> (forall s. Maybe (Label mname -> (key : (value : (store : s))) :-> (store : s))) -> StoreSubmapOps store mname key value [sopMem] :: StoreSubmapOps store mname key value -> forall s. Label mname -> (key : (store : s)) :-> (Bool : s) [sopGet] :: StoreSubmapOps store mname key value -> forall s. Label mname -> (key : (store : s)) :-> (Maybe value : s) [sopUpdate] :: StoreSubmapOps store mname key value -> forall s. Label mname -> (key : (Maybe value : (store : s))) :-> (store : s) [sopDelete] :: StoreSubmapOps store mname key value -> forall s. Maybe (Label mname -> (key : (store : s)) :-> (store : s)) [sopInsert] :: StoreSubmapOps store mname key value -> forall s. Maybe (Label mname -> (key : (value : (store : s))) :-> (store : s)) -- | Indicates a submap with given key and value types. data k ~> v infix 9 ~> -- | Concise way to write down constraints with expected content of a -- storage. -- -- Use it like follows: -- --
--   type StorageConstraint = StorageContains
--     [ "fieldInt" := Int
--     , "fieldNat" := Nat
--     , "balances" := Address ~> Int
--     ]
--   
type family StorageContains store (content :: [NamedField]) :: Constraint -- | Pick storage field. stToField :: StoreHasField store fname ftype => Label fname -> (store : s) :-> (ftype : s) -- | Get storage field, preserving the storage itself on stack. stGetField :: StoreHasField store fname ftype => Label fname -> (store : s) :-> (ftype : (store : s)) -- | Update storage field. stSetField :: StoreHasField store fname ftype => Label fname -> (ftype : (store : s)) :-> (store : s) -- | Check value presence in storage. stMem :: StoreHasSubmap store mname key value => Label mname -> (key : (store : s)) :-> (Bool : s) -- | Get value in storage. stGet :: StoreHasSubmap store mname key value => Label mname -> (key : (store : s)) :-> (Maybe value : s) -- | Update a value in storage. stUpdate :: StoreHasSubmap store mname key value => Label mname -> (key : (Maybe value : (store : s))) :-> (store : s) -- | Delete a value in storage. stDelete :: forall store mname key value s. (StoreHasSubmap store mname key value, KnownValue value) => Label mname -> (key : (store : s)) :-> (store : s) -- | Add a value in storage. stInsert :: StoreHasSubmap store mname key value => Label mname -> (key : (value : (store : s))) :-> (store : s) -- | Add a value in storage, but fail if it will overwrite some existing -- entry. stInsertNew :: StoreHasSubmap store mname key value => Label mname -> (forall s0 any. (key : s0) :-> any) -> (key : (value : (store : s))) :-> (store : s) -- | Implementation of StoreHasField for case of datatype keeping a -- pack of fields. storeFieldOpsADT :: HasFieldOfType dt fname ftype => StoreFieldOps dt fname ftype -- | Implementation of StoreHasField for a data type which has an -- instance of StoreHasField inside. For instance, it can be used -- for top-level storage. storeFieldOpsDeeper :: (HasFieldOfType storage fieldsPartName fields, StoreHasField fields fname ftype) => Label fieldsPartName -> StoreFieldOps storage fname ftype -- | Implementation of StoreHasSubmap for a data type which has an -- instance of StoreHasSubmap inside. For instance, it can be used -- for top-level storage. storeSubmapOpsDeeper :: (HasFieldOfType storage bigMapPartName fields, StoreHasSubmap fields mname key value) => Label bigMapPartName -> StoreSubmapOps storage mname key value -- | Pretend that given StoreSubmapOps implementation is made up for -- submap with name desiredName, not its actual name. Logic of -- the implementation remains the same. -- -- See also storeSubmapOpsReferTo. storeFieldOpsReferTo :: Label name -> StoreFieldOps storage name field -> StoreFieldOps storage desiredName field -- | Pretend that given StoreSubmapOps implementation is made up for -- submap with name desiredName, not its actual name. Logic of -- the implementation remains the same. -- -- Use case: imagine that your code requires access to submap named -- X, but in your storage that submap is called Y. Then -- you implement the instance which makes X refer to Y: -- --
--   instance StoreHasSubmap Store X Key Value where
--     storeSubmapOps = storeSubmapOpsReferTo #Y storeSubmapOpsForY
--   
storeSubmapOpsReferTo :: Label name -> StoreSubmapOps storage name key value -> StoreSubmapOps storage desiredName key value -- | Chain two implementations of field operations. -- -- Suits for a case when your store does not contain its fields directly -- rather has a nested structure. composeStoreFieldOps :: Label nameInStore -> StoreFieldOps store nameInStore substore -> StoreFieldOps substore nameInSubstore field -> StoreFieldOps store nameInSubstore field -- | Chain implementations of field and submap operations. composeStoreSubmapOps :: Label nameInStore -> StoreFieldOps store nameInStore substore -> StoreSubmapOps substore mname key value -> StoreSubmapOps store mname key value instance (key Data.Type.Equality.~ key', value Data.Type.Equality.~ value', Michelson.Typed.Haskell.Value.IsComparable key) => Lorentz.StoreClass.StoreHasSubmap (Michelson.Typed.Haskell.Value.BigMap key' value') name key value instance (key Data.Type.Equality.~ key', value Data.Type.Equality.~ value', Michelson.Typed.Haskell.Value.IsComparable key) => Lorentz.StoreClass.StoreHasSubmap (Data.Map.Internal.Map key' value') name key value module Lorentz.UStore.Instances instance Lorentz.UStore.Instr.HasUField fname ftype templ => Lorentz.StoreClass.StoreHasField (Lorentz.UStore.Types.UStore templ) fname ftype instance Lorentz.UStore.Instr.HasUStore mname key value templ => Lorentz.StoreClass.StoreHasSubmap (Lorentz.UStore.Types.UStore templ) mname key value -- | This module contains implementation of UStore. -- -- UStore is essentially Store modified for the sake of -- upgradeability. -- -- In API it differs from Store in the following ways: 1. It -- keeps both virtual big_maps and plain fields; 2. Neat -- conversion between Michelson and Haskell values is implemented; 3. -- Regarding composabililty, one can operate with one UStore and -- then lift it to a bigger one which includes the former. This allows -- for simpler management of stores and clearer error messages. In spite -- of this, operations with UStores over deeply nested templates -- will still work as before. -- -- We represent UStore as big_map bytes bytes. -- -- module Lorentz.UStore -- | Gathers multple fields and BigMaps under one object. -- -- Type argument of this datatype stands for a "store template" - a -- datatype with one constructor and multiple fields, each containing an -- object of type UStoreFieldExt or |~> and -- corresponding to single virtual field or BigMap respectively. -- It's also possible to parameterize it with a larger type which is a -- product of types satisfying the above property. data UStore (a :: Type) -- | Describes one virtual big map in the storage. newtype k |~> v UStoreSubMap :: Map k v -> (|~>) k v [unUStoreSubMap] :: (|~>) k v -> Map k v -- | Describes plain field in the storage. newtype UStoreFieldExt (m :: UStoreMarkerType) (v :: Type) UStoreField :: v -> UStoreFieldExt [unUStoreField] :: UStoreFieldExt -> v -- | Just a plain field used as data. type UStoreField = UStoreFieldExt UMarkerPlainField -- | Specific kind used to designate markers for UStoreFieldExt. -- -- We suggest that fields may serve different purposes and so annotated -- with special markers accordingly. See example below. -- -- This kind is implemented like that because we want markers to differ -- from all other types in kind; herewith UStoreMarkerType is -- still an open kind (has potentially infinite number of inhabitants). type UStoreMarkerType = UStoreMarker -> Type -- | Allows to specify format of key under which fields of this type are -- stored. Useful to avoid collisions. class KnownUStoreMarker (marker :: UStoreMarkerType) where { -- | Display type-level information about UStore field with given marker -- and field value type. Used for error messages. type family ShowUStoreField marker v :: ErrorMessage; type ShowUStoreField marker v = 'Text "field of type " :<>: 'ShowType v; } -- | By field name derive key under which field should be stored. mkFieldMarkerUKey :: (KnownUStoreMarker marker, KnownSymbol name) => Label name -> ByteString -- | By field name derive key under which field should be stored. mkFieldMarkerUKey :: (KnownUStoreMarker marker, KnownSymbol name) => Label name -> ByteString -- | Get type of submap key. type GetUStoreKey store name = MSKey (GetUStore name store) -- | Get type of submap value. type GetUStoreValue store name = MSValue (GetUStore name store) -- | Get type of plain field. This ignores marker with field type. type GetUStoreField store name = FSValue (GetUStore name store) -- | Get kind of field. type GetUStoreFieldMarker store name = FSMarker (GetUStore name store) ustoreMem :: forall store name s. KeyAccessC store name => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (Bool : s) ustoreGet :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (Maybe (GetUStoreValue store name) : s) ustoreUpdate :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (Maybe (GetUStoreValue store name) : (UStore store : s))) :-> (UStore store : s) ustoreInsert :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (GetUStoreValue store name : (UStore store : s))) :-> (UStore store : s) -- | Insert a key-value pair, but fail if it will overwrite some existing -- entry. ustoreInsertNew :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (forall s0 any. (GetUStoreKey store name : s0) :-> any) -> (GetUStoreKey store name : (GetUStoreValue store name : (UStore store : s))) :-> (UStore store : s) ustoreDelete :: forall store name s. KeyAccessC store name => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (UStore store : s) -- | Like toField, but for UStore. -- -- This may fail only if UStore was made up incorrectly during -- contract initialization. ustoreToField :: forall store name s. FieldAccessC store name => Label name -> (UStore store : s) :-> (GetUStoreField store name : s) -- | Like getField, but for UStore. -- -- This may fail only if UStore was made up incorrectly during -- contract initialization. ustoreGetField :: forall store name s. FieldAccessC store name => Label name -> (UStore store : s) :-> (GetUStoreField store name : (UStore store : s)) -- | Like setField, but for UStore. ustoreSetField :: forall store name s. FieldAccessC store name => Label name -> (GetUStoreField store name : (UStore store : s)) :-> (UStore store : s) -- | This constraint can be used if a function needs to work with -- big store, but needs to know only about some submap(s) of it. -- -- It can use all UStore operations for a particular name, key and value -- without knowing whole template. type HasUStore name key value store = (KeyAccessC store name, ValueAccessC store name, GetUStoreKey store name ~ key, GetUStoreValue store name ~ value) -- | This constraint can be used if a function needs to work with -- big store, but needs to know only about some field of it. type HasUField name ty store = (FieldAccessC store name, GetUStoreField store name ~ ty) -- | Write down all sensisble constraints which given store -- satisfies and apply them to constrained. -- -- This store should have |~> and UStoreFieldExt fields -- in its immediate fields, no deep inspection is performed. type HasUStoreForAllIn store constrained = (Generic store, GHasStoreForAllIn constrained (Rep store)) -- | Lift an UStore to another UStore which contains all the -- entries of the former under given field. -- -- This function is not intended for use in migrations, only in normal -- entry points. -- -- Note that this function ensures that template of resulting store does -- not contain inner nested templates with duplicated fields, otherwise -- UStore invariants could get broken. liftUStore :: (Generic template, RequireAllUniqueFields template) => Label name -> (UStore (GetFieldType template name) : s) :-> (UStore template : s) -- | Unlift an UStore to a smaller UStore which is part of -- the former. -- -- This function is not intended for use in migrations, only in normal -- entry points. -- -- Surprisingly, despite smaller UStore may have extra entries, -- this function is safe when used in contract code. Truly, all getters -- and setters are still safe to use. Also, there is no way for the -- resulting small UStore to leak outside of the contract since -- the only place where big_map can appear is contract storage, -- so this small UStore can be either dropped or lifted back via -- liftUStore to appear as part of the new contract's state. -- -- When this function is run as part of standalone instructions sequence, -- not as part of contract code (e.g. in tests), you may get an -- UStore with entries not inherent to it. unliftUStore :: Generic template => Label name -> (UStore template : s) :-> (UStore (GetFieldType template name) : s) -- | Given template can be converted to UStore value. class (Generic template, GUStoreConversible (Rep template)) => UStoreConversible template -- | Make UStore from separate big_maps and fields. mkUStore :: UStoreConversible template => template -> UStore template -- | Decompose UStore into separate big_maps and fields. -- -- Since this function needs to UNPACK content of -- UStore to actual keys and values, you have to provide -- UnpackEnv. -- -- Along with resulting value, you get a list of UStore entries -- which were not recognized as belonging to any submap or field -- according to UStore's template - this should be empty unless -- UStore invariants were violated. ustoreDecompose :: forall template. UStoreConversible template => UStore template -> Either Text (UStoreContent, template) -- | Like ustoreDecompose, but requires all entries from -- UStore to be recognized. ustoreDecomposeFull :: forall template. UStoreConversible template => UStore template -> Either Text template -- | Make migration script which initializes UStore from scratch. fillUStore :: UStoreConversible template => template -> UStoreMigrationT () template -- | Absolutely empty storage. type InitUStore = UStore () -- | Code of migration for UStore. -- -- Invariant: preferably should fit into op size / gas limits (quite -- obvious). Often this stands for exactly one stage of migration (one -- Tezos transaction). newtype MigrationScript MigrationScript :: Lambda UStore_ UStore_ -> MigrationScript [unMigrationScript] :: MigrationScript -> Lambda UStore_ UStore_ -- | Keeps information about migration between UStores with two -- given templates. Note that it is polymorphic over whole storage types, -- not their templates, for convenience (so that there is no need to -- export the template). data UStoreMigration (oldStore :: Type) (newStore :: Type) -- | Alias for UStoreMigration which accepts UStore templates as -- type arguments. type UStoreMigrationT ot nt = UStoreMigration (UStore ot) (UStore nt) -- | Get migration script in case of simple (non-batched) migration. migrationToScript :: UStoreMigration ot nt -> MigrationScript -- | Turn Migration into a whole piece of code for transforming -- storage. -- -- This is not want you'd want to use for contract deployment because of -- gas and operation size limits that Tezos applies to transactions. migrationToLambda :: UStoreMigrationT oldTemplate newTemplate -> Lambda (UStore oldTemplate) (UStore newTemplate) -- | Safe way to create migration scripts for UStore. -- -- You have to supply a code which would transform MUStore, -- coverring required diff step-by-step. All basic instructions work, -- also use migrate* functions from this module to operate with -- MUStore. -- -- This method produces a whole migration, it cannot be splitted in -- batches. In case if your migration is too big to be applied within a -- single transaction, use mkUStoreBatchedMigration. mkUStoreMigration :: Lambda (MUStore oldTempl newTempl (BuildDiff oldTempl newTempl) '[]) (MUStore oldTempl newTempl '[] _1) -> UStoreMigrationT oldTempl newTempl -- | Get the old version of storage. -- -- This can be applied only in the beginning of migration. -- -- In fact this function is not very useful, all required operations -- should be available for MUStore, but leaving it here just in -- case. mustoreToOld :: RequireBeInitial touched => (MUStore oldTemplate newTemplate remDiff touched : s) :-> (UStore oldTemplate : s) -- | Get a field present in old version of UStore. migrateGetField :: forall field oldTempl newTempl diff touched fieldTy s. (HasUField field fieldTy oldTempl, RequireUntouched field (field `IsElem` touched)) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) -- | Add a field which was not present before. This covers one addition -- from the diff and any removals of field with given name. -- -- This function cannot overwrite existing field with the same name, if -- this is necessary use migrateOverwriteField which would declare -- removal explicitly. migrateAddField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcAdd field diff, HasUField field fieldTy newTempl) => Label field -> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Remove a field which should not be present in new version of storage. -- This covers one removal from the diff. -- -- In fact, this action could be performed automatically, but since -- removal is a destructive operation, being explicit about it seems like -- a good thing. migrateRemoveField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcRemove field diff, HasUField field fieldTy oldTempl) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Get and remove a field from old version of UStore. -- -- You probably want to use this more often than plain -- migrateRemoveField. migrateExtractField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcRemove field diff, HasUField field fieldTy oldTempl, RequireUntouched field (field `IsElem` touched)) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (fieldTy : (MUStore oldTempl newTempl newDiff (field : touched) : s)) -- | Remove field and write new one in place of it. -- -- This is semantically equivalent to dip (migrateRemoveField label) -- >> migrateAddField label, but is cheaper. migrateOverwriteField :: forall field oldTempl newTempl diff touched fieldTy oldFieldTy marker oldMarker newDiff newDiff0 s. ('(UStoreFieldExt oldMarker oldFieldTy, newDiff0) ~ CoverDiff 'DcRemove field diff, '(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcAdd field newDiff0, HasUField field fieldTy newTempl) => Label field -> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Collect all fields with the given marker. type PickMarkedFields marker template = GPickMarkedFields marker (Rep template) -- | Impementation of Store - object incapsulating multiple -- BigMaps. -- -- This module also provides template for the contract storage - -- StorageSkeleton. -- -- We represent Store as big_map bytes (a | b | ...). -- -- Key of this map is formed as (index, orig_key), where -- index is zero-based index of emulated map, orig_key -- is key of this emulated map. -- -- Value of this map is just a union of emulated map's values. -- | Deprecated: Contract storage can contain multiple big_maps starting -- from Michelson 005 module Lorentz.Store -- | Gathers multple BigMaps under one object. -- -- Type argument of this datatype stands for a "map template" - a -- datatype with multiple constructors, each containing an object of type -- |-> and corresponding to single virtual BigMap. It's -- also possible to parameterize it with a larger type which is a sum of -- types satisfying the above property. -- -- Inside it keeps only one BigMap thus not violating Michelson -- limitations. -- -- See examples below. newtype Store a Store :: BigMap ByteString a -> Store a [unStore] :: Store a -> BigMap ByteString a -- | Describes one virtual big map. data k |-> v type GetStoreKey store name = MSKey (GetStore name store) type GetStoreValue store name = MSValue (GetStore name store) storeMem :: forall store name s. StoreMemC store name => Label name -> (GetStoreKey store name : (Store store : s)) :-> (Bool : s) storeGet :: forall store name s. StoreGetC store name => Label name -> (GetStoreKey store name : (Store store : s)) :-> (Maybe (GetStoreValue store name) : s) storeUpdate :: forall store name s. StoreUpdateC store name => Label name -> (GetStoreKey store name : (Maybe (GetStoreValue store name) : (Store store : s))) :-> (Store store : s) storeInsert :: forall store name s. StoreInsertC store name => Label name -> (GetStoreKey store name : (GetStoreValue store name : (Store store : s))) :-> (Store store : s) -- | Insert a key-value pair, but fail if it will overwrite some existing -- entry. storeInsertNew :: forall store name s. (StoreInsertC store name, KnownSymbol name) => Label name -> (forall s0 any. (GetStoreKey store name : s0) :-> any) -> (GetStoreKey store name : (GetStoreValue store name : (Store store : s))) :-> (Store store : s) storeDelete :: forall store name s. StoreDeleteC store name => Label name -> (GetStoreKey store name : (Store store : s)) :-> (Store store : s) type StoreMemC store name = StoreOpC store name type StoreGetC store name = (StoreOpC store name, InstrUnwrapC store name, KnownValue (GetStoreValue store name), CtorHasOnlyField name store (GetStoreKey store name |-> GetStoreValue store name)) type StoreUpdateC store name = (KnownValue store, StoreOpC store name, InstrWrapC store name, CtorHasOnlyField name store (GetStoreKey store name |-> GetStoreValue store name)) type StoreInsertC store name = (StoreOpC store name, InstrWrapC store name, CtorHasOnlyField name store (GetStoreKey store name |-> GetStoreValue store name)) type StoreDeleteC store name = (StoreOpC store name, KnownValue store) -- | This constraint can be used if a function needs to work with -- big store, but needs to know only about some part(s) of it. -- -- It can use all Store operations for a particular name, key and value -- without knowing whole template. type HasStore name key value store = (StoreGetC store name, StoreInsertC store name, StoreDeleteC store name, GetStoreKey store name ~ key, GetStoreValue store name ~ value, StorePieceC store name key value) -- | Write down all sensisble constraints which given store -- satisfies and apply them to constrained. -- -- This store should have |-> datatype in its immediate fields, -- no deep inspection is performed. type HasStoreForAllIn store constrained = GForAllHasStore constrained (Rep store) -- | Contract storage with big_map. -- -- Due to Michelson constraints it is the only possible layout containing -- big_map. data StorageSkeleton storeTemplate other StorageSkeleton :: Store storeTemplate -> other -> StorageSkeleton storeTemplate other [sMap] :: StorageSkeleton storeTemplate other -> Store storeTemplate [sFields] :: StorageSkeleton storeTemplate other -> other -- | Unpack StorageSkeleton into a pair. storageUnpack :: (StorageSkeleton store fields : s) :-> ((Store store, fields) : s) -- | Pack a pair into StorageSkeleton. storagePack :: ((Store store, fields) : s) :-> (StorageSkeleton store fields : s) storageMem :: forall store name fields s. StoreMemC store name => Label name -> (GetStoreKey store name : (StorageSkeleton store fields : s)) :-> (Bool : s) storageGet :: forall store name fields s. StoreGetC store name => Label name -> (GetStoreKey store name : (StorageSkeleton store fields : s)) :-> (Maybe (GetStoreValue store name) : s) storageInsert :: forall store name fields s. StoreInsertC store name => Label name -> (GetStoreKey store name : (GetStoreValue store name : (StorageSkeleton store fields : s))) :-> (StorageSkeleton store fields : s) -- | Insert a key-value pair, but fail if it will overwrite some existing -- entry. storageInsertNew :: forall store name fields s. (StoreInsertC store name, KnownSymbol name) => Label name -> (forall s0 any. (GetStoreKey store name : s0) :-> any) -> (GetStoreKey store name : (GetStoreValue store name : (StorageSkeleton store fields : s))) :-> (StorageSkeleton store fields : s) storageDelete :: forall store name fields s. StoreDeleteC store name => Label name -> (GetStoreKey store name : (StorageSkeleton store fields : s)) :-> (StorageSkeleton store fields : s) -- | Lift a key-value pair to Store. -- -- Further you can use Monoid instance of Store to make -- up large stores. storePiece :: forall name store key value. StorePieceC store name key value => Label name -> key -> value -> Store store storeKeyValueList :: forall name store key value. StorePieceC store name key value => Label name -> [(key, value)] -> Store store -- | Get a value from store by key. -- -- It expects map to be consistent, otherwise call to this function fails -- with error. storeLookup :: forall name store key value ctorIdx. (key ~ GetStoreKey store name, value ~ GetStoreValue store name, ctorIdx ~ MSCtorIdx (GetStore name store), NicePackedValue key, KnownNat ctorIdx, InstrUnwrapC store name, Generic store, CtorOnlyField name store ~ (key |-> value)) => Label name -> key -> Store store -> Maybe value type StorePieceC store name key value = (key ~ GetStoreKey store name, value ~ GetStoreValue store name, NicePackedValue key, KnownNat (MSCtorIdx (GetStore name store)), InstrWrapC store name, Generic store, ExtractCtorField (GetCtorField store name) ~ (key |-> value)) instance (Michelson.Typed.Haskell.Value.IsoValue storeTemplate, Michelson.Typed.Haskell.Value.IsoValue other) => Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Store.StorageSkeleton storeTemplate other) instance Data.Default.Class.Default other => Data.Default.Class.Default (Lorentz.Store.StorageSkeleton storeTemplate other) instance GHC.Generics.Generic (Lorentz.Store.StorageSkeleton storeTemplate other) instance (GHC.Show.Show storeTemplate, GHC.Show.Show other) => GHC.Show.Show (Lorentz.Store.StorageSkeleton storeTemplate other) instance (GHC.Classes.Eq storeTemplate, GHC.Classes.Eq other) => GHC.Classes.Eq (Lorentz.Store.StorageSkeleton storeTemplate other) instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.Store.MyStoreTemplateBig instance GHC.Generics.Generic Lorentz.Store.MyStoreTemplateBig instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.Store.MyStoreTemplate3 instance GHC.Generics.Generic Lorentz.Store.MyStoreTemplate3 instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.Store.MyNatural instance Michelson.Typed.Haskell.Value.IsoCValue Lorentz.Store.MyNatural instance GHC.Generics.Generic Lorentz.Store.MyNatural instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.Store.MyStoreTemplate2 instance GHC.Generics.Generic Lorentz.Store.MyStoreTemplate2 instance Michelson.Typed.Haskell.Value.IsoValue Lorentz.Store.MyStoreTemplate instance GHC.Generics.Generic Lorentz.Store.MyStoreTemplate instance forall k1 (k2 :: k1) v. Michelson.Typed.Haskell.Value.IsoValue v => Michelson.Typed.Haskell.Value.IsoValue (k2 Lorentz.Store.|-> v) instance forall k1 (k2 :: k1) v. GHC.Generics.Generic (k2 Lorentz.Store.|-> v) instance Michelson.Typed.Haskell.Value.IsoValue a => Michelson.Typed.Haskell.Value.IsoValue (Lorentz.Store.Store a) instance GHC.Base.Monoid (Lorentz.Store.Store a) instance GHC.Base.Semigroup (Lorentz.Store.Store a) instance Data.Default.Class.Default (Lorentz.Store.Store a) instance GHC.Show.Show a => GHC.Show.Show (Lorentz.Store.Store a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Lorentz.Store.Store a) instance (Lorentz.StoreClass.StoreHasField other fname ftype, Michelson.Typed.Haskell.Value.IsoValue store, Michelson.Typed.Haskell.Value.IsoValue other) => Lorentz.StoreClass.StoreHasField (Lorentz.Store.StorageSkeleton store other) fname ftype instance (Lorentz.Store.StoreMemC store name, Lorentz.Store.StoreGetC store name, Lorentz.Store.StoreUpdateC store name, key Data.Type.Equality.~ Lorentz.Store.GetStoreKey store name, value Data.Type.Equality.~ Lorentz.Store.GetStoreValue store name, Michelson.Typed.Haskell.Value.IsoValue other) => Lorentz.StoreClass.StoreHasSubmap (Lorentz.Store.StorageSkeleton store other) name key value instance (Lorentz.Store.StoreMemC store name, Lorentz.Store.StoreGetC store name, Lorentz.Store.StoreUpdateC store name, key Data.Type.Equality.~ Lorentz.Store.GetStoreKey store name, value Data.Type.Equality.~ Lorentz.Store.GetStoreValue store name) => Lorentz.StoreClass.StoreHasSubmap (Lorentz.Store.Store store) name key value -- | Reimplementation of some syntax sugar. -- -- You need the following module pragmas to make it work smoothly: module Lorentz.Rebinded -- | Aliases for '(#)' used by do-blocks. (>>) :: (a :-> b) -> (b :-> c) -> a :-> c -- | Lift a value. pure :: Applicative f => a -> f a -- | Inject a value into the monadic type. return :: Monad m => a -> m a -- | Defines semantics of if ... then ... else ... construction. ifThenElse :: Condition st arg argl argr -> (argl :-> o) -> (argr :-> o) -> arg :-> o -- | Predicate for if ... then .. else ... construction, defines a -- kind of operation applied to the top elements of the current stack. data Condition st arg argl argr [Holds] :: Condition s (Bool : s) s s [IsSome] :: Condition s (Maybe a : s) (a : s) s [IsNone] :: Condition s (Maybe a : s) s (a : s) [IsLeft] :: Condition s (Either l r : s) (l : s) (r : s) [IsRight] :: Condition s (Either l r : s) (r : s) (l : s) [IsCons] :: Condition s ([a] : s) (a : ([a] : s)) s [IsNil] :: Condition s ([a] : s) s (a : ([a] : s)) [IsZero] :: (UnaryArithOpHs Eq' a, UnaryArithResHs Eq' a ~ Bool) => Condition s (a : s) s s [IsNotZero] :: (UnaryArithOpHs Eq' a, UnaryArithResHs Eq' a ~ Bool) => Condition s (a : s) s s [IsEq] :: IfCmpXConstraints a Eq' => Condition s (a : (a : s)) s s [IsNeq] :: IfCmpXConstraints a Neq => Condition s (a : (a : s)) s s [IsLt] :: IfCmpXConstraints a Lt => Condition s (a : (a : s)) s s [IsGt] :: IfCmpXConstraints a Gt => Condition s (a : (a : s)) s s [IsLe] :: IfCmpXConstraints a Le => Condition s (a : (a : s)) s s [IsGe] :: IfCmpXConstraints a Ge => Condition s (a : (a : s)) s s -- | Conversion from an Integer. An integer literal represents the -- application of the function fromInteger to the appropriate -- value of type Integer, so such literals have type -- (Num a) => a. fromInteger :: Num a => Integer -> a fromString :: IsString a => String -> a fromLabel :: IsLabel x a => a -- | By default we represent error tags using strings. This module makes it -- possible to use numbers instead. -- -- There are two possible ways to use it: 1. If you have just one Lorentz -- instruction (potentially a big one), just use useNumericErrors -- function. It will change error representation there and return a map -- that can be used to interpret new error codes. 2. If your contract -- consists of multiple parts, start with gathering all error tags -- (gatherErrorTags). Then build ErrorTagMap using -- addNewErrorTags. Pass empty map if you are building from -- scratch (you can use buildErrorTagMap shortcut) or an existing -- map if you have one (e. g. you are upgrading a contract). module Lorentz.Errors.Numeric -- | This is a bidirectional map with correspondence between numeric and -- textual error tags. type ErrorTagMap = Bimap Natural MText -- | Find all textual error tags that are used in typical FAILWITH -- patterns within given instruction. Map them to natural numbers. gatherErrorTags :: (inp :-> out) -> HashSet MText -- | Add more error tags to an existing ErrorTagMap. It is useful -- when your contract consists of multiple parts (e. g. in case of -- contract upgrade), you have existing map for some part and want to add -- tags from another part to it. You can pass empty map as existing one -- if you just want to build ErrorTagMap from a set of textual -- tags. See buildErrorTagMap. addNewErrorTags :: ErrorTagMap -> HashSet MText -> ErrorTagMap -- | Build ErrorTagMap from a set of textual tags. buildErrorTagMap :: HashSet MText -> ErrorTagMap -- | For each typical FAILWITH that uses a string to represent error -- tag this function changes error tag to be a number using the supplied -- conversion map. It assumes that supplied map contains all such strings -- (and will error out if it does not). It will always be the case if you -- gather all error tags using gatherErrorTags and build -- ErrorTagMap from them using addNewErrorTags. applyErrorTagMap :: HasCallStack => ErrorTagMap -> (inp :-> out) -> inp :-> out -- | This function implements the simplest scenario of using this module's -- functionality: 1. Gather all error tags from a single instruction. 2. -- Turn them into error conversion map. 3. Apply this conversion. useNumericErrors :: HasCallStack => (inp :-> out) -> (inp :-> out, ErrorTagMap) -- | If you apply numeric error representation in your contract, -- errorFromVal will stop working because it doesn't know about -- this transformation. This function takes this transformation into -- account. If a number is used as a tag, but it is not found in the -- passed map, we conservatively preserve that number (because this whole -- approach is rather a heuristic). errorFromValNumeric :: (Typeable t, SingI t, IsError e) => ErrorTagMap -> Value t -> Either Text e -- | Some common errors. -- -- Such registry makes sense, as soon as errors are declared globally. module Lorentz.Errors.Common instance Formatting.Buildable.Buildable (Lorentz.Errors.CustomError "senderIsNotAdmin") instance Lorentz.Errors.CustomErrorHasDoc "senderIsNotAdmin" module Lorentz -- | Application operator. This operator is redundant, since ordinary -- application (f x) means the same as (f $ x). -- However, $ has low, right-associative binding precedence, so it -- sometimes allows parentheses to be omitted; for example: -- --
--   f $ g $ h x  =  f (g (h x))
--   
-- -- It is also useful in higher-order situations, such as map -- ($ 0) xs, or zipWith ($) fs xs. -- -- Note that ($) is levity-polymorphic in its result type, so -- that foo $ True where foo :: Bool -> Int# is well-typed ($) :: () => (a -> b) -> a -> b infixr 0 $ -- | The Bounded class is used to name the upper and lower limits of -- a type. Ord is not a superclass of Bounded since types -- that are not totally ordered may also have upper and lower bounds. -- -- The Bounded class may be derived for any enumeration type; -- minBound is the first constructor listed in the data -- declaration and maxBound is the last. Bounded may also -- be derived for single-constructor datatypes whose constituent types -- are in Bounded. class Bounded a minBound :: Bounded a => a maxBound :: Bounded a => a -- | The Eq class defines equality (==) and inequality -- (/=). All the basic datatypes exported by the Prelude -- are instances of Eq, and Eq may be derived for any -- datatype whose constituents are also instances of Eq. -- -- The Haskell Report defines no laws for Eq. However, == -- is customarily expected to implement an equivalence relationship where -- two values comparing equal are indistinguishable by "public" -- functions, with a "public" function being one not allowing to see -- implementation details. For example, for a type representing -- non-normalised natural numbers modulo 100, a "public" function doesn't -- make the difference between 1 and 201. It is expected to have the -- following properties: -- -- -- -- Minimal complete definition: either == or /=. class Eq a -- | Inject a value into the monadic type. return :: Monad m => a -> m a -- | Conversion from an Integer. An integer literal represents the -- application of the function fromInteger to the appropriate -- value of type Integer, so such literals have type -- (Num a) => a. fromInteger :: Num a => Integer -> a -- | The Ord class is used for totally ordered datatypes. -- -- Instances of Ord can be derived for any user-defined datatype -- whose constituent types are in Ord. The declared order of the -- constructors in the data declaration determines the ordering in -- derived Ord instances. The Ordering datatype allows a -- single comparison to determine the precise ordering of two objects. -- -- The Haskell Report defines no laws for Ord. However, -- <= is customarily expected to implement a non-strict partial -- order and have the following properties: -- -- -- -- Note that the following operator interactions are expected to hold: -- --
    --
  1. x >= y = y <= x
  2. --
  3. x < y = x <= y && x /= y
  4. --
  5. x > y = y < x
  6. --
  7. x < y = compare x y == LT
  8. --
  9. x > y = compare x y == GT
  10. --
  11. x == y = compare x y == EQ
  12. --
  13. min x y == if x <= y then x else y = True
  14. --
  15. max x y == if x >= y then x else y = True
  16. --
-- -- Minimal complete definition: either compare or <=. -- Using compare can be more efficient for complex types. class Eq a => Ord a fromString :: IsString a => String -> a -- | Lift a value. pure :: Applicative f => a -> f a -- | Representable types of kind *. This class is derivable in GHC -- with the DeriveGeneric flag on. -- -- A Generic instance must satisfy the following laws: -- --
--   from . toid
--   to . fromid
--   
class Generic a fromLabel :: IsLabel x a => a -- | The class of semigroups (types with an associative binary operation). -- -- Instances should satisfy the associativity law: -- -- class Semigroup a -- | An associative operation. (<>) :: Semigroup a => a -> a -> a -- | Reduce a non-empty list with <> -- -- The default definition should be sufficient, but this can be -- overridden for efficiency. sconcat :: Semigroup a => NonEmpty a -> a -- | Repeat a value n times. -- -- Given that this works on a Semigroup it is allowed to fail if -- you request 0 or fewer repetitions, and the default definition will do -- so. -- -- By making this a member of the class, idempotent semigroups and -- monoids can upgrade this to execute in O(1) by picking -- stimes = stimesIdempotent or stimes = -- stimesIdempotentMonoid respectively. stimes :: (Semigroup a, Integral b) => b -> a -> a infixr 6 <> -- | The class of monoids (types with an associative binary operation that -- has an identity). Instances should satisfy the following laws: -- -- -- -- The method names refer to the monoid of lists under concatenation, but -- there are many other instances. -- -- Some types can be viewed as a monoid in more than one way, e.g. both -- addition and multiplication on numbers. In such cases we often define -- newtypes and make those instances of Monoid, e.g. -- Sum and Product. -- -- NOTE: Semigroup is a superclass of Monoid since -- base-4.11.0.0. class Semigroup a => Monoid a -- | Identity of mappend mempty :: Monoid a => a -- | An associative operation -- -- NOTE: This method is redundant and has the default -- implementation mappend = '(<>)' since -- base-4.11.0.0. mappend :: Monoid a => a -> a -> a -- | Fold a list using the monoid. -- -- For most types, the default definition for mconcat will be -- used, but the function is included in the class definition so that an -- optimized version can be provided for specific types. mconcat :: Monoid a => [a] -> a data Bool False :: Bool True :: Bool -- | Invariant: Jn# and Jp# are used iff value doesn't fit in -- S# -- -- Useful properties resulting from the invariants: -- -- data Integer -- | Type representing arbitrary-precision non-negative integers. -- --
--   >>> 2^100 :: Natural
--   1267650600228229401496703205376
--   
-- -- Operations whose result would be negative throw -- (Underflow :: ArithException), -- --
--   >>> -1 :: Natural
--   *** Exception: arithmetic underflow
--   
data Natural -- | The Maybe type encapsulates an optional value. A value of type -- Maybe a either contains a value of type a -- (represented as Just a), or it is empty (represented -- as Nothing). Using Maybe is a good way to deal with -- errors or exceptional cases without resorting to drastic measures such -- as error. -- -- The Maybe type is also a monad. It is a simple kind of error -- monad, where all errors are represented by Nothing. A richer -- error monad can be built using the Either type. data Maybe a Nothing :: Maybe a Just :: a -> Maybe a -- | The Either type represents values with two possibilities: a -- value of type Either a b is either Left -- a or Right b. -- -- The Either type is sometimes used to represent a value which is -- either correct or an error; by convention, the Left constructor -- is used to hold an error value and the Right constructor is -- used to hold a correct value (mnemonic: "right" also means "correct"). -- --

Examples

-- -- The type Either String Int is the type -- of values which can be either a String or an Int. The -- Left constructor can be used only on Strings, and the -- Right constructor can be used only on Ints: -- --
--   >>> let s = Left "foo" :: Either String Int
--   
--   >>> s
--   Left "foo"
--   
--   >>> let n = Right 3 :: Either String Int
--   
--   >>> n
--   Right 3
--   
--   >>> :type s
--   s :: Either String Int
--   
--   >>> :type n
--   n :: Either String Int
--   
-- -- The fmap from our Functor instance will ignore -- Left values, but will apply the supplied function to values -- contained in a Right: -- --
--   >>> let s = Left "foo" :: Either String Int
--   
--   >>> let n = Right 3 :: Either String Int
--   
--   >>> fmap (*2) s
--   Left "foo"
--   
--   >>> fmap (*2) n
--   Right 6
--   
-- -- The Monad instance for Either allows us to chain -- together multiple actions which may fail, and fail overall if any of -- the individual steps failed. First we'll write a function that can -- either parse an Int from a Char, or fail. -- --
--   >>> import Data.Char ( digitToInt, isDigit )
--   
--   >>> :{
--       let parseEither :: Char -> Either String Int
--           parseEither c
--             | isDigit c = Right (digitToInt c)
--             | otherwise = Left "parse error"
--   
--   >>> :}
--   
-- -- The following should work, since both '1' and '2' -- can be parsed as Ints. -- --
--   >>> :{
--       let parseMultiple :: Either String Int
--           parseMultiple = do
--             x <- parseEither '1'
--             y <- parseEither '2'
--             return (x + y)
--   
--   >>> :}
--   
-- --
--   >>> parseMultiple
--   Right 3
--   
-- -- But the following should fail overall, since the first operation where -- we attempt to parse 'm' as an Int will fail: -- --
--   >>> :{
--       let parseMultiple :: Either String Int
--           parseMultiple = do
--             x <- parseEither 'm'
--             y <- parseEither '2'
--             return (x + y)
--   
--   >>> :}
--   
-- --
--   >>> parseMultiple
--   Left "parse error"
--   
data Either a b Left :: a -> Either a b Right :: b -> Either a b -- | A space-efficient representation of a Word8 vector, supporting -- many efficient operations. -- -- A ByteString contains 8-bit bytes, or by using the operations -- from Data.ByteString.Char8 it can be interpreted as containing -- 8-bit characters. data ByteString -- | A space efficient, packed, unboxed Unicode text type. data Text -- | Function composition. (.) :: () => (b -> c) -> (a -> b) -> a -> c infixr 9 . -- | A Map from keys k to values a. data Map k a -- | Proxy is a type that holds no data, but has a phantom parameter -- of arbitrary type (or even kind). Its use is to provide type -- information, even though there is no value available of that type (or -- it may be too costly to create one). -- -- Historically, Proxy :: Proxy a is a safer -- alternative to the 'undefined :: a' idiom. -- --
--   >>> Proxy :: Proxy (Void, Int -> Int)
--   Proxy
--   
-- -- Proxy can even hold types of higher kinds, -- --
--   >>> Proxy :: Proxy Either
--   Proxy
--   
-- --
--   >>> Proxy :: Proxy Functor
--   Proxy
--   
-- --
--   >>> Proxy :: Proxy complicatedStructure
--   Proxy
--   
data Proxy (t :: k) :: forall k. () => k -> Type Proxy :: Proxy -- | From a Dict, takes a value in an environment where the instance -- witnessed by the Dict is in scope, and evaluates it. -- -- Essentially a deconstruction of a Dict into its -- continuation-style form. -- -- Can also be used to deconstruct an entailment, a :- b, -- using a context a. -- --
--   withDict :: Dict c -> (c => r) -> r
--   withDict :: a => (a :- c) -> (c => r) -> r
--   
withDict :: HasDict c e => e -> (c -> r) -> r -- | A set of values a. data Set a -- | A class for types with a default value. class Default a -- | The default value for this type. def :: Default a => a -- | Wrapped provides isomorphisms to wrap and unwrap newtypes or -- data types with one constructor. class Wrapped s where { type family Unwrapped s :: Type; } -- | An isomorphism between s and a. -- -- If your type has a Generic instance, _Wrapped' will -- default to _GWrapped', and you can choose to not override it -- with your own definition. _Wrapped' :: Wrapped s => Iso' s (Unwrapped s) -- | error that takes Text as an argument. error :: HasCallStack => Text -> a -- | undefined that leaves a warning in code on every usage. undefined :: HasCallStack => a -- | Infix application. -- --
--   f :: Either String $ Maybe Int
--   =
--   f :: Either String (Maybe Int)
--   
type ($) (f :: k -> k1) (a :: k) = f a infixr 2 $ -- | A variation of arg for optional arguments. Requires a default -- value to handle the case when the optional argument was omitted: -- --
--   fn (argDef #answer 42 -> ans) = ...
--   
-- -- In case you want to get a value wrapped in Maybe instead, use -- argF or ArgF. argDef :: () => Name name -> a -> (name :? a) -> a -- | argF is similar to arg: it unwraps a named parameter -- with the specified name. The difference is that the result of -- argF is inside an arity wrapper, which is Identity for -- normal parameters and Maybe for optional parameters. argF :: () => Name name -> NamedF f a name -> f a -- | arg unwraps a named parameter with the specified name. One way -- to use it is to match on arguments with -XViewPatterns: -- --
--   fn (arg #t -> t) (arg #f -> f) = ...
--   
-- -- This way, the names of parameters can be inferred from the patterns: -- no type signature for fn is required. In case a type -- signature for fn is provided, the parameters must come in the -- same order: -- --
--   fn :: "t" :! Integer -> "f" :! Integer -> ...
--   fn (arg #t -> t) (arg #f -> f) = ... -- ok
--   fn (arg #f -> f) (arg #t -> t) = ... -- does not typecheck
--   
arg :: () => Name name -> (name :! a) -> a -- | Infix notation for the type of a named parameter. type (:!) (name :: Symbol) a = NamedF Identity a name -- | Infix notation for the type of an optional named parameter. type (:?) (name :: Symbol) a = NamedF Maybe a name -- | A record is parameterized by a universe u, an interpretation -- f and a list of rows rs. The labels or indices of -- the record are given by inhabitants of the kind u; the type -- of values at any label r :: u is given by its interpretation -- f r :: *. data Rec (a :: u -> Type) (b :: [u]) :: forall u. () => u -> Type -> [u] -> Type [RNil] :: forall u (a :: u -> Type) (b :: [u]). () => Rec a ([] :: [u]) [:&] :: forall u (a :: u -> Type) (b :: [u]) (r :: u) (rs :: [u]). () => !a r -> !Rec a rs -> Rec a (r : rs) infixr 7 :& -- | A piece of markdown document. -- -- This is opposed to Text type, which in turn is not supposed to -- contain markup elements. type Markdown = Builder -- | Michelson string value. -- -- This is basically a mere text with limits imposed by the language: -- http://tezos.gitlab.io/zeronet/whitedoc/michelson.html#constants -- Although, this document seems to be not fully correct, and thus we -- applied constraints deduced empirically. -- -- You construct an item of this type using one of the following ways: -- -- -- --
--   >>> [mt|Some text|]
--   MTextUnsafe { unMText = "Some text" }
--   
-- -- data MText -- | QuasyQuoter for constructing Michelson strings. -- -- Validity of result will be checked at compile time. Note: -- -- mt :: QuasiQuoter -- | Blake2b_160 hash of a public key. data KeyHash -- | Cryptographic signatures used by Tezos. Constructors correspond to -- PublicKey constructors. -- -- Tezos distinguishes signatures for different curves. For instance, -- ed25519 signatures and secp256k1 signatures are printed differently -- (have different prefix). However, signatures are packed without -- information about the curve. For this purpose there is a generic -- signature which only stores bytes and doesn't carry information about -- the curve. Apparently unpacking from bytes always produces such -- signature. Unpacking from string produces a signature with curve -- information. data Signature -- | Public cryptographic key used by Tezos. There are three cryptographic -- curves each represented by its own constructor. data PublicKey -- | Identifier of a network (babylonnet, mainnet, test network or other). -- Evaluated as hash of the genesis block. -- -- The only operation supported for this type is packing. Use case: -- multisig contract, for instance, now includes chain ID into signed -- data "in order to add extra replay protection between the main chain -- and the test chain". data ChainId -- | Time in the real world. Use the functions below to convert it to/from -- Unix time in seconds. data Timestamp -- | Mutez is a wrapper over integer data type. 1 mutez is 1 token (μTz). data Mutez -- | Safely create Mutez. -- -- This is recommended way to create Mutez from a numeric -- literal; you can't construct all valid Mutez values using -- this function but for small values it works neat. -- -- Warnings displayed when trying to construct invalid Natural or -- Word literal are hardcoded for these types in GHC -- implementation, so we can only exploit these existing rules. toMutez :: Word32 -> Mutez timestampFromSeconds :: Integer -> Timestamp timestampFromUTCTime :: UTCTime -> Timestamp -- | Quote a value of type Timestamp in -- yyyy-mm-ddThh:mm:ss[.sss]Z format. -- --
--   >>> formatTimestamp [timestampQuote| 2019-02-21T16:54:12.2344523Z |]
--   "2019-02-21T16:54:12Z"
--   
-- -- Inspired by 'time-quote' library. timestampQuote :: QuasiQuoter -- | Data type corresponding to address structure in Tezos. data Address -- | Address with optional entrypoint name attached to it. TODO: come up -- with better name? data EpAddress EpAddress :: Address -> EpName -> EpAddress -- | Address itself [eaAddress] :: EpAddress -> Address -- | Entrypoint name (might be empty) [eaEntryPoint] :: EpAddress -> EpName -- | Representation of comparable value in Michelson language. -- -- By specification, we're allowed to compare only following types: int, -- nat, string, bytes, mutez, bool, key_hash, timestamp, address. -- -- Only these values can be used as map keys or set elements. data CValue t [CvInt] :: Integer -> CValue 'CInt [CvNat] :: Natural -> CValue 'CNat [CvString] :: MText -> CValue 'CString [CvBytes] :: ByteString -> CValue 'CBytes [CvMutez] :: Mutez -> CValue 'CMutez [CvBool] :: Bool -> CValue 'CBool [CvKeyHash] :: KeyHash -> CValue 'CKeyHash [CvTimestamp] :: Timestamp -> CValue 'CTimestamp [CvAddress] :: EpAddress -> CValue 'CAddress -- | Keeps documentation gathered for some piece of contract code. -- -- Used for building documentation of a contract. data ContractDoc ContractDoc :: DocBlock -> DocBlock -> Set SomeDocDefinitionItem -> Set DocItemId -> ContractDoc -- | All inlined doc items. [cdContents] :: ContractDoc -> DocBlock -- | Definitions used in document. -- -- Usually you put some large and repetitive descriptions here. This -- differs from the document content in that it contains sections which -- are always at top-level, disregard the nesting. -- -- All doc items which define docItemId method go here, and only -- they. [cdDefinitions] :: ContractDoc -> DocBlock -- | We remember all already declared entries to avoid cyclic dependencies -- in documentation items discovery. [cdDefinitionsSet] :: ContractDoc -> Set SomeDocDefinitionItem -- | We remember all already used identifiers. (Documentation naturally -- should not declare multiple items with the same identifier because -- that would make references to the respective anchors ambiguous). [cdDefinitionIds] :: ContractDoc -> Set DocItemId -- | A part of documentation to be grouped. Essentially incapsulates -- DocBlock. newtype SubDoc SubDoc :: DocBlock -> SubDoc -- | Hides some documentation item which is put to "definitions" section. data SomeDocDefinitionItem [SomeDocDefinitionItem] :: (DocItem d, DocItemPlacement d ~ 'DocItemInDefinitions) => d -> SomeDocDefinitionItem -- | Hides some documentation item. data SomeDocItem [SomeDocItem] :: DocItem d => d -> SomeDocItem -- | How to render section name. data DocSectionNameStyle -- | Suitable for block name. DocSectionNameBig :: DocSectionNameStyle -- | Suitable for subsection title within block. DocSectionNameSmall :: DocSectionNameStyle -- | Defines an identifier which given doc item can be referenced with. data DocItemRef (p :: DocItemPlacementKind) [DocItemRef] :: DocItemId -> DocItemRef 'DocItemInDefinitions [DocItemNoRef] :: DocItemRef 'DocItemInlined -- | Where do we place given doc item. data DocItemPlacementKind -- | Placed in the document content itself. DocItemInlined :: DocItemPlacementKind -- | Placed in dedicated definitions section; can later be referenced. DocItemInDefinitions :: DocItemPlacementKind -- | Some unique identifier of a doc item. -- -- All doc items which should be refer-able need to have this identifier. newtype DocItemId DocItemId :: Text -> DocItemId -- | A piece of documentation describing one property of a thing, be it a -- name or description of a contract, or an error throwable by given -- endpoint. -- -- Items of the same type appear close to each other in a rendered -- documentation and form a section. -- -- Doc items are later injected into a contract code via a dedicated -- nop-like instruction. Normally doc items which belong to one section -- appear in resulting doc in the same order in which they appeared in -- the contract. -- -- While documentation framework grows, this typeclass acquires more and -- more methods for fine tuning of existing rendering logic because we -- don't want to break backward compatibility, hope one day we will make -- everything concise :( E.g. all rendering and reording stuff could be -- merged in one method, and we could have several template -- implementations for it which would allow user to specify only stuff -- relevant to his case. class (Typeable d, DOrd d, KnownNat (DocItemPosition d)) => DocItem d where { -- | Position of this item in the resulting documentation; the smaller the -- value, the higher the section with this element will be placed. -- -- Documentation structure is not necessarily flat. If some doc item -- consolidates a whole documentation block within it, this block will -- have its own placement of items independent from outer parts of the -- doc. type family DocItemPosition d = (pos :: Nat) | pos -> d; -- | Defines where given doc item should be put. There are two options: 1. -- Inline right here (default behaviour); 2. Put into definitions -- section. -- -- Note that we require all doc items with "in definitions" placement to -- have Eq and Ord instances which comply the following -- law: if two documentation items describe the same entity or property, -- they should be considered equal. type family DocItemPlacement d :: DocItemPlacementKind; type DocItemPlacement d = 'DocItemInlined; } -- | When multiple items of the same type belong to one section, how this -- section will be called. -- -- If not provided, section will contain just untitled content. docItemSectionName :: DocItem d => Maybe Text -- | Description of a section. -- -- Can be used to mention some common things about all elements of this -- section. Markdown syntax is permitted here. docItemSectionDescription :: DocItem d => Maybe Markdown -- | How to render section name. -- -- Takes effect only if section name is set. docItemSectionNameStyle :: DocItem d => DocSectionNameStyle -- | Defines a function which constructs an unique identifier of given doc -- item, if it has been decided to put the doc item into definitions -- section. -- -- Identifier should be unique both among doc items of the same type and -- items of other types. Thus, consider using "typeId-contentId" pattern. docItemRef :: DocItem d => d -> DocItemRef (DocItemPlacement d) -- | Defines a function which constructs an unique identifier of given doc -- item, if it has been decided to put the doc item into definitions -- section. -- -- Identifier should be unique both among doc items of the same type and -- items of other types. Thus, consider using "typeId-contentId" pattern. docItemRef :: (DocItem d, DocItemPlacement d ~ 'DocItemInlined) => d -> DocItemRef (DocItemPlacement d) -- | Render given doc item to Markdown, preferably one line, optionally -- with header. -- -- Accepts the smallest allowed level of header. (Using smaller value -- than provided one will interfere with existing headers thus delivering -- mess). docItemToMarkdown :: DocItem d => HeaderLevel -> d -> Markdown -- | All doc items which this doc item refers to. -- -- They will automatically be put to definitions as soon as given doc -- item is detected. docItemDependencies :: DocItem d => d -> [SomeDocDefinitionItem] -- | This function accepts doc items put under the same section in the -- order in which they appeared in the contract and returns their new -- desired order. It's also fine to use this function for filtering or -- merging doc items. -- -- Default implementation * leaves inlined items as is; * for items put -- to definitions, lexicographically sorts them by their id. docItemsOrder :: DocItem d => [d] -> [d] -- | Get doc item position at term-level. docItemPosition :: forall d. DocItem d => DocItemPos -- | Make a reference to doc item in definitions. docDefinitionRef :: (DocItem d, DocItemPlacement d ~ 'DocItemInDefinitions) => Markdown -> d -> Markdown -- | Render documentation for SubDoc. subDocToMarkdown :: HeaderLevel -> SubDoc -> Markdown data DComment DComment :: Text -> DComment -- | Repository settings for DGitRevision. newtype GitRepoSettings GitRepoSettings :: (Text -> Text) -> GitRepoSettings -- | By commit sha make up a url to that commit in remote repository. [grsMkGitRevision] :: GitRepoSettings -> Text -> Text -- | Specify version if given contract. data DGitRevision DGitRevision :: GitRepoSettings -> Text -> Text -> DGitRevision [dgrRepoSettings] :: DGitRevision -> GitRepoSettings [dgrCommitSha] :: DGitRevision -> Text [dgrCommitDate] :: DGitRevision -> Text -- | Specify version if given contract. data DVersion DVersion :: Natural -> DVersion -- | Description of something. data DDescription DDescription :: Markdown -> DDescription -- | A function which groups a piece of doc under one doc item. type DocGrouping = SubDoc -> SomeDocItem -- | Render given contract documentation to markdown document. contractDocToMarkdown :: ContractDoc -> LText morleyRepoSettings :: GitRepoSettings -- | Make DGitRevision. -- --
--   >>> :t $mkDGitRevision
--   GitRepoSettings -> DGitRevision
--   
mkDGitRevision :: Q Exp type Operation = Operation' Instr type Value = Value' Instr newtype BigMap k v BigMap :: Map k v -> BigMap k v [unBigMap] :: BigMap k v -> Map k v -- | Since Contract name is used to designate contract code, lets -- call analogy of TContract type as follows. data ContractRef (arg :: Type) ContractRef :: Address -> SomeEntryPointCall arg -> ContractRef [crAddress] :: ContractRef -> Address [crEntryPoint] :: ContractRef -> SomeEntryPointCall arg type SomeEntryPointCall arg = SomeEntryPointCallT (ToT arg) type EntryPointCall param arg = EntryPointCallT (ToT param) (ToT arg) -- | Isomorphism between Michelson values and plain Haskell types. -- -- Default implementation of this typeclass converts ADTs to Michelson -- "pair"s and "or"s. class IsoValue a where { -- | Type function that converts a regular Haskell type into a T -- type. type family ToT a :: T; type ToT a = GValueType (Rep a); } -- | Converts a Haskell structure into Value representation. toVal :: IsoValue a => a -> Value (ToT a) -- | Converts a Haskell structure into Value representation. toVal :: (IsoValue a, Generic a, GIsoValue (Rep a), ToT a ~ GValueType (Rep a)) => a -> Value (ToT a) -- | Converts a Value into Haskell type. fromVal :: IsoValue a => Value (ToT a) -> a -- | Converts a Value into Haskell type. fromVal :: (IsoValue a, Generic a, GIsoValue (Rep a), ToT a ~ GValueType (Rep a)) => Value (ToT a) -> a -- | Isomorphism between Michelson primitive values and plain Haskell -- types. class IsoCValue a where { -- | Type function that converts a regular Haskell type into a comparable -- type (which has kind CT). type family ToCT a :: CT; } -- | Converts a single Haskell value into CVal representation. toCVal :: IsoCValue a => a -> CValue (ToCT a) -- | Converts a CVal value into a single Haskell value. fromCVal :: IsoCValue a => CValue (ToCT a) -> a -- | Replace type argument of ContractAddr with isomorphic one. coerceContractRef :: ToT a ~ ToT b => ContractRef a -> ContractRef b -- | Constraint for instrConstruct. type InstrConstructC dt = (IsoValue dt, Generic dt, GInstrConstruct (Rep dt), GValueType (Rep dt) ~ ToT dt) -- | Types of all fields in a datatype. type ConstructorFieldTypes dt = GFieldTypes (Rep dt) -- | Require this type to be homomorphic. class IsHomomorphic a -- | Require two types to be built from the same type constructor. -- -- E.g. HaveCommonTypeCtor (Maybe Integer) (Maybe Natural) is -- defined, while HaveCmmonTypeCtor (Maybe Integer) [Integer] is -- not. class HaveCommonTypeCtor a b -- | Doc element with description of a type. data DType [DType] :: TypeHasDoc a => Proxy a -> DType -- | Data hides some type implementing TypeHasDoc. data SomeTypeWithDoc [SomeTypeWithDoc] :: TypeHasDoc td => Proxy td -> SomeTypeWithDoc -- | Description for a Haskell type appearing in documentation. class Typeable a => TypeHasDoc a -- | Name of type as it appears in definitions section. -- -- Each type must have its own unique name because it will be used in -- identifier for references. -- -- Default definition derives name from Generics. If it does not fit, -- consider defining this function manually. (We tried using Data -- for this, but it produces names including module names which is not do -- we want). typeDocName :: TypeHasDoc a => Proxy a -> Text -- | Name of type as it appears in definitions section. -- -- Each type must have its own unique name because it will be used in -- identifier for references. -- -- Default definition derives name from Generics. If it does not fit, -- consider defining this function manually. (We tried using Data -- for this, but it produces names including module names which is not do -- we want). typeDocName :: (TypeHasDoc a, Generic a, KnownSymbol (GenericTypeName a)) => Proxy a -> Text -- | Explanation of a type. Markdown formatting is allowed. typeDocMdDescription :: TypeHasDoc a => Markdown -- | How reference to this type is rendered, in Markdown. -- -- Examples: * Integer, * Maybe -- (). -- -- Consider using one of the following functions as default -- implementation; which one to use depends on number of type arguments -- in your type: * homomorphicTypeDocMdReference * -- poly1TypeDocMdReference * poly2TypeDocMdReference -- -- If none of them fits your purposes precisely, consider using -- customTypeDocMdReference. typeDocMdReference :: TypeHasDoc a => Proxy a -> WithinParens -> Markdown -- | How reference to this type is rendered, in Markdown. -- -- Examples: * Integer, * Maybe -- (). -- -- Consider using one of the following functions as default -- implementation; which one to use depends on number of type arguments -- in your type: * homomorphicTypeDocMdReference * -- poly1TypeDocMdReference * poly2TypeDocMdReference -- -- If none of them fits your purposes precisely, consider using -- customTypeDocMdReference. typeDocMdReference :: (TypeHasDoc a, Typeable a, IsHomomorphic a) => Proxy a -> WithinParens -> Markdown -- | All types which this type directly contains. -- -- Used in automatic types discovery. typeDocDependencies :: TypeHasDoc a => Proxy a -> [SomeTypeWithDoc] -- | All types which this type directly contains. -- -- Used in automatic types discovery. typeDocDependencies :: (TypeHasDoc a, Generic a, GTypeHasDoc (Rep a)) => Proxy a -> [SomeTypeWithDoc] -- | For complex types - their immediate Haskell representation. -- -- For primitive types set this to Nothing. -- -- For homomorphic types use homomorphicTypeDocHaskellRep -- implementation. -- -- For polymorhpic types consider using concreteTypeDocHaskellRep -- as implementation. -- -- Modifier haskellRepNoFields can be used to hide names of -- fields, beneficial for newtypes. -- -- Another modifier called haskellRepStripFieldPrefix can be used -- for datatypes to leave only meaningful part of name in every field. typeDocHaskellRep :: TypeHasDoc a => TypeDocHaskellRep a -- | For complex types - their immediate Haskell representation. -- -- For primitive types set this to Nothing. -- -- For homomorphic types use homomorphicTypeDocHaskellRep -- implementation. -- -- For polymorhpic types consider using concreteTypeDocHaskellRep -- as implementation. -- -- Modifier haskellRepNoFields can be used to hide names of -- fields, beneficial for newtypes. -- -- Another modifier called haskellRepStripFieldPrefix can be used -- for datatypes to leave only meaningful part of name in every field. typeDocHaskellRep :: (TypeHasDoc a, Generic a, GTypeHasDoc (Rep a), IsHomomorphic a) => TypeDocHaskellRep a -- | Final michelson representation of a type. -- -- For homomorphic types use homomorphicTypeDocMichelsonRep -- implementation. -- -- For polymorhpic types consider using -- concreteTypeDocMichelsonRep as implementation. typeDocMichelsonRep :: TypeHasDoc a => TypeDocMichelsonRep a -- | Final michelson representation of a type. -- -- For homomorphic types use homomorphicTypeDocMichelsonRep -- implementation. -- -- For polymorhpic types consider using -- concreteTypeDocMichelsonRep as implementation. typeDocMichelsonRep :: (TypeHasDoc a, SingI (ToT a), IsHomomorphic a) => TypeDocMichelsonRep a -- | Render a reference to a type which consists of type constructor (you -- have to provide name of this type constructor and documentation for -- the whole type) and zero or more type arguments. customTypeDocMdReference :: (Text, DType) -> [DType] -> WithinParens -> Markdown -- | Derive typeDocMdReference, for homomorphic types only. homomorphicTypeDocMdReference :: forall (t :: Type). (Typeable t, TypeHasDoc t, IsHomomorphic t) => Proxy t -> WithinParens -> Markdown -- | Derive typeDocMdReference, for polymorphic type with one type -- argument, like Maybe Integer. poly1TypeDocMdReference :: forall t (r :: Type) (a :: Type). (r ~ t a, Typeable t, Each '[TypeHasDoc] [r, a], IsHomomorphic t) => Proxy r -> WithinParens -> Markdown -- | Derive typeDocMdReference, for polymorphic type with two type -- arguments, like Lambda Integer Natural. poly2TypeDocMdReference :: forall t (r :: Type) (a :: Type) (b :: Type). (r ~ t a b, Typeable t, Each '[TypeHasDoc] [r, a, b], IsHomomorphic t) => Proxy r -> WithinParens -> Markdown -- | Implement typeDocDependencies via getting all immediate fields -- of a datatype. -- -- Note: this will not include phantom types, I'm not sure yet how this -- scenario should be handled (@martoon). genericTypeDocDependencies :: forall a. (Generic a, GTypeHasDoc (Rep a)) => Proxy a -> [SomeTypeWithDoc] -- | Implement typeDocHaskellRep for a homomorphic type. -- -- Note that it does not require your type to be of IsHomomorphic -- instance, which can be useful for some polymorhpic types which, for -- documentation purposes, we want to consider homomorphic. Example: -- Operation is in fact polymorhpic, but we don't want this fact -- to be reflected in the documentation. homomorphicTypeDocHaskellRep :: forall a. (Generic a, GTypeHasDoc (Rep a)) => TypeDocHaskellRep a -- | Implement typeDocHaskellRep on example of given concrete type. -- -- This is a best effort attempt to implement typeDocHaskellRep -- for polymorhpic types, as soon as there is no simple way to preserve -- type variables when automatically deriving Haskell representation of a -- type. concreteTypeDocHaskellRep :: forall a b. (Typeable a, IsoValue a, Generic a, GTypeHasDoc (Rep a), HaveCommonTypeCtor b a) => TypeDocHaskellRep b -- | Version of concreteTypeDocHaskellRep which does not ensure -- whether the type for which representation is built is any similar to -- the original type which you implement a TypeHasDoc instance -- for. concreteTypeDocHaskellRepUnsafe :: forall a b. (Typeable a, IsoValue a, Generic a, GTypeHasDoc (Rep a)) => TypeDocHaskellRep b -- | Erase fields from Haskell datatype representation. -- -- Use this when rendering fields names is undesired. haskellRepNoFields :: TypeDocHaskellRep a -> TypeDocHaskellRep a -- | Cut fields prefixes which we use according to the style guide. -- -- E.g. cmMyField field will be transformed to myField. haskellRepStripFieldPrefix :: HasCallStack => TypeDocHaskellRep a -> TypeDocHaskellRep a -- | Implement typeDocMichelsonRep for homomorphic type. homomorphicTypeDocMichelsonRep :: forall a. SingI (ToT a) => TypeDocMichelsonRep a -- | Implement typeDocMichelsonRep on example of given concrete -- type. -- -- This function exists for the same reason as -- concreteTypeDocHaskellRep. concreteTypeDocMichelsonRep :: forall a b. (Typeable a, SingI (ToT a), HaveCommonTypeCtor b a) => TypeDocMichelsonRep b -- | Version of concreteTypeDocHaskellRepUnsafe which does not -- ensure whether the type for which representation is built is any -- similar to the original type which you implement a TypeHasDoc -- instance for. concreteTypeDocMichelsonRepUnsafe :: forall a b. (Typeable a, SingI (ToT a)) => TypeDocMichelsonRep b -- | Lifted EDivOp. class (EDivOp (ToCT n) (ToCT m), IsComparable n, IsComparable m, ToT (EDivOpResHs n m) ~ 'Tc (EDivOpRes (ToCT n) (ToCT m)), ToT (EModOpResHs n m) ~ 'Tc (EModOpRes (ToCT n) (ToCT m))) => EDivOpHs n m where { type family EDivOpResHs n m :: Type; type family EModOpResHs n m :: Type; } -- | Lifted SliceOp. class SliceOp (ToT c) => SliceOpHs c -- | Lifted ConcatOp. class ConcatOp (ToT c) => ConcatOpHs c -- | Lifted GetOp. class (GetOp (ToT c), ToT (GetOpKeyHs c) ~ 'Tc (GetOpKey (ToT c)), ToT (GetOpValHs c) ~ GetOpVal (ToT c)) => GetOpHs c where { type family GetOpKeyHs c :: Type; type family GetOpValHs c :: Type; } -- | Lifted UpdOp. class (UpdOp (ToT c), ToT (UpdOpKeyHs c) ~ 'Tc (UpdOpKey (ToT c)), ToT (UpdOpParamsHs c) ~ UpdOpParams (ToT c)) => UpdOpHs c where { type family UpdOpKeyHs c :: Type; type family UpdOpParamsHs c :: Type; } -- | Lifted SizeOp. -- -- This could be just a constraint alias, but to avoid T types -- appearance in error messages we make a full type class with concrete -- instances. class SizeOp (ToT c) => SizeOpHs c -- | Lifted IterOp. class (IterOp (ToT c), ToT (IterOpElHs c) ~ IterOpEl (ToT c)) => IterOpHs c where { type family IterOpElHs c :: Type; } -- | Lifted MapOp. class (MapOp (ToT c), ToT (MapOpInpHs c) ~ MapOpInp (ToT c), ToT (MapOpResHs c ()) ~ MapOpRes (ToT c) (ToT ())) => MapOpHs c where { type family MapOpInpHs c :: Type; type family MapOpResHs c :: Type -> Type; } -- | A useful property which holds for reasonable MapOp instances. -- -- It's a separate thing from MapOpHs because it mentions -- b type parameter. type family IsoMapOpRes c b -- | Lifted MemOpKey. class (MemOp (ToT c), ToT (MemOpKeyHs c) ~ 'Tc (MemOpKey (ToT c))) => MemOpHs c where { type family MemOpKeyHs c :: Type; } type NicePrintedValue a = (KnownValue a, ProperPrintedValBetterErrors (ToT a)) type NiceFullPackedValue a = (NicePackedValue a, NiceUnpackedValue a) type NiceUnpackedValue a = (KnownValue a, ProperUnpackedValBetterErrors (ToT a)) type NicePackedValue a = (KnownValue a, ProperPackedValBetterErrors (ToT a)) type NiceConstant a = (KnownValue a, ProperConstantBetterErrors (ToT a)) type NiceStorage a = (KnownValue a, ProperStorageBetterErrors (ToT a)) -- | Constraint applied to parameter type. type NiceParameter a = (KnownValue a, ProperParameterBetterErrors (ToT a)) class (IsoValue a, HasNoNestedBigMaps (ToT a)) => CanHaveBigMap a class (IsoValue a, ForbidBigMap (ToT a)) => NoBigMap a class (IsoValue a, ForbidContract (ToT a)) => NoContractType a -- | Ensure given type does not contain "operation". class (IsoValue a, ForbidOp (ToT a)) => NoOperation a class (IsoValue a, Typeable (ToCT a), SingI (ToCT a)) => KnownCValue a -- | Gathers constraints, commonly required for values. class (IsoValue a, Typeable (ToT a), SingI (ToT a)) => KnownValue a niceParameterEvi :: forall a. NiceParameter a :- ParameterScope (ToT a) niceStorageEvi :: forall a. NiceStorage a :- StorageScope (ToT a) niceConstantEvi :: forall a. NiceConstant a :- ConstantScope (ToT a) nicePackedValueEvi :: forall a. NicePackedValue a :- PackedValScope (ToT a) niceUnpackedValueEvi :: forall a. NiceUnpackedValue a :- UnpackedValScope (ToT a) nicePrintedValueEvi :: forall a. NicePrintedValue a :- PrintedValScope (ToT a) -- | Convert something from ContractAddr in Haskell world. class FromContractRef (cp :: Type) (contract :: Type) fromContractAddr :: FromContractRef cp contract => ContractRef cp -> contract -- | Convert something to ContractRef in Haskell world. class ToContractRef (cp :: Type) (contract :: Type) toContractRef :: (ToContractRef cp contract, HasCallStack) => contract -> ContractRef cp -- | Convert something to Address in Haskell world. -- -- Use this when you want to access state of the contract and are not -- interested in calling it. class ToAddress a toAddress :: ToAddress a => a -> Address -- | Address associated with the contract of given type. -- -- Places where ContractAddr can appear are now severely -- limited, this type gives you type-safety of ContractAddr but -- still can be used everywhere. -- -- This may be refer to specific entrypoint of the contract, in such case -- type parameter p stands for argument of that entrypoint like -- in ContractAddr. -- -- You still cannot be sure that the referred contract exists though. newtype FutureContract p FutureContract :: EpAddress -> FutureContract p [futureContractAddress] :: FutureContract p -> EpAddress type List = [] -- | Turn future contract into actual contract. embodyFutureContract :: forall arg. (NiceParameter arg, HasCallStack) => FutureContract arg -> ContractRef arg convertContractRef :: forall cp contract2 contract1. (ToContractRef cp contract1, FromContractRef cp contract2) => contract1 -> contract2 class (Typeable (ToCT n), IsComparable n, CompareOp (ToCT n)) => CompareOpHs n -- | Lifted UnaryAithOp. class (UnaryArithOp aop (ToCT n), IsComparable n, Typeable (ToCT n), ToT (UnaryArithResHs aop n) ~ 'Tc (UnaryArithRes aop (ToCT n))) => UnaryArithOpHs (aop :: Type) (n :: Type) where { type family UnaryArithResHs aop n :: Type; } -- | Lifted AithOp. class (ArithOp aop (ToCT n) (ToCT m), IsComparable n, IsComparable m, Typeable (ToCT n), Typeable (ToCT m), ToT (ArithResHs aop n m) ~ 'Tc (ArithRes aop (ToCT n) (ToCT m))) => ArithOpHs (aop :: Type) (n :: Type) (m :: Type) where { type family ArithResHs aop n m :: Type; } lPackValue :: forall a. NicePackedValue a => a -> ByteString lUnpackValue :: forall a. NiceUnpackedValue a => ByteString -> Either UnpackError a type Lambda i o = '[i] :-> '[o] type (&) (a :: Type) (b :: [Type]) = a : b infixr 2 & data SomeContract [SomeContract] :: (NiceParameter cp, NiceStorage st) => Contract cp st -> SomeContract type Contract cp st = '[(cp, st)] :-> ContractOut st type ContractOut st = '[([Operation], st)] -- | Alias for :->, seems to make signatures more readable -- sometimes. -- -- Let's someday decide which one of these two should remain. type (%>) = (:->) infixr 1 %> -- | Alias for instruction which hides inner types representation via -- T. newtype (inp :: [Type]) :-> (out :: [Type]) LorentzInstr :: RemFail Instr (ToTs inp) (ToTs out) -> (:->) [unLorentzInstr] :: (:->) -> RemFail Instr (ToTs inp) (ToTs out) infixr 1 :-> pattern FI :: (forall out'. Instr (ToTs inp) out') -> inp :-> out pattern I :: Instr (ToTs inp) (ToTs out) -> inp :-> out iGenericIf :: (forall s'. Instr (ToTs a) s' -> Instr (ToTs b) s' -> Instr (ToTs c) s') -> (a :-> s) -> (b :-> s) -> c :-> s iAnyCode :: (inp :-> out) -> Instr (ToTs inp) (ToTs out) iNonFailingCode :: HasCallStack => (inp :-> out) -> Instr (ToTs inp) (ToTs out) iMapAnyCode :: (forall o'. Instr (ToTs i1) o' -> Instr (ToTs i2) o') -> (i1 :-> o) -> i2 :-> o (#) :: (a :-> b) -> (b :-> c) -> a :-> c infixl 8 # -- | Parse textual representation of a Michelson value and turn it into -- corresponding Haskell value. -- -- Note: it won't work in some complex cases, e. g. if there is a lambda -- which uses an instruction which depends on current contract's type. -- Obviously it can not work, because we don't have any information about -- a contract to which this value belongs (there is no such contract at -- all). parseLorentzValue :: forall v. (IsoValue v, SingI (ToT v), Typeable (ToT v)) => Text -> Either ParseLorentzError v -- | Lorentz version of transformStrings. transformStringsLorentz :: Bool -> (MText -> MText) -> (inp :-> out) -> inp :-> out -- | Lorentz version of transformBytes. transformBytesLorentz :: Bool -> (ByteString -> ByteString) -> (inp :-> out) -> inp :-> out optimizeLorentzWithConf :: OptimizerConf -> (inp :-> out) -> inp :-> out optimizeLorentz :: (inp :-> out) -> inp :-> out stackRef :: forall (gn :: Nat) st n. (n ~ ToPeano gn, SingI n, KnownPeano n, RequireLongerThan st n) => PrintComment st printComment :: PrintComment (ToTs s) -> s :-> s testAssert :: (Typeable (ToTs out), HasCallStack) => Text -> PrintComment (ToTs inp) -> (inp :-> (Bool & out)) -> inp :-> inp stackType :: forall s. s :-> s -- | Implementation of parameterEntryPoints. newtype ParameterEntryPointsSplit p ParameterEntryPointsSplit :: Notes (ToT p) -> ParameterEntryPointsSplit p -- | Parameter annotations which declare necessary entrypoints. [pesNotes] :: ParameterEntryPointsSplit p -> Notes (ToT p) -- | Which entrypoints given parameter declares. class NiceParameter p => ParameterEntryPoints p parameterEntryPoints :: ParameterEntryPoints p => ParameterEntryPointsSplit p mapParameterEntryPoints :: ToT a ~ ToT b => (a -> b) -> ParameterEntryPointsSplit a -> ParameterEntryPointsSplit b -- | No entrypoints declared, parameter type will serve as argument type of -- the only existing entrypoint. pepNone :: SingI (ToT p) => ParameterEntryPointsSplit p -- | Fits for case when your contract exposes multiple entrypoints via -- having sum type as its parameter. -- -- In particular, this will attach field annotations to immediate -- parameter "arms" which will be named as corresponding constructor -- names. pepPlain :: PesEntryPointsC 'False cp st => ParameterEntryPointsSplit cp -- | Similar to pesEntryPoints, but for case of parameter being -- defined as several nested datatypes. -- -- In particular, this will traverse sum types recursively, stopping at -- Michelson primitives (like Natural) and constructors with -- number of fields different from one. pepRecursive :: PesEntryPointsC 'True cp st => ParameterEntryPointsSplit cp -- | For use outside of Lorentz. compileLorentz :: (inp :-> out) -> Instr (ToTs inp) (ToTs out) -- | Version of compileLorentz specialized to instruction -- corresponding to contract code. compileLorentzContract :: forall cp st. (NiceParameter cp, NiceStorage st, ParameterEntryPoints cp) => Contract cp st -> FullContract (ToT cp) (ToT st) -- | Interpret a Lorentz instruction, for test purposes. interpretLorentzInstr :: (IsoValuesStack inp, IsoValuesStack out) => ContractEnv -> (inp :-> out) -> Rec Identity inp -> Either MichelsonFailed (Rec Identity out) -- | Like interpretLorentzInstr, but works on lambda rather than -- arbitrary instruction. interpretLorentzLambda :: (IsoValue inp, IsoValue out) => ContractEnv -> Lambda inp out -> inp -> Either MichelsonFailed out -- | Lorentz version of analyzer. analyzeLorentz :: (inp :-> out) -> AnalyzerRes -- | Pretty-print a Haskell value as Michelson one. printLorentzValue :: forall v. NicePrintedValue v => Bool -> v -> LText -- | Pretty-print a Lorentz contract into Michelson code. printLorentzContract :: forall cp st. (NiceParameter cp, NiceStorage st, ParameterEntryPoints cp) => Bool -> Contract cp st -> LText -- | Retain the value only if it is not zero. nonZero :: NonZero t => (t : s) :-> (Maybe t : s) class LorentzFunctor (c :: Type -> Type) lmap :: (LorentzFunctor c, KnownValue b) => ((a : s) :-> (b : s)) -> (c a : s) :-> (c b : s) type ConstraintDIPNLorentz (n :: Peano) (inp :: [Type]) (out :: [Type]) (s :: [Type]) (s' :: [Type]) = (ConstraintDIPN n (ToTs inp) (ToTs out) (ToTs s) (ToTs s'), ConstraintDIPN' Type n inp out s s') nop :: s :-> s drop :: (a & s) :-> s -- | Drop top n elements from the stack. dropN :: forall (n :: Nat) (s :: [Type]). (SingI (ToPeano n), KnownPeano (ToPeano n), RequireLongerOrSameLength (ToTs s) (ToPeano n), Drop (ToPeano n) (ToTs s) ~ ToTs (Drop (ToPeano n) s)) => s :-> Drop (ToPeano n) s dup :: (a & s) :-> (a & (a & s)) swap :: (a & (b & s)) :-> (b & (a & s)) -- | Version of dig which uses Peano number. It is inteded for -- internal usage in Lorentz. digPeano :: forall (n :: Peano) inp out a. ConstraintDIGLorentz n inp out a => inp :-> out dig :: forall (n :: Nat) inp out a. ConstraintDIGLorentz (ToPeano n) inp out a => inp :-> out dug :: forall (n :: Nat) inp out a. ConstraintDUGLorentz (ToPeano n) inp out a => inp :-> out push :: forall t s. NiceConstant t => t -> s :-> (t & s) some :: (a & s) :-> (Maybe a & s) none :: forall a s. KnownValue a => s :-> (Maybe a & s) unit :: s :-> (() & s) ifNone :: (s :-> s') -> ((a & s) :-> s') -> (Maybe a & s) :-> s' pair :: (a & (b & s)) :-> ((a, b) & s) car :: ((a, b) & s) :-> (a & s) cdr :: ((a, b) & s) :-> (b & s) left :: forall a b s. KnownValue b => (a & s) :-> (Either a b & s) right :: forall a b s. KnownValue a => (b & s) :-> (Either a b & s) ifLeft :: ((a & s) :-> s') -> ((b & s) :-> s') -> (Either a b & s) :-> s' nil :: KnownValue p => s :-> (List p & s) cons :: (a & (List a & s)) :-> (List a & s) ifCons :: ((a & (List a & s)) :-> s') -> (s :-> s') -> (List a & s) :-> s' size :: SizeOpHs c => (c & s) :-> (Natural & s) emptySet :: KnownCValue e => s :-> (Set e & s) emptyMap :: (KnownCValue k, KnownValue v) => s :-> (Map k v & s) emptyBigMap :: (KnownCValue k, KnownValue v) => s :-> (BigMap k v & s) map :: (MapOpHs c, IsoMapOpRes c b, HasCallStack) => ((MapOpInpHs c & s) :-> (b & s)) -> (c & s) :-> (MapOpResHs c b & s) iter :: (IterOpHs c, HasCallStack) => ((IterOpElHs c & s) :-> s) -> (c & s) :-> s mem :: MemOpHs c => (MemOpKeyHs c & (c & s)) :-> (Bool & s) get :: GetOpHs c => (GetOpKeyHs c & (c & s)) :-> (Maybe (GetOpValHs c) & s) update :: UpdOpHs c => (UpdOpKeyHs c & (UpdOpParamsHs c & (c & s))) :-> (c & s) if_ :: (s :-> s') -> (s :-> s') -> (Bool & s) :-> s' loop :: (s :-> (Bool & s)) -> (Bool & s) :-> s loopLeft :: ((a & s) :-> (Either a b & s)) -> (Either a b & s) :-> (b & s) lambda :: (ZipInstrs [i, o], KnownValue (ZippedStack i), KnownValue (ZippedStack o)) => (i :-> o) -> s :-> ((i :-> o) & s) exec :: (a & (Lambda a b & s)) :-> (b & s) -- | Similar to exec but works for lambdas with arbitrary size of -- input and output. -- -- Note that this instruction has its arguments flipped, lambda goes -- first. This seems to be the only reasonable way to achieve good -- inference. execute :: forall i o s. Each [KnownList, ZipInstr] [i, o] => ((i :-> o) : (i ++ s)) :-> (o ++ s) apply :: forall a b c s. NiceConstant a => (a & (Lambda (a, b) c & s)) :-> (Lambda b c & s) dip :: forall a s s'. HasCallStack => (s :-> s') -> (a & s) :-> (a & s') -- | Version of dipN which uses Peano number. It is inteded for -- internal usage in Lorentz. dipNPeano :: forall (n :: Peano) (inp :: [Type]) (out :: [Type]) (s :: [Type]) (s' :: [Type]). ConstraintDIPNLorentz n inp out s s' => (s :-> s') -> inp :-> out dipN :: forall (n :: Nat) (inp :: [Type]) (out :: [Type]) (s :: [Type]) (s' :: [Type]). ConstraintDIPNLorentz (ToPeano n) inp out s s' => (s :-> s') -> inp :-> out failWith :: KnownValue a => (a & s) :-> t cast :: KnownValue a => (a & s) :-> (a & s) pack :: forall a s. NicePackedValue a => (a & s) :-> (ByteString & s) unpack :: forall a s. NiceUnpackedValue a => (ByteString & s) :-> (Maybe a & s) concat :: ConcatOpHs c => (c & (c & s)) :-> (c & s) concat' :: ConcatOpHs c => (List c & s) :-> (c & s) slice :: SliceOpHs c => (Natural & (Natural & (c & s))) :-> (Maybe c & s) isNat :: (Integer & s) :-> (Maybe Natural & s) add :: ArithOpHs Add n m => (n & (m & s)) :-> (ArithResHs Add n m & s) sub :: ArithOpHs Sub n m => (n & (m & s)) :-> (ArithResHs Sub n m & s) rsub :: ArithOpHs Sub n m => (m & (n & s)) :-> (ArithResHs Sub n m & s) mul :: ArithOpHs Mul n m => (n & (m & s)) :-> (ArithResHs Mul n m & s) ediv :: EDivOpHs n m => (n & (m & s)) :-> (Maybe (EDivOpResHs n m, EModOpResHs n m) & s) abs :: UnaryArithOpHs Abs n => (n & s) :-> (UnaryArithResHs Abs n & s) neg :: UnaryArithOpHs Neg n => (n & s) :-> (UnaryArithResHs Neg n & s) lsl :: ArithOpHs Lsl n m => (n & (m & s)) :-> (ArithResHs Lsl n m & s) lsr :: ArithOpHs Lsr n m => (n & (m & s)) :-> (ArithResHs Lsr n m & s) or :: ArithOpHs Or n m => (n & (m & s)) :-> (ArithResHs Or n m & s) and :: ArithOpHs And n m => (n & (m & s)) :-> (ArithResHs And n m & s) xor :: ArithOpHs Xor n m => (n & (m & s)) :-> (ArithResHs Xor n m & s) not :: UnaryArithOpHs Not n => (n & s) :-> (UnaryArithResHs Not n & s) compare :: ArithOpHs Compare n n => (n & (n & s)) :-> (ArithResHs Compare n n & s) eq0 :: UnaryArithOpHs Eq' n => (n & s) :-> (UnaryArithResHs Eq' n & s) neq0 :: UnaryArithOpHs Neq n => (n & s) :-> (UnaryArithResHs Neq n & s) lt0 :: UnaryArithOpHs Lt n => (n & s) :-> (UnaryArithResHs Lt n & s) gt0 :: UnaryArithOpHs Gt n => (n & s) :-> (UnaryArithResHs Gt n & s) le0 :: UnaryArithOpHs Le n => (n & s) :-> (UnaryArithResHs Le n & s) ge0 :: UnaryArithOpHs Ge n => (n & s) :-> (UnaryArithResHs Ge n & s) int :: (Natural & s) :-> (Integer & s) self :: forall p s. NiceParameter p => s :-> (ContractRef p & s) contract :: forall p s. NiceParameter p => (Address & s) :-> (Maybe (ContractRef p) & s) transferTokens :: forall p s. NiceParameter p => (p & (Mutez & (ContractRef p & s))) :-> (Operation & s) setDelegate :: (Maybe KeyHash & s) :-> (Operation & s) createContract :: forall p g s. (NiceStorage g, ParameterEntryPoints p) => Contract p g -> (Maybe KeyHash & (Mutez & (g & s))) :-> (Operation & (Address & s)) implicitAccount :: (KeyHash & s) :-> (ContractRef () & s) now :: s :-> (Timestamp & s) amount :: s :-> (Mutez & s) balance :: s :-> (Mutez & s) checkSignature :: (PublicKey & (Signature & (ByteString & s))) :-> (Bool & s) sha256 :: (ByteString & s) :-> (ByteString & s) sha512 :: (ByteString & s) :-> (ByteString & s) blake2B :: (ByteString & s) :-> (ByteString & s) hashKey :: (PublicKey & s) :-> (KeyHash & s) -- | Warning: STEPS_TO_QUOTA instruction is deprecated in Michelson -- 005 stepsToQuota :: s :-> (Natural & s) -- | Warning: Using source is considered a bad practice. Consider -- using sender instead until further investigation source :: s :-> (Address & s) sender :: s :-> (Address & s) address :: (ContractRef a & s) :-> (Address & s) chainId :: s :-> (ChainId & s) -- | Execute given instruction on truncated stack. -- -- This instruction requires you to specify the piece of stack to -- truncate as type argument. framed :: forall s i o. (KnownList i, KnownList o) => (i :-> o) -> (i ++ s) :-> (o ++ s) -- | Helper instruction. -- -- Checks whether given key present in the storage and fails if it is. -- This instruction leaves stack intact. failingWhenPresent :: forall c k s v st e. (MemOpHs c, k ~ MemOpKeyHs c, KnownValue e, st ~ (k & (v & (c & s)))) => (forall s0. (k : s0) :-> (e : s0)) -> st :-> st -- | Like update, but throw an error on attempt to overwrite -- existing entry. updateNew :: forall c k s e. (UpdOpHs c, MemOpHs c, k ~ UpdOpKeyHs c, k ~ MemOpKeyHs c, KnownValue e) => (forall s0. (k : s0) :-> (e : s0)) -> (k & (UpdOpParamsHs c & (c & s))) :-> (c & s) -- | Duplicate an element of stack referring it by type. -- -- If stack contains multiple entries of this type, compile error is -- raised. dupT :: forall a st. DupT st a st => st :-> (a : st) -- | Dip repeatedly until element of the given type is on top of the stack. -- -- If stack contains multiple entries of this type, compile error is -- raised. dipT :: forall a inp dinp dout out. DipT inp a inp dinp dout out => (dinp :-> dout) -> inp :-> out -- | Remove element with the given type from the stack. dropT :: forall a inp dinp dout out. (DipT inp a inp dinp dout out, dinp ~ (a : dout)) => inp :-> out -- | Version of Entrypoint which accepts no argument. type Entrypoint_ store = '[store] :-> ContractOut store -- | Single entrypoint of a contract. -- -- Note that we cannot make it return [[Operation], store] -- because such entrypoint should've been followed by pair, and -- this is not possible if entrypoint implementation ends with -- failWith. type Entrypoint param store = '[param, store] :-> ContractOut store -- | Whether two types have the same Michelson representation. type Coercible_ a b = ToT a ~ ToT b -- | Convert between values of types that have the same representation. coerce_ :: Coercible_ a b => (a & s) :-> (b & s) gcoerce_ :: Coercible_ (t a) (t b) => (t a : s) :-> (t b : s) -- | Convert between two stacks via failing. fakeCoerce :: s1 :-> s2 -- | Specialized version of coerce_ to wrap into a haskell newtype. coerceWrap :: Coercible_ newtyp (Unwrapped newtyp) => (Unwrapped newtyp : s) :-> (newtyp : s) -- | Specialized version of coerce_ to unwrap a haskell newtype. coerceUnwrap :: Coercible_ newtyp (Unwrapped newtyp) => (newtyp : s) :-> (Unwrapped newtyp : s) -- | Lift given value to a named value. toNamed :: Label name -> (a : s) :-> (NamedF Identity a name : s) -- | Unpack named value. fromNamed :: Label name -> (NamedF Identity a name : s) :-> (a : s) -- | Make up a FutureContract. futureContract :: (Address : s) :-> (FutureContract p : s) -- | Get address referred by FutureContract. unFutureContract :: (FutureContract p : s) :-> (Address : s) type CaseTC dt out inp clauses = (InstrCaseC dt inp out, RMap (CaseClauses dt), RecFromTuple clauses, clauses ~ Rec (CaseClauseL inp out) (CaseClauses dt)) -- | Provides "case" arrow which works on different wrappers for clauses. class CaseArrow name body clause | clause -> name, clause -> body -- | Lift an instruction to case clause. -- -- You should write out constructor name corresponding to the clause -- explicitly. Prefix constructor name with "c" letter, otherwise your -- label will not be recognized by Haskell parser. Passing constructor -- name can be circumvented but doing so is not recomended as mentioning -- contructor name improves readability and allows avoiding some -- mistakes. (/->) :: CaseArrow name body clause => Label name -> body -> clause infixr 0 /-> -- | Lorentz analogy of CaseClause, it works on plain Type -- types. data CaseClauseL (inp :: [Type]) (out :: [Type]) (param :: CaseClauseParam) [CaseClauseL] :: (AppendCtorField x inp :-> out) -> CaseClauseL inp out ( 'CaseClauseParam ctor x) -- | Shortcut for multiple HasFieldOfType constraints. type family HasFieldsOfType (dt :: Type) (fs :: [NamedField]) :: Constraint type n := ty = 'NamedField n ty infixr 0 := -- | A pair of field name and type. data NamedField NamedField :: Symbol -> Type -> NamedField -- | Like HasField, but allows constrainting field type. type HasFieldOfType dt fname fieldTy = (HasField dt fname, GetFieldType dt fname ~ fieldTy) -- | Allows field access and modification. type HasField dt fname = (InstrGetFieldC dt fname, InstrSetFieldC dt fname) -- | Extract a field of a datatype replacing the value of this datatype -- with the extracted field. -- -- For this and the following functions you have to specify field name -- which is either record name or name attached with (:!) -- operator. toField :: forall dt name st. InstrGetFieldC dt name => Label name -> (dt & st) :-> (GetFieldType dt name & st) -- | Like toField, but leaves field named. toFieldNamed :: forall dt name st. InstrGetFieldC dt name => Label name -> (dt & st) :-> ((name :! GetFieldType dt name) & st) -- | Extract a field of a datatype, leaving the original datatype on stack. getField :: forall dt name st. InstrGetFieldC dt name => Label name -> (dt & st) :-> (GetFieldType dt name & (dt : st)) -- | Like getField, but leaves field named. getFieldNamed :: forall dt name st. InstrGetFieldC dt name => Label name -> (dt & st) :-> ((name :! GetFieldType dt name) & (dt : st)) -- | Set a field of a datatype. setField :: forall dt name st. InstrSetFieldC dt name => Label name -> (GetFieldType dt name : (dt : st)) :-> (dt : st) -- | Apply given modifier to a datatype field. modifyField :: forall dt name st. (InstrGetFieldC dt name, InstrSetFieldC dt name) => Label name -> (forall st0. (GetFieldType dt name : st0) :-> (GetFieldType dt name : st0)) -> (dt & st) :-> (dt & st) -- | Make up a datatype. You provide a pack of individual fields -- constructors. -- -- Each element of the accepted record should be an instruction wrapped -- with fieldCtor function. This instruction will have access to -- the stack at the moment of calling construct. Instructions -- have to output fields of the built datatype, one per instruction; -- instructions order is expected to correspond to the order of fields in -- the datatype. construct :: forall dt st. (InstrConstructC dt, RMap (ConstructorFieldTypes dt)) => Rec (FieldConstructor st) (ConstructorFieldTypes dt) -> st :-> (dt & st) -- | Version of construct which accepts tuple of field constructors. constructT :: forall dt fctors st. (InstrConstructC dt, RMap (ConstructorFieldTypes dt), fctors ~ Rec (FieldConstructor st) (ConstructorFieldTypes dt), RecFromTuple fctors) => IsoRecTuple fctors -> st :-> (dt & st) -- | Lift an instruction to field constructor. fieldCtor :: HasCallStack => (st :-> (f & st)) -> FieldConstructor st f -- | Wrap entry in constructor. Useful for sum types. wrap_ :: forall dt name st. InstrWrapC dt name => Label name -> AppendCtorField (GetCtorField dt name) st :-> (dt & st) -- | Pattern match on the given sum type. -- -- You have to provide a Rec containing case branches. To -- construct a case branch use /-> operator. case_ :: forall dt out inp. (InstrCaseC dt inp out, RMap (CaseClauses dt)) => Rec (CaseClauseL inp out) (CaseClauses dt) -> (dt & inp) :-> out -- | Like case_, accepts a tuple of clauses, which may be more -- convenient. -- -- If user is experiencing problems with wierd errors about tuples while -- using this function, he should take look at Instances and -- ensure that his tuple isn't bigger than generated instances, if so, he -- should probably extend number of generated instances. caseT :: forall dt out inp clauses. CaseTC dt out inp clauses => IsoRecTuple clauses -> (dt & inp) :-> out -- | Wrap entry in constructor. Useful for sum types. unwrapUnsafe_ :: forall dt name st. InstrUnwrapC dt name => Label name -> (dt & st) :-> (CtorOnlyField name dt : st) -- | Put a document item. doc :: DocItem di => di -> s :-> s -- | Group documentation built in the given piece of code into block -- dedicated to one thing, e.g. to one entry point. docGroup :: DocGrouping -> (inp :-> out) -> inp :-> out -- | Give a name to given contract. Apply it to the whole contract code. contractName :: Text -> (inp :-> out) -> inp :-> out buildLorentzDoc :: (inp :-> out) -> ContractDoc renderLorentzDoc :: (inp :-> out) -> LText -- | Leave only instructions related to documentation. -- -- This function is useful when your method executes a lambda coming from -- outside, but you know its properties and want to propagate its -- documentation to your contract code. cutLorentzNonDoc :: (inp :-> out) -> s :-> s -- | Collect all fields with the given marker. type PickMarkedFields marker template = GPickMarkedFields marker (Rep template) -- | Get kind of field. type GetUStoreFieldMarker store name = FSMarker (GetUStore name store) -- | Get type of plain field. This ignores marker with field type. type GetUStoreField store name = FSValue (GetUStore name store) -- | Get type of submap value. type GetUStoreValue store name = MSValue (GetUStore name store) -- | Get type of submap key. type GetUStoreKey store name = MSKey (GetUStore name store) -- | Allows to specify format of key under which fields of this type are -- stored. Useful to avoid collisions. class KnownUStoreMarker (marker :: UStoreMarkerType) where { -- | Display type-level information about UStore field with given marker -- and field value type. Used for error messages. type family ShowUStoreField marker v :: ErrorMessage; type ShowUStoreField marker v = 'Text "field of type " :<>: 'ShowType v; } -- | By field name derive key under which field should be stored. mkFieldMarkerUKey :: (KnownUStoreMarker marker, KnownSymbol name) => Label name -> ByteString -- | By field name derive key under which field should be stored. mkFieldMarkerUKey :: (KnownUStoreMarker marker, KnownSymbol name) => Label name -> ByteString -- | Just a plain field used as data. type UStoreField = UStoreFieldExt UMarkerPlainField -- | Specific kind used to designate markers for UStoreFieldExt. -- -- We suggest that fields may serve different purposes and so annotated -- with special markers accordingly. See example below. -- -- This kind is implemented like that because we want markers to differ -- from all other types in kind; herewith UStoreMarkerType is -- still an open kind (has potentially infinite number of inhabitants). type UStoreMarkerType = UStoreMarker -> Type -- | Describes plain field in the storage. newtype UStoreFieldExt (m :: UStoreMarkerType) (v :: Type) UStoreField :: v -> UStoreFieldExt [unUStoreField] :: UStoreFieldExt -> v -- | Describes one virtual big map in the storage. newtype k |~> v UStoreSubMap :: Map k v -> (|~>) k v [unUStoreSubMap] :: (|~>) k v -> Map k v -- | Gathers multple fields and BigMaps under one object. -- -- Type argument of this datatype stands for a "store template" - a -- datatype with one constructor and multiple fields, each containing an -- object of type UStoreFieldExt or |~> and -- corresponding to single virtual field or BigMap respectively. -- It's also possible to parameterize it with a larger type which is a -- product of types satisfying the above property. data UStore (a :: Type) -- | Lift an UStore to another UStore which contains all the -- entries of the former under given field. -- -- This function is not intended for use in migrations, only in normal -- entry points. -- -- Note that this function ensures that template of resulting store does -- not contain inner nested templates with duplicated fields, otherwise -- UStore invariants could get broken. liftUStore :: (Generic template, RequireAllUniqueFields template) => Label name -> (UStore (GetFieldType template name) : s) :-> (UStore template : s) -- | Unlift an UStore to a smaller UStore which is part of -- the former. -- -- This function is not intended for use in migrations, only in normal -- entry points. -- -- Surprisingly, despite smaller UStore may have extra entries, -- this function is safe when used in contract code. Truly, all getters -- and setters are still safe to use. Also, there is no way for the -- resulting small UStore to leak outside of the contract since -- the only place where big_map can appear is contract storage, -- so this small UStore can be either dropped or lifted back via -- liftUStore to appear as part of the new contract's state. -- -- When this function is run as part of standalone instructions sequence, -- not as part of contract code (e.g. in tests), you may get an -- UStore with entries not inherent to it. unliftUStore :: Generic template => Label name -> (UStore template : s) :-> (UStore (GetFieldType template name) : s) -- | Code of migration for UStore. -- -- Invariant: preferably should fit into op size / gas limits (quite -- obvious). Often this stands for exactly one stage of migration (one -- Tezos transaction). newtype MigrationScript MigrationScript :: Lambda UStore_ UStore_ -> MigrationScript [unMigrationScript] :: MigrationScript -> Lambda UStore_ UStore_ -- | Absolutely empty storage. type InitUStore = UStore () -- | Alias for UStoreMigration which accepts UStore templates as -- type arguments. type UStoreMigrationT ot nt = UStoreMigration (UStore ot) (UStore nt) -- | Keeps information about migration between UStores with two -- given templates. Note that it is polymorphic over whole storage types, -- not their templates, for convenience (so that there is no need to -- export the template). data UStoreMigration (oldStore :: Type) (newStore :: Type) -- | Turn Migration into a whole piece of code for transforming -- storage. -- -- This is not want you'd want to use for contract deployment because of -- gas and operation size limits that Tezos applies to transactions. migrationToLambda :: UStoreMigrationT oldTemplate newTemplate -> Lambda (UStore oldTemplate) (UStore newTemplate) -- | Safe way to create migration scripts for UStore. -- -- You have to supply a code which would transform MUStore, -- coverring required diff step-by-step. All basic instructions work, -- also use migrate* functions from this module to operate with -- MUStore. -- -- This method produces a whole migration, it cannot be splitted in -- batches. In case if your migration is too big to be applied within a -- single transaction, use mkUStoreBatchedMigration. mkUStoreMigration :: Lambda (MUStore oldTempl newTempl (BuildDiff oldTempl newTempl) '[]) (MUStore oldTempl newTempl '[] _1) -> UStoreMigrationT oldTempl newTempl -- | Get migration script in case of simple (non-batched) migration. migrationToScript :: UStoreMigration ot nt -> MigrationScript -- | Pick a type documentation from CtorField. class DeriveCtorFieldDoc (cf :: CtorField) deriveCtorFieldDoc :: DeriveCtorFieldDoc cf => Maybe DType -- | Describes argument of an entry point. data DEntryPointArg DEntryPointArg :: Maybe DType -> [ParamBuildingStep] -> DEntryPointArg -- | Argument of the entry point. Pass Nothing if no argument is -- required. [epaArg] :: DEntryPointArg -> Maybe DType -- | Describes a way to lift an entry point argument into full parameter -- which can be passed to the contract. -- -- Steps are supposed to be applied in the order in which they are given. -- E.g. suppose that an entry point is called as Run (Service1 -- arg); then the first step should describe wrapping into -- Service1 constructor, and the second step should be about -- wrapping into Run constructor. [epaBuilding] :: DEntryPointArg -> [ParamBuildingStep] -- | Describes a parameter building step. -- -- This can be wrapping into (Haskell) constructor, or a more complex -- transformation. data ParamBuildingStep ParamBuildingStep :: Markdown -> (CurrentParam -> Markdown) -> (CurrentParam -> Markdown) -> ParamBuildingStep -- | Plain english description of this step. [pbsEnglish] :: ParamBuildingStep -> Markdown -- | How to construct parameter in Haskell code. [pbsHaskell] :: ParamBuildingStep -> CurrentParam -> Markdown -- | How to construct parameter working on raw Michelson. [pbsMichelson] :: ParamBuildingStep -> CurrentParam -> Markdown -- | Default value for DEntryPoint type argument. data PlainEntryPointsKind -- | Gathers information about single entry point. -- -- We assume that entry points might be of different kinds, which is -- designated by phantom type parameter. For instance, you may want to -- have several groups of entry points corresponding to various parts of -- a contract - specifying different kind type argument for each -- of those groups will allow you defining different DocItem -- instances with appropriate custom descriptions for them. data DEntryPoint (kind :: Type) DEntryPoint :: Text -> SubDoc -> DEntryPoint -- | Default implementation of docItemToMarkdown for entry points. diEntryPointToMarkdown :: HeaderLevel -> DEntryPoint level -> Markdown mkDEntryPointArgSimple :: forall t. TypeHasDoc t => DEntryPointArg -- | Go over contract code and update every occurrence of -- DEntryPointArg documentation item, adding the given step to its -- "how to build parameter" description. clarifyParamBuildingSteps :: ParamBuildingStep -> (inp :-> out) -> inp :-> out -- | Like caseT, to be used for pattern-matching on parameter. -- -- Modifies documentation accordingly. Including description of -- entrypoints' arguments, thus for them you will need to supply -- TypeHasDoc instance. entryCase :: forall dt entryPointKind out inp clauses. (CaseTC dt out inp clauses, DocumentEntryPoints entryPointKind dt) => Proxy entryPointKind -> IsoRecTuple clauses -> (dt & inp) :-> out -- | Signature of userFailWith. type FailUsingArg e name fieldTy s s' = (KnownSymbol name, IsError e, IsoValue fieldTy, CtorHasOnlyField name e fieldTy, Each [Typeable, SingI] '[ToT fieldTy], HasCallStack) => Label name -> fieldTy : s :-> s' -- | Prompt an error message saying that IsoValue is not applicable -- for this type. type family CustomErrorNoIsoValue a -- | Documentation for custom errors. -- -- Mentions that entrypoint throws given error. data DThrows [DThrows] :: IsError e => Proxy e -> DThrows -- | Mentions that contract uses given error. data DError [DError] :: IsError e => Proxy e -> DError class (KnownSymbol tag, TypeHasDoc (ErrorArg tag), IsError (CustomError tag)) => CustomErrorHasDoc tag -- | What should happen for this error to be raised. customErrDocMdCause :: CustomErrorHasDoc tag => Markdown -- | Brief version of customErrDocMdCause. This will appear along -- with the error when mentioned in entrypoint description. -- -- By default, the first sentence of the full description is used. customErrDocMdCauseInEntrypoint :: CustomErrorHasDoc tag => Markdown -- | Error class. -- -- By default this returns "unknown error" class; though you should -- provide explicit implementation in order to avoid a warning. customErrClass :: CustomErrorHasDoc tag => ErrorClass -- | Clarification of error argument meaning. -- -- Provide when it's not obvious, e.g. argument is not named with -- :!. -- -- NOTE: This should not be an entire sentence, rather just the -- semantic backbone. -- -- Bad: * Error argument stands for the previous value of -- approval. -- -- Good: * the previous value of approval * pair, first -- argument of which is one thing, and the second is another customErrArgumentSemantics :: CustomErrorHasDoc tag => Maybe Markdown -- | Error class on how the error should be handled by the client. data ErrorClass -- | Normal expected error. Examples: "insufficient balance", "wallet does -- not exist". ErrClassActionException :: ErrorClass -- | Invalid argument passed to entrypoint. Examples: your entrypoint -- accepts an enum represented as nat, and unknown value is -- provided. This includes more complex cases which involve multiple -- entrypoints. E.g. API provides iterator interface, middleware should -- care about using it hiding complex details and exposing a simpler API -- to user; then an attempt to request non-existing element would also -- correspond to an error from this class. ErrClassBadArgument :: ErrorClass -- | Unexpected error. Most likely it means that there is a bug in the -- contract or the contract has been deployed incorrectly. ErrClassContractInternal :: ErrorClass -- | It's possible to leave error class unspecified. ErrClassUnknown :: ErrorClass -- | Material custom error. -- -- Use this in pattern matches against error (e.g. in tests). data CustomError (tag :: Symbol) CustomError :: Label tag -> ErrorArg tag -> CustomError [ceTag] :: CustomError -> Label tag [ceArg] :: CustomError -> ErrorArg tag -- | Declares a custom error, defining error name - error argument -- relation. -- -- If your error is supposed to carry no argument, then provide -- (). -- -- Note that this relation is defined globally rather than on -- per-contract basis, so define errors accordingly. If your error has -- argument specific to your contract, call it such that error name -- reflects its belonging to this contract. type family ErrorArg (tag :: Symbol) :: Type -- | Use this type as replacement for () when you really -- want to leave error cause unspecified. data UnspecifiedError UnspecifiedError :: UnspecifiedError class ErrorHasDoc e -- | Name of error as it appears in the corresponding section title. errorDocName :: ErrorHasDoc e => Text -- | What should happen for this error to be raised. errorDocMdCause :: ErrorHasDoc e => Markdown -- | Brief version of errorDocMdCause. -- -- This will appear along with the error when mentioned in entrypoint -- description. By default, the first sentence of the full description is -- used. errorDocMdCauseInEntrypoint :: ErrorHasDoc e => Markdown -- | How this error is represented in Haskell. errorDocHaskellRep :: ErrorHasDoc e => Markdown -- | Error class. errorDocClass :: ErrorHasDoc e => ErrorClass -- | Which definitions documentation for this error mentions. errorDocDependencies :: ErrorHasDoc e => [SomeDocDefinitionItem] -- | Haskell type representing error. class (Typeable e, ErrorHasDoc e) => IsError e -- | Converts a Haskell error into Value representation. errorToVal :: IsError e => e -> (forall t. ErrorScope t => Value t -> r) -> r -- | Converts a Value into Haskell error. errorFromVal :: (IsError e, Typeable t, SingI t) => Value t -> Either Text e -- | Implementation of errorToVal via IsoValue. isoErrorToVal :: (KnownError e, IsoValue e) => e -> (forall t. ErrorScope t => Value t -> r) -> r -- | Implementation of errorFromVal via IsoValue. isoErrorFromVal :: (Typeable t, Typeable (ToT e), IsoValue e) => Value t -> Either Text e -- | Fail with the given Haskell value. failUsing :: forall e s t. IsError e => e -> s :-> t -- | Fail, providing a reference to the place in the code where this -- function is called. -- -- Like error in Haskell code, this instruction is for internal -- errors only. failUnexpected :: MText -> s :-> t -- | Fail with given custom error. failCustom :: forall tag err s any. (err ~ ErrorArg tag, CustomErrorHasDoc tag, KnownError err) => Label tag -> (err : s) :-> any -- | Specialization of failCustom for no-arg errors. failCustom_ :: forall tag s any notVoidError. (TypeErrorUnless (ErrorArg tag == ()) notVoidError, CustomErrorHasDoc tag, notVoidError ~ ( 'Text "Expected no-arg error, but given error requires argument of type " :<>: 'ShowType (ErrorArg tag))) => Label tag -> s :-> any -- | Implementation of typeDocMdDescription (of TypeHasDoc -- typeclass) for Haskell types which sole purpose is to be error. typeDocMdDescriptionReferToError :: forall e. IsError e => Markdown -- | This is to be included on top of Errors section of the -- generated documentation. errorsDocumentation :: Markdown -- | Implementation of errorToVal for custom errors. -- | Deprecated: Datatype error declarations has been deprecated customErrorToVal :: (LooseSumC e, HasCallStack) => e -> (forall t. ErrorScope t => Value t -> r) -> r -- | Implementation of errorFromVal for custom errors. -- -- This function is deprecated. -- | Deprecated: Datatype error declarations has been deprecated customErrorFromVal :: forall t e. (SingI t, LooseSumC e) => Value t -> Either Text e -- | Derive IsError instance for given type. -- -- This will also forbid deriving IsoValue instance for that type -- to avoid having multiple different Michelson representations. -- | Deprecated: Datatype error declarations has been deprecated deriveCustomError :: Name -> Q [Dec] -- | Fail with given error, picking argument for error from the top of the -- stack. -- -- If your error constructor does not carry an argument, use -- failUsing function instead. Consider the following practice: -- once error datatype for your contract is defined, create a -- specialization of this function to the error type. -- -- This function is deprecated. -- | Deprecated: Datatype error declarations has been deprecated failUsingArg :: forall err name fieldTy s s'. FailUsingArg err name fieldTy s s' -- | Newtype over void result type used in tests to distinguish successful -- void result from other errors. -- -- Usage example: lExpectFailWith (== VoidResult roleMaster)` -- -- This error is special - it can contain arguments of different types -- depending on entrypoint which raises it. newtype VoidResult r VoidResult :: r -> VoidResult r [unVoidResult] :: VoidResult r -> r -- | void type synonym as described in A1. data Void_ (a :: Type) (b :: Type) Void_ :: a -> Lambda b b -> Void_ -- | Entry point argument. [voidParam] :: Void_ -> a -- | Type of result reported via failWith. [voidResProxy] :: Void_ -> Lambda b b -- | view type synonym as described in A1. data View (a :: Type) (r :: Type) View :: a -> ContractRef r -> View [viewParam] :: View -> a [viewCallbackTo] :: View -> ContractRef r -- | Insert given element into map. mapInsert :: (MapInstrs map, IsComparable k) => (k : (v : (map k v : s))) :-> (map k v : s) -- | Insert given element into map, ensuring that it does not overwrite any -- existing entry. -- -- As first argument accepts container name (for error message). mapInsertNew :: (MapInstrs map, IsComparable k, KnownValue e) => (forall s0. (k : s0) :-> (e : s0)) -> (k : (v : (map k v : s))) :-> (map k v : s) -- | Delete element from the map. deleteMap :: forall k v s. (MapInstrs map, IsComparable k, KnownValue k, KnownValue v) => (k : (map k v : s)) :-> (map k v : s) type IfCmpXConstraints a op = (Typeable a, ArithOpHs Compare a a, UnaryArithOpHs op (ArithResHs Compare a a), UnaryArithResHs op (ArithResHs Compare a a) ~ Bool) eq :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Eq' (ArithResHs Compare n n) & s) neq :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Neq (ArithResHs Compare n n) & s) gt :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Gt (ArithResHs Compare n n) & s) le :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Le (ArithResHs Compare n n) & s) ge :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Ge (ArithResHs Compare n n) & s) lt :: ArithOpHs Compare n n => (n & (n & s)) :-> (UnaryArithResHs Lt (ArithResHs Compare n n) & s) ifEq0 :: IfCmp0Constraints a Eq' => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifNeq0 :: IfCmp0Constraints a Neq => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifLt0 :: IfCmp0Constraints a Lt => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifGt0 :: IfCmp0Constraints a Gt => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifLe0 :: IfCmp0Constraints a Le => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifGe0 :: IfCmp0Constraints a Ge => (s :-> s') -> (s :-> s') -> (a & s) :-> s' ifEq :: IfCmpXConstraints a Eq' => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifNeq :: IfCmpXConstraints a Neq => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifLt :: IfCmpXConstraints a Lt => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifGt :: IfCmpXConstraints a Gt => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifLe :: IfCmpXConstraints a Le => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' ifGe :: IfCmpXConstraints a Ge => (s :-> s') -> (s :-> s') -> (a & (a & s)) :-> s' -- | Analog of the FAIL macro in Michelson. Its usage is discouraged -- because it doesn't carry any information about failure. -- | Warning: fail_ remains in code fail_ :: a :-> c assert :: IsError err => err -> (Bool & s) :-> s assertEq0 :: (IfCmp0Constraints a Eq', IsError err) => err -> (a & s) :-> s assertNeq0 :: (IfCmp0Constraints a Neq, IsError err) => err -> (a & s) :-> s assertLt0 :: (IfCmp0Constraints a Lt, IsError err) => err -> (a & s) :-> s assertGt0 :: (IfCmp0Constraints a Gt, IsError err) => err -> (a & s) :-> s assertLe0 :: (IfCmp0Constraints a Le, IsError err) => err -> (a & s) :-> s assertGe0 :: (IfCmp0Constraints a Ge, IsError err) => err -> (a & s) :-> s assertEq :: (IfCmpXConstraints a Eq', IsError err) => err -> (a & (a & s)) :-> s assertNeq :: (IfCmpXConstraints a Neq, IsError err) => err -> (a & (a & s)) :-> s assertLt :: (IfCmpXConstraints a Lt, IsError err) => err -> (a & (a & s)) :-> s assertGt :: (IfCmpXConstraints a Gt, IsError err) => err -> (a & (a & s)) :-> s assertLe :: (IfCmpXConstraints a Le, IsError err) => err -> (a & (a & s)) :-> s assertGe :: (IfCmpXConstraints a Ge, IsError err) => err -> (a & (a & s)) :-> s assertNone :: IsError err => err -> (Maybe a & s) :-> s assertSome :: IsError err => err -> (Maybe a & s) :-> (a & s) assertLeft :: IsError err => err -> (Either a b & s) :-> (a & s) assertRight :: IsError err => err -> (Either a b & s) :-> (b & s) assertUsing :: IsError a => a -> (Bool & s) :-> s -- | Custom Lorentz macro that drops element with given index (starting -- from 0) from the stack. dropX :: forall (n :: Nat) a inp out s s'. (ConstraintDIPNLorentz (ToPeano n) inp out s s', s ~ (a : s')) => inp :-> out -- | Duplicate the top of the stack n times. -- -- For example, `cloneX @3` has type `a & s :-> a & a & a -- & a & s`. cloneX :: forall (n :: Nat) a s. CloneX (ToPeano n) a s => (a & s) :-> CloneXT (ToPeano n) a s -- | DUU+P macro. For example, `duupX @3` is DUUUP, it -- puts the 3-rd (starting from 1) element to the top of the stack. Note -- that it is implemented differently for `n ≤ 2` and for `n > 2`. In -- the latter case it is implemented using dipN, dig and -- dup. In the former case it uses specialized versions. There is -- also a minor difference with the implementation of `DUU*P` in -- Michelson. They implement DUUUUP as `DIP 3 { DUP }; DIG 4`. -- We implement it as `DIP 3 { DUP }; DIG 3`. These are equivalent. Our -- version is supposedly cheaper, at least it should be packed more -- efficiently due to the way numbers are packed. duupX :: forall (n :: Nat) a (s :: [Type]) (s1 :: [Type]) (tail :: [Type]). (ConstraintDuupXLorentz (ToPeano (n - 1)) s a s1 tail, DuupX (ToPeano n) s a s1 tail) => s :-> (a : s) -- | Version of framed which accepts number of elements on input -- stack which should be preserved. -- -- You can treat this macro as calling a Michelson function with given -- number of arguments. framedN :: forall n nNat s i i' o o'. (nNat ~ ToPeano n, i' ~ Take nNat i, s ~ Drop nNat i, i ~ (i' ++ s), o ~ (o' ++ s), KnownList i', KnownList o') => (i' :-> o') -> i :-> o papair :: (a & (b & (c & s))) :-> (((a, b), c) & s) ppaiir :: (a & (b & (c & s))) :-> ((a, (b, c)) & s) unpair :: ((a, b) & s) :-> (a & (b & s)) cdar :: ((a1, (a2, b)) & s) :-> (a2 & s) cddr :: ((a1, (a2, b)) & s) :-> (b & s) caar :: (((a, b1), b2) & s) :-> (a & s) cadr :: (((a, b1), b2) & s) :-> (b1 & s) setCar :: ((a, b1) & (b2 & s)) :-> ((b2, b1) & s) setCdr :: ((a, b1) & (b2 & s)) :-> ((a, b2) & s) mapCar :: ((a & s) :-> (a1 & s)) -> ((a, b) & s) :-> ((a1, b) & s) mapCdr :: ((b & ((a, b) & s)) :-> (b1 & ((a, b) & s))) -> ((a, b) & s) :-> ((a, b1) & s) ifRight :: ((b & s) :-> s') -> ((a & s) :-> s') -> (Either a b & s) :-> s' ifSome :: ((a & s) :-> s') -> (s :-> s') -> (Maybe a & s) :-> s' -- | Insert given element into set. -- -- This is a separate function from updateMap because stacks -- they operate with differ in length. setInsert :: IsComparable e => (e & (Set e & s)) :-> (Set e & s) -- | Insert given element into set, ensuring that it does not overwrite any -- existing entry. -- -- As first argument accepts container name. setInsertNew :: (IsComparable e, KnownValue err) => (forall s0. (e : s0) :-> (err : s0)) -> (e & (Set e & s)) :-> (Set e & s) -- | Delete given element from the set. setDelete :: IsComparable e => (e & (Set e & s)) :-> (Set e & s) buildViewTuple :: TupleF a => View a r -> Builder buildView :: (a -> Builder) -> View a r -> Builder -- | Polymorphic version of View constructor. mkView :: ToContractRef r contract => a -> contract -> View a r view_ :: NiceParameter r => (forall s0. ((a, storage) & s0) :-> (r : s0)) -> (View a r & (storage & s)) :-> ((List Operation, storage) & s) mkVoid :: forall b a. a -> Void_ a b void_ :: forall a b s s' anything. (IsError (VoidResult b), KnownValue b) => ((a & s) :-> (b & s')) -> (Void_ a b & s) :-> anything -- | Turn FutureContract into actual contract. -- -- This requires contracts lookup and may fail. pickFutureContract :: NiceParameter p => (FutureContract p : s) :-> (Maybe (ContractRef p) : s) -- | Push a value of contract type. -- -- Doing this via push instruction is not possible, so we need to -- perform extra actions here. -- -- Aside from contract value itself you will need to specify -- which error to throw in case this value is not valid. pushContractRef :: NiceParameter arg => (forall s0. (Address : s) :-> s0) -> ContractRef arg -> s :-> (ContractRef arg : s) -- | Write down all sensisble constraints which given store -- satisfies and apply them to constrained. -- -- This store should have |~> and UStoreFieldExt fields -- in its immediate fields, no deep inspection is performed. type HasUStoreForAllIn store constrained = (Generic store, GHasStoreForAllIn constrained (Rep store)) -- | This constraint can be used if a function needs to work with -- big store, but needs to know only about some field of it. type HasUField name ty store = (FieldAccessC store name, GetUStoreField store name ~ ty) -- | This constraint can be used if a function needs to work with -- big store, but needs to know only about some submap(s) of it. -- -- It can use all UStore operations for a particular name, key and value -- without knowing whole template. type HasUStore name key value store = (KeyAccessC store name, ValueAccessC store name, GetUStoreKey store name ~ key, GetUStoreValue store name ~ value) ustoreMem :: forall store name s. KeyAccessC store name => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (Bool : s) ustoreGet :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (Maybe (GetUStoreValue store name) : s) ustoreUpdate :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (Maybe (GetUStoreValue store name) : (UStore store : s))) :-> (UStore store : s) ustoreInsert :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (GetUStoreKey store name : (GetUStoreValue store name : (UStore store : s))) :-> (UStore store : s) -- | Insert a key-value pair, but fail if it will overwrite some existing -- entry. ustoreInsertNew :: forall store name s. (KeyAccessC store name, ValueAccessC store name) => Label name -> (forall s0 any. (GetUStoreKey store name : s0) :-> any) -> (GetUStoreKey store name : (GetUStoreValue store name : (UStore store : s))) :-> (UStore store : s) ustoreDelete :: forall store name s. KeyAccessC store name => Label name -> (GetUStoreKey store name : (UStore store : s)) :-> (UStore store : s) -- | Like toField, but for UStore. -- -- This may fail only if UStore was made up incorrectly during -- contract initialization. ustoreToField :: forall store name s. FieldAccessC store name => Label name -> (UStore store : s) :-> (GetUStoreField store name : s) -- | Like getField, but for UStore. -- -- This may fail only if UStore was made up incorrectly during -- contract initialization. ustoreGetField :: forall store name s. FieldAccessC store name => Label name -> (UStore store : s) :-> (GetUStoreField store name : (UStore store : s)) -- | Like setField, but for UStore. ustoreSetField :: forall store name s. FieldAccessC store name => Label name -> (GetUStoreField store name : (UStore store : s)) :-> (UStore store : s) -- | Get a field present in old version of UStore. migrateGetField :: forall field oldTempl newTempl diff touched fieldTy s. (HasUField field fieldTy oldTempl, RequireUntouched field (field `IsElem` touched)) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) -- | Add a field which was not present before. This covers one addition -- from the diff and any removals of field with given name. -- -- This function cannot overwrite existing field with the same name, if -- this is necessary use migrateOverwriteField which would declare -- removal explicitly. migrateAddField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcAdd field diff, HasUField field fieldTy newTempl) => Label field -> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Remove a field which should not be present in new version of storage. -- This covers one removal from the diff. -- -- In fact, this action could be performed automatically, but since -- removal is a destructive operation, being explicit about it seems like -- a good thing. migrateRemoveField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcRemove field diff, HasUField field fieldTy oldTempl) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Get and remove a field from old version of UStore. -- -- You probably want to use this more often than plain -- migrateRemoveField. migrateExtractField :: forall field oldTempl newTempl diff touched fieldTy newDiff marker s. ('(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcRemove field diff, HasUField field fieldTy oldTempl, RequireUntouched field (field `IsElem` touched)) => Label field -> (MUStore oldTempl newTempl diff touched : s) :-> (fieldTy : (MUStore oldTempl newTempl newDiff (field : touched) : s)) -- | Remove field and write new one in place of it. -- -- This is semantically equivalent to dip (migrateRemoveField label) -- >> migrateAddField label, but is cheaper. migrateOverwriteField :: forall field oldTempl newTempl diff touched fieldTy oldFieldTy marker oldMarker newDiff newDiff0 s. ('(UStoreFieldExt oldMarker oldFieldTy, newDiff0) ~ CoverDiff 'DcRemove field diff, '(UStoreFieldExt marker fieldTy, newDiff) ~ CoverDiff 'DcAdd field newDiff0, HasUField field fieldTy newTempl) => Label field -> (fieldTy : (MUStore oldTempl newTempl diff touched : s)) :-> (MUStore oldTempl newTempl newDiff (field : touched) : s) -- | Get the old version of storage. -- -- This can be applied only in the beginning of migration. -- -- In fact this function is not very useful, all required operations -- should be available for MUStore, but leaving it here just in -- case. mustoreToOld :: RequireBeInitial touched => (MUStore oldTemplate newTemplate remDiff touched : s) :-> (UStore oldTemplate : s) -- | Given template can be converted to UStore value. class (Generic template, GUStoreConversible (Rep template)) => UStoreConversible template -- | Make UStore from separate big_maps and fields. mkUStore :: UStoreConversible template => template -> UStore template -- | Decompose UStore into separate big_maps and fields. -- -- Since this function needs to UNPACK content of -- UStore to actual keys and values, you have to provide -- UnpackEnv. -- -- Along with resulting value, you get a list of UStore entries -- which were not recognized as belonging to any submap or field -- according to UStore's template - this should be empty unless -- UStore invariants were violated. ustoreDecompose :: forall template. UStoreConversible template => UStore template -> Either Text (UStoreContent, template) -- | Make migration script which initializes UStore from scratch. fillUStore :: UStoreConversible template => template -> UStoreMigrationT () template -- | Like ustoreDecompose, but requires all entries from -- UStore to be recognized. ustoreDecomposeFull :: forall template. UStoreConversible template => UStore template -> Either Text template -- | Entry points template derived from given ADT sum. type UParamLinearized p = GUParamLinearized (Rep p) -- | Constraint required by uparamFromAdt. type UParamLinearize p = (Generic p, GUParamLinearize (Rep p)) -- | Make up a "case" over entry points. class CaseUParam (entries :: [EntryPointKind]) -- | An action invoked when user-provided entry point is not found. type UParamFallback inp out = ((MText, ByteString) : inp) :-> out -- | Implementations of some entry points. -- -- Note that this thing inherits properties of Rec, e.g. you can -- Data.Vinyl.Core.rappend implementations for two entry point -- sets when assembling scattered parts of a contract. type EntryPointsImpl inp out entries = Rec (CaseClauseU inp out) entries data EntryPointLookupError NoSuchEntryPoint :: MText -> EntryPointLookupError ArgumentUnpackFailed :: EntryPointLookupError -- | This class is needed to implement unpackUParam. class UnpackUParam (c :: Type -> Constraint) entries -- | Turn UParam into a Haskell value. Since we don't know its type -- in compile time, we have to erase it using ConstrainedSome. The -- user of this function can require arbitrary constraint to hold -- (depending on how they want to use the result). unpackUParam :: UnpackUParam c entries => UParam entries -> Either EntryPointLookupError (MText, ConstrainedSome c) -- | This type can store any value that satisfies a certain constraint. data ConstrainedSome (c :: Type -> Constraint) [ConstrainedSome] :: c a => a -> ConstrainedSome c -- | Ensure that given entry points do no contain duplicated names. type family RequireUniqueEntryPoints (entries :: [EntryPointKind]) :: Constraint -- | Get type of entry point argument by its name. type family LookupEntryPoint (name :: Symbol) (entries :: [EntryPointKind]) :: Type -- | Encapsulates parameter for one of entry points. It keeps entry point -- name and corresponding argument serialized. -- -- In Haskell world, we keep an invariant of that contained value relates -- to one of entry points from entries list. newtype UParam (entries :: [EntryPointKind]) UParamUnsafe :: (MText, ByteString) -> UParam -- | A convenient alias for type-level name-something pair. type (n :: Symbol) ?: (a :: k) = '(n, a) -- | An entry point is described by two types: its name and type of -- argument. type EntryPointKind = (Symbol, Type) -- | Construct a UParam safely. mkUParam :: (KnownSymbol name, NicePackedValue a, LookupEntryPoint name entries ~ a, RequireUniqueEntryPoints entries) => Label name -> a -> UParam entries -- | Helper instruction which extracts content of UParam. unwrapUParam :: (UParam entries : s) :-> ((MText, ByteString) : s) -- | Default implementation for UParamFallback, simply reports an -- error. uparamFallbackFail :: UParamFallback inp out -- | Pattern-match on given UParam entries. -- -- You have to provide all case branches and a fallback action on case -- when entry point is not found. caseUParam :: (CaseUParam entries, RequireUniqueEntryPoints entries) => Rec (CaseClauseU inp out) entries -> UParamFallback inp out -> (UParam entries : inp) :-> out -- | Like caseUParam, but accepts a tuple of clauses, not a -- Rec. caseUParamT :: forall entries inp out clauses. (clauses ~ Rec (CaseClauseU inp out) entries, RecFromTuple clauses, CaseUParam entries) => IsoRecTuple clauses -> UParamFallback inp out -> (UParam entries : inp) :-> out -- | Make up UParam from ADT sum. -- -- Entry points template will consist of (constructorName, -- constructorFieldType) pairs. Each constructor is expected to have -- exactly one field. uparamFromAdt :: UParamLinearize up => up -> UParam (UParamLinearized up) -- | Note that calling given entrypoints involves constructing -- UParam. pbsUParam :: forall ctorName. KnownSymbol ctorName => ParamBuildingStep -- | Concise way to write down constraints with expected content of a -- storage. -- -- Use it like follows: -- --
--   type StorageConstraint = StorageContains
--     [ "fieldInt" := Int
--     , "fieldNat" := Nat
--     , "balances" := Address ~> Int
--     ]
--   
type family StorageContains store (content :: [NamedField]) :: Constraint -- | Indicates a submap with given key and value types. data k ~> v infix 9 ~> -- | Provides operations on fields for storage. class StoreHasSubmap store mname key value | store mname -> key value storeSubmapOps :: StoreHasSubmap store mname key value => StoreSubmapOps store mname key value -- | Datatype containing the full implementation of StoreHasField -- typeclass. -- -- We use this grouping because in most cases implementation will be -- chosen among the default ones, and initializing all methods at once is -- simpler and more consistent. (One can say that we are trying to -- emulate DerivingVia extension.) data StoreSubmapOps store mname key value StoreSubmapOps :: (forall s. Label mname -> (key : (store : s)) :-> (Bool : s)) -> (forall s. Label mname -> (key : (store : s)) :-> (Maybe value : s)) -> (forall s. Label mname -> (key : (Maybe value : (store : s))) :-> (store : s)) -> (forall s. Maybe (Label mname -> (key : (store : s)) :-> (store : s))) -> (forall s. Maybe (Label mname -> (key : (value : (store : s))) :-> (store : s))) -> StoreSubmapOps store mname key value [sopMem] :: StoreSubmapOps store mname key value -> forall s. Label mname -> (key : (store : s)) :-> (Bool : s) [sopGet] :: StoreSubmapOps store mname key value -> forall s. Label mname -> (key : (store : s)) :-> (Maybe value : s) [sopUpdate] :: StoreSubmapOps store mname key value -> forall s. Label mname -> (key : (Maybe value : (store : s))) :-> (store : s) [sopDelete] :: StoreSubmapOps store mname key value -> forall s. Maybe (Label mname -> (key : (store : s)) :-> (store : s)) [sopInsert] :: StoreSubmapOps store mname key value -> forall s. Maybe (Label mname -> (key : (value : (store : s))) :-> (store : s)) -- | Provides operations on fields for storage. class StoreHasField store fname ftype | store fname -> ftype storeFieldOps :: StoreHasField store fname ftype => StoreFieldOps store fname ftype -- | Datatype containing the full implementation of StoreHasField -- typeclass. -- -- We use this grouping because in most cases implementation will be -- chosen among the default ones, and initializing all methods at once is -- simpler and more consistent. (One can say that we are trying to -- emulate benefits of DerivingVia extension.) data StoreFieldOps store fname ftype StoreFieldOps :: (forall s. Label fname -> (store : s) :-> (ftype : s)) -> (forall s. Label fname -> (ftype : (store : s)) :-> (store : s)) -> StoreFieldOps store fname ftype [sopToField] :: StoreFieldOps store fname ftype -> forall s. Label fname -> (store : s) :-> (ftype : s) [sopSetField] :: StoreFieldOps store fname ftype -> forall s. Label fname -> (ftype : (store : s)) :-> (store : s) -- | Pick storage field. stToField :: StoreHasField store fname ftype => Label fname -> (store : s) :-> (ftype : s) -- | Get storage field, preserving the storage itself on stack. stGetField :: StoreHasField store fname ftype => Label fname -> (store : s) :-> (ftype : (store : s)) -- | Update storage field. stSetField :: StoreHasField store fname ftype => Label fname -> (ftype : (store : s)) :-> (store : s) -- | Check value presence in storage. stMem :: StoreHasSubmap store mname key value => Label mname -> (key : (store : s)) :-> (Bool : s) -- | Get value in storage. stGet :: StoreHasSubmap store mname key value => Label mname -> (key : (store : s)) :-> (Maybe value : s) -- | Update a value in storage. stUpdate :: StoreHasSubmap store mname key value => Label mname -> (key : (Maybe value : (store : s))) :-> (store : s) -- | Delete a value in storage. stDelete :: forall store mname key value s. (StoreHasSubmap store mname key value, KnownValue value) => Label mname -> (key : (store : s)) :-> (store : s) -- | Add a value in storage. stInsert :: StoreHasSubmap store mname key value => Label mname -> (key : (value : (store : s))) :-> (store : s) -- | Add a value in storage, but fail if it will overwrite some existing -- entry. stInsertNew :: StoreHasSubmap store mname key value => Label mname -> (forall s0 any. (key : s0) :-> any) -> (key : (value : (store : s))) :-> (store : s) -- | Implementation of StoreHasField for case of datatype keeping a -- pack of fields. storeFieldOpsADT :: HasFieldOfType dt fname ftype => StoreFieldOps dt fname ftype -- | Implementation of StoreHasField for a data type which has an -- instance of StoreHasField inside. For instance, it can be used -- for top-level storage. storeFieldOpsDeeper :: (HasFieldOfType storage fieldsPartName fields, StoreHasField fields fname ftype) => Label fieldsPartName -> StoreFieldOps storage fname ftype -- | Implementation of StoreHasSubmap for a data type which has an -- instance of StoreHasSubmap inside. For instance, it can be used -- for top-level storage. storeSubmapOpsDeeper :: (HasFieldOfType storage bigMapPartName fields, StoreHasSubmap fields mname key value) => Label bigMapPartName -> StoreSubmapOps storage mname key value -- | Pretend that given StoreSubmapOps implementation is made up for -- submap with name desiredName, not its actual name. Logic of -- the implementation remains the same. -- -- Use case: imagine that your code requires access to submap named -- X, but in your storage that submap is called Y. Then -- you implement the instance which makes X refer to Y: -- --
--   instance StoreHasSubmap Store X Key Value where
--     storeSubmapOps = storeSubmapOpsReferTo #Y storeSubmapOpsForY
--   
storeSubmapOpsReferTo :: Label name -> StoreSubmapOps storage name key value -> StoreSubmapOps storage desiredName key value -- | Pretend that given StoreSubmapOps implementation is made up for -- submap with name desiredName, not its actual name. Logic of -- the implementation remains the same. -- -- See also storeSubmapOpsReferTo. storeFieldOpsReferTo :: Label name -> StoreFieldOps storage name field -> StoreFieldOps storage desiredName field -- | Chain two implementations of field operations. -- -- Suits for a case when your store does not contain its fields directly -- rather has a nested structure. composeStoreFieldOps :: Label nameInStore -> StoreFieldOps store nameInStore substore -> StoreFieldOps substore nameInSubstore field -> StoreFieldOps store nameInSubstore field -- | Chain implementations of field and submap operations. composeStoreSubmapOps :: Label nameInStore -> StoreFieldOps store nameInStore substore -> StoreSubmapOps substore mname key value -> StoreSubmapOps store mname key value -- | Predicate for if ... then .. else ... construction, defines a -- kind of operation applied to the top elements of the current stack. data Condition st arg argl argr [Holds] :: Condition s (Bool : s) s s [IsSome] :: Condition s (Maybe a : s) (a : s) s [IsNone] :: Condition s (Maybe a : s) s (a : s) [IsLeft] :: Condition s (Either l r : s) (l : s) (r : s) [IsRight] :: Condition s (Either l r : s) (r : s) (l : s) [IsCons] :: Condition s ([a] : s) (a : ([a] : s)) s [IsNil] :: Condition s ([a] : s) s (a : ([a] : s)) [IsZero] :: (UnaryArithOpHs Eq' a, UnaryArithResHs Eq' a ~ Bool) => Condition s (a : s) s s [IsNotZero] :: (UnaryArithOpHs Eq' a, UnaryArithResHs Eq' a ~ Bool) => Condition s (a : s) s s [IsEq] :: IfCmpXConstraints a Eq' => Condition s (a : (a : s)) s s [IsNeq] :: IfCmpXConstraints a Neq => Condition s (a : (a : s)) s s [IsLt] :: IfCmpXConstraints a Lt => Condition s (a : (a : s)) s s [IsGt] :: IfCmpXConstraints a Gt => Condition s (a : (a : s)) s s [IsLe] :: IfCmpXConstraints a Le => Condition s (a : (a : s)) s s [IsGe] :: IfCmpXConstraints a Ge => Condition s (a : (a : s)) s s -- | Aliases for '(#)' used by do-blocks. (>>) :: (a :-> b) -> (b :-> c) -> a :-> c -- | Defines semantics of if ... then ... else ... construction. ifThenElse :: Condition st arg argl argr -> (argl :-> o) -> (argr :-> o) -> arg :-> o -- | This is a bidirectional map with correspondence between numeric and -- textual error tags. type ErrorTagMap = Bimap Natural MText -- | Find all textual error tags that are used in typical FAILWITH -- patterns within given instruction. Map them to natural numbers. gatherErrorTags :: (inp :-> out) -> HashSet MText -- | Add more error tags to an existing ErrorTagMap. It is useful -- when your contract consists of multiple parts (e. g. in case of -- contract upgrade), you have existing map for some part and want to add -- tags from another part to it. You can pass empty map as existing one -- if you just want to build ErrorTagMap from a set of textual -- tags. See buildErrorTagMap. addNewErrorTags :: ErrorTagMap -> HashSet MText -> ErrorTagMap -- | Build ErrorTagMap from a set of textual tags. buildErrorTagMap :: HashSet MText -> ErrorTagMap -- | For each typical FAILWITH that uses a string to represent error -- tag this function changes error tag to be a number using the supplied -- conversion map. It assumes that supplied map contains all such strings -- (and will error out if it does not). It will always be the case if you -- gather all error tags using gatherErrorTags and build -- ErrorTagMap from them using addNewErrorTags. applyErrorTagMap :: HasCallStack => ErrorTagMap -> (inp :-> out) -> inp :-> out -- | This function implements the simplest scenario of using this module's -- functionality: 1. Gather all error tags from a single instruction. 2. -- Turn them into error conversion map. 3. Apply this conversion. useNumericErrors :: HasCallStack => (inp :-> out) -> (inp :-> out, ErrorTagMap) -- | If you apply numeric error representation in your contract, -- errorFromVal will stop working because it doesn't know about -- this transformation. This function takes this transformation into -- account. If a number is used as a tag, but it is not found in the -- passed map, we conservatively preserve that number (because this whole -- approach is rather a heuristic). errorFromValNumeric :: (Typeable t, SingI t, IsError e) => ErrorTagMap -> Value t -> Either Text e -- | Functions to import contracts to be used in tests. module Michelson.Test.Import readContract :: forall cp st. Each [Typeable, SingI] [cp, st] => FilePath -> Text -> Either ImportContractError (Contract, Contract cp st) -- | Import contract from a given file path. -- -- This function reads file, parses and type checks a contract. Within -- the typechecking we assume that no contracts are originated, otherwise -- a type checking error will be caused. -- -- This function may throw IOException and -- ImportContractError. importContract :: forall cp st. Each [Typeable, SingI] [cp, st] => FilePath -> IO (Contract, Contract cp st) importUntypedContract :: FilePath -> IO Contract -- | Error type for importContract function. data ImportContractError ICEUnexpectedParamType :: !Type -> !Type -> ImportContractError ICEUnexpectedStorageType :: !Type -> !Type -> ImportContractError ICEParse :: !ParserException -> ImportContractError ICETypeCheck :: !TCError -> ImportContractError -- | Import contract and use to create test trees. Both versions of -- contract are passed to the callback function (untyped and typed). -- -- If contract's import fails, a tree with single failing test will be -- generated (so test tree will likely be generated unexceptionally, but -- a failing result will notify about problem). testTreesWithContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> IO [TestTree]) -> IO [TestTree] -- | Like testTreesWithContract but for Lorentz types. testTreesWithContractL :: (Each [Typeable, SingI] [ToT cp, ToT st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> IO [TestTree]) -> IO [TestTree] -- | Like testTreesWithContract but supplies only typed contract. testTreesWithTypedContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> (Contract cp st -> IO [TestTree]) -> IO [TestTree] -- | Like testTreesWithContract but supplies only untyped contract. testTreesWithUntypedContract :: HasCallStack => FilePath -> (Contract -> IO [TestTree]) -> IO [TestTree] concatTestTrees :: [IO [TestTree]] -> IO [TestTree] -- | Import contract and use it in the spec. Both versions of contract are -- passed to the callback function (untyped and typed). -- -- If contract's import fails, a spec with single failing expectation -- will be generated (so tests will likely run unexceptionally, but a -- failing result will notify about problem). specWithContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> Spec) -> Spec -- | Like specWithContract, but for Lorentz types. specWithContractL :: (Each [Typeable, SingI] [ToT cp, ToT st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> Spec) -> Spec -- | A version of specWithContract which passes only the typed -- representation of the contract. specWithTypedContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> (Contract cp st -> Spec) -> Spec specWithUntypedContract :: FilePath -> (Contract -> Spec) -> Spec instance GHC.Classes.Eq Michelson.Test.Import.ImportContractError instance GHC.Show.Show Michelson.Test.Import.ImportContractError instance Formatting.Buildable.Buildable Michelson.Test.Import.ImportContractError instance GHC.Exception.Type.Exception Michelson.Test.Import.ImportContractError -- | Module containing some utilities for testing Michelson contracts using -- Haskell testing frameworks (hspec and QuickCheck in particular). It's -- Morley testing EDSL. module Michelson.Test -- | Import contract and use it in the spec. Both versions of contract are -- passed to the callback function (untyped and typed). -- -- If contract's import fails, a spec with single failing expectation -- will be generated (so tests will likely run unexceptionally, but a -- failing result will notify about problem). specWithContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> Spec) -> Spec -- | Like specWithContract, but for Lorentz types. specWithContractL :: (Each [Typeable, SingI] [ToT cp, ToT st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> Spec) -> Spec -- | A version of specWithContract which passes only the typed -- representation of the contract. specWithTypedContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> (Contract cp st -> Spec) -> Spec specWithUntypedContract :: FilePath -> (Contract -> Spec) -> Spec -- | Import contract and use to create test trees. Both versions of -- contract are passed to the callback function (untyped and typed). -- -- If contract's import fails, a tree with single failing test will be -- generated (so test tree will likely be generated unexceptionally, but -- a failing result will notify about problem). testTreesWithContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> IO [TestTree]) -> IO [TestTree] -- | Like testTreesWithContract but for Lorentz types. testTreesWithContractL :: (Each [Typeable, SingI] [ToT cp, ToT st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> IO [TestTree]) -> IO [TestTree] -- | Like testTreesWithContract but supplies only untyped contract. testTreesWithUntypedContract :: HasCallStack => FilePath -> (Contract -> IO [TestTree]) -> IO [TestTree] -- | Like testTreesWithContract but supplies only typed contract. testTreesWithTypedContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> (Contract cp st -> IO [TestTree]) -> IO [TestTree] concatTestTrees :: [IO [TestTree]] -> IO [TestTree] importUntypedContract :: FilePath -> IO Contract type ContractReturn st = (Either MichelsonFailed ([Operation], Value st), InterpreterState) -- | Type for contract execution validation. -- -- It's a function which is supplied with contract execution output -- (failure or new storage with operation list). -- -- Function returns a property which type is designated by type variable -- prop and might be Property or Expectation or -- anything else relevant. type ContractPropValidator st prop = ContractReturn st -> prop -- | Contract's property tester against given input. Takes contract -- environment, initial storage and parameter, interprets contract on -- this input and invokes validation function. contractProp :: (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> param -> storage -> prop -- | Version of contractProp which takes Val as arguments -- instead of regular Haskell values. contractPropVal :: Contract cp st -> ContractPropValidator st prop -> ContractEnv -> Value cp -> Value st -> prop contractRepeatedProp :: (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> [param] -> storage -> prop contractRepeatedPropVal :: Contract cp st -> ContractPropValidator st prop -> ContractEnv -> [Value cp] -> Value st -> prop -- | Validator for integrational testing. If an error is expected, it -- should be Left with validator for errors. Otherwise it should -- check final global state and its updates. type IntegrationalValidator = Either (InterpreterError -> Bool) SuccessValidator -- | Validator for integrational testing that expects successful execution. type SuccessValidator = InternalState -> GState -> [GStateUpdate] -> Either ValidationError () type IntegrationalScenario = IntegrationalScenarioM Validated -- | A monad inside which integrational tests can be described using -- do-notation. type IntegrationalScenarioM = StateT InternalState (Except ScenarioError) -- | Integrational test that executes given operations and validates them -- using given validator. It can fail using Expectation -- capability. It starts with initGState and some reasonable dummy -- values for gas limit and current timestamp. You can update blockchain -- state by performing some operations. integrationalTestExpectation :: HasCallStack => IntegrationalScenario -> Expectation -- | Integrational test similar to integrationalTestExpectation. It -- can fail using Property capability. It can be used with -- QuickCheck's forAll to make a property-based test with -- arbitrary data. integrationalTestProperty :: IntegrationalScenario -> Property -- | Originate a contract with given initial storage and balance. Its -- address is returned. originate :: Contract -> Text -> Value -> Mutez -> IntegrationalScenarioM Address -- | Transfer tokens to given address. transfer :: TxData -> Address -> IntegrationalScenarioM () -- | Execute all operations that were added to the scenarion since last -- validate call. If validator fails, the execution will be -- aborted. validate :: IntegrationalValidator -> IntegrationalScenario -- | Make all further interpreter calls (which are triggered by the -- validate function) use given gas limit. setMaxSteps :: RemainingSteps -> IntegrationalScenarioM () -- | Make all further interpreter calls (which are triggered by the -- validate function) use given timestamp as the current one. setNow :: Timestamp -> IntegrationalScenarioM () -- | Execute multiple testing scenarios independently, basing them on -- scenario built till this point. -- -- The following property holds for this function: -- -- pre >> branchout [a, b, c] = branchout [pre >> a, pre -- >> b, pre >> c] . -- -- In case of property failure in one of the branches no following branch -- is executed. -- -- Providing empty list of scenarios to this function causes error; we do -- not require NonEmpty here though for convenience. branchout :: HasCallStack => [(Text, IntegrationalScenario)] -> IntegrationalScenario -- | Make a tuple with name without extra syntactic noise. (?-) :: Text -> a -> (Text, a) infixr 0 ?- -- | Compose two success validators. -- -- For example: -- -- expectBalance bal addr composeValidators -- expectStorageUpdateConst addr2 ValueUnit composeValidators :: SuccessValidator -> SuccessValidator -> SuccessValidator -- | Compose a list of success validators. composeValidatorsList :: [SuccessValidator] -> SuccessValidator -- | SuccessValidator that always passes. expectAnySuccess :: SuccessValidator -- | Check that there were no updates. expectNoUpdates :: SuccessValidator -- | Check that there were no storage updates. expectNoStorageUpdates :: SuccessValidator -- | Check that storage value is updated for given address. Takes a -- predicate that is used to check the value. -- -- It works even if updates are not filtered (i. e. a value can be -- updated more than once). expectStorageUpdate :: Address -> (Value -> Either ValidationError ()) -> SuccessValidator -- | Like expectStorageUpdate, but expects a constant. expectStorageUpdateConst :: Address -> Value -> SuccessValidator -- | Check that eventually address has some particular balance. expectBalance :: Address -> Mutez -> SuccessValidator -- | Check that eventually address has some particular storage value. expectStorageConst :: Address -> Value -> SuccessValidator -- | Check that interpreter failed due to gas exhaustion. expectGasExhaustion :: InterpreterError -> Bool -- | Expect that interpretation of contract with given address ended with -- [FAILED]. expectMichelsonFailed :: (MichelsonFailed -> Bool) -> Address -> InterpreterError -> Bool -- | Data associated with a particular transaction. data TxData TxData :: !Address -> !Value -> !Mutez -> TxData [tdSenderAddress] :: TxData -> !Address [tdParameter] :: TxData -> !Value [tdAmount] :: TxData -> !Mutez -- | One of genesis addresses. genesisAddress :: Address -- | A Property that always failes with given message. failedProp :: Text -> Property -- | A Property that always succeeds. succeededProp :: Property -- | The Property holds on `Left a`. qcIsLeft :: Show b => Either a b -> Property -- | The Property holds on `Right b`. qcIsRight :: Show a => Either a b -> Property -- | Dummy ContractEnv with some reasonable hardcoded values. You -- can override values you are interested in using record update syntax. dummyContractEnv :: ContractEnv -- | Minimal (earliest) timestamp used for Arbitrary (CValue -- 'CTimestamp) minTimestamp :: Timestamp -- | Maximal (latest) timestamp used for Arbitrary (CValue -- 'CTimestamp) maxTimestamp :: Timestamp -- | Median of minTimestamp and maxTimestamp. Useful for -- testing (exactly half of generated dates will be before and after this -- date). midTimestamp :: Timestamp module Util.Test.Arbitrary -- | Run given generator deterministically. runGen :: Int -> Gen a -> a instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Value.InternalByteString instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Ext.Var instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Ext.TyVar instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Ext.StackTypePattern instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Aliases.ExpandedExtInstr instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.ErrorPos.Pos instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.ErrorPos.Pos instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.ErrorPos.SrcPos instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.ErrorPos.SrcPos instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.ErrorPos.LetName instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.ErrorPos.LetName instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.ErrorPos.InstrCallStack instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.ErrorPos.InstrCallStack instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.Untyped.Instr.ExpandedOp instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Instr.ExpandedOp instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Tezos.Core.Mutez instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.Untyped.Annotation.TypeAnn instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Annotation.TypeAnn instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.Untyped.Annotation.FieldAnn instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Annotation.FieldAnn instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.Untyped.Annotation.VarAnn instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Annotation.VarAnn instance (Test.QuickCheck.Arbitrary.Arbitrary op, Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary op) => Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary (Michelson.Untyped.Contract.Contract' op) instance Test.QuickCheck.Arbitrary.Arbitrary op => Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Untyped.Contract.Contract' op) instance (Test.QuickCheck.Arbitrary.Arbitrary op, Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary op, Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Untyped.Ext.ExtInstrAbstract op)) => Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary (Michelson.Untyped.Instr.InstrAbstract op) instance (Test.QuickCheck.Arbitrary.Arbitrary op, Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Untyped.Ext.ExtInstrAbstract op)) => Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Untyped.Instr.InstrAbstract op) instance (Test.QuickCheck.Arbitrary.Arbitrary op, Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary op) => Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary (Michelson.Untyped.Value.Value' op) instance Test.QuickCheck.Arbitrary.Arbitrary op => Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Untyped.Value.Value' op) instance (Test.QuickCheck.Arbitrary.Arbitrary op, Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary op) => Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary (Michelson.Untyped.Value.Elt op) instance Test.QuickCheck.Arbitrary.Arbitrary op => Test.QuickCheck.Arbitrary.Arbitrary (Michelson.Untyped.Value.Elt op) instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.Untyped.Type.Type instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Type.Type instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.Untyped.Type.T instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Type.T instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.Untyped.Type.CT instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Type.CT instance Test.QuickCheck.Arbitrary.ADT.ToADTArbitrary Michelson.Untyped.Type.Comparable instance Test.QuickCheck.Arbitrary.Arbitrary Michelson.Untyped.Type.Comparable instance (GHC.Classes.Ord k, Test.QuickCheck.Arbitrary.Arbitrary k, Test.QuickCheck.Arbitrary.Arbitrary v) => Test.QuickCheck.Arbitrary.Arbitrary (k Lorentz.UStore.Types.|~> v) instance Test.QuickCheck.Arbitrary.Arbitrary v => Test.QuickCheck.Arbitrary.Arbitrary (Lorentz.UStore.Types.UStoreFieldExt m v) -- | Mirrors Integrational module in a Lorentz way. module Lorentz.Test.Integrational -- | Data associated with a particular transaction. data TxData TxData :: !Address -> !Value -> !Mutez -> TxData [tdSenderAddress] :: TxData -> !Address [tdParameter] :: TxData -> !Value [tdAmount] :: TxData -> !Mutez -- | Initially these addresses have a lot of money. genesisAddresses :: NonEmpty Address -- | One of genesis addresses. genesisAddress :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress1 :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress2 :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress3 :: Address genesisAddress4 :: Address genesisAddress5 :: Address genesisAddress6 :: Address -- | Like originate, but for typed contract and value. tOriginate :: (ParameterScope cp, StorageScope st) => Contract cp st -> Text -> Value st -> Mutez -> IntegrationalScenarioM Address -- | Similar to transfer, for typed values. tTransfer :: forall cp. ParameterScope cp => ("from" :! Address) -> ("to" :! Address) -> Mutez -> Value cp -> IntegrationalScenarioM () -- | Similar to expectStorageConst, for typed stuff. tExpectStorageConst :: forall st. StorageScope st => Address -> Value st -> SuccessValidator -- | Validator for integrational testing. If an error is expected, it -- should be Left with validator for errors. Otherwise it should -- check final global state and its updates. type IntegrationalValidator = Either (InterpreterError -> Bool) SuccessValidator -- | Validator for integrational testing that expects successful execution. type SuccessValidator = InternalState -> GState -> [GStateUpdate] -> Either ValidationError () -- | A monad inside which integrational tests can be described using -- do-notation. type IntegrationalScenarioM = StateT InternalState (Except ScenarioError) type IntegrationalScenario = IntegrationalScenarioM Validated data ValidationError UnexpectedInterpreterError :: IntegrationalInterpreterError -> ValidationError UnexpectedTypeCheckError :: TCError -> ValidationError ExpectingInterpreterToFail :: ValidationError IncorrectUpdates :: ValidationError -> [GStateUpdate] -> ValidationError IncorrectStorageUpdate :: AddressName -> Text -> ValidationError InvalidStorage :: AddressName -> ExpectedStorage -> Text -> ValidationError InvalidBalance :: AddressName -> ExpectedBalance -> Text -> ValidationError UnexpectedUpdates :: NonEmpty GStateUpdate -> ValidationError CustomValidationError :: Text -> ValidationError -- | Integrational test that executes given operations and validates them -- using given validator. It can fail using Expectation -- capability. It starts with initGState and some reasonable dummy -- values for gas limit and current timestamp. You can update blockchain -- state by performing some operations. integrationalTestExpectation :: HasCallStack => IntegrationalScenario -> Expectation -- | Integrational test similar to integrationalTestExpectation. It -- can fail using Property capability. It can be used with -- QuickCheck's forAll to make a property-based test with -- arbitrary data. integrationalTestProperty :: IntegrationalScenario -> Property -- | Like originate, but for Lorentz contracts. lOriginate :: forall cp st. (NiceParameter cp, NiceStorage st) => Contract cp st -> Text -> st -> Mutez -> IntegrationalScenarioM (ContractRef cp) -- | Originate a contract with empty balance and default storage. lOriginateEmpty :: (NiceParameter cp, NiceStorage st, Default st) => Contract cp st -> Text -> IntegrationalScenarioM (ContractRef cp) -- | Similar to transfer, for Lorentz values. lTransfer :: forall cp contract. (NiceParameter cp, ToContractRef cp contract) => ("from" :! Address) -> ("to" :! contract) -> Mutez -> cp -> IntegrationalScenarioM () -- | Call a contract without caring about the source address. Transfers 0 -- mutez. lCall :: forall cp contract. (NiceParameter cp, ToContractRef cp contract) => contract -> cp -> IntegrationalScenarioM () -- | Execute all operations that were added to the scenarion since last -- validate call. If validator fails, the execution will be -- aborted. validate :: IntegrationalValidator -> IntegrationalScenario -- | Make all further interpreter calls (which are triggered by the -- validate function) use given gas limit. setMaxSteps :: RemainingSteps -> IntegrationalScenarioM () -- | Make all further interpreter calls (which are triggered by the -- validate function) use given timestamp as the current one. setNow :: Timestamp -> IntegrationalScenarioM () -- | Increase current time by the given number of seconds. rewindTime :: Integer -> IntegrationalScenarioM () -- | Pretend that given address initiates all the transfers within the code -- block (i.e. SENDER instruction will return this address). withSender :: Address -> IntegrationalScenarioM a -> IntegrationalScenarioM a -- | Make all further interpreter calls (which are triggered by the -- validate function) use given chain id. setChainId :: ChainId -> IntegrationalScenarioM () -- | Execute multiple testing scenarios independently, basing them on -- scenario built till this point. -- -- The following property holds for this function: -- -- pre >> branchout [a, b, c] = branchout [pre >> a, pre -- >> b, pre >> c] . -- -- In case of property failure in one of the branches no following branch -- is executed. -- -- Providing empty list of scenarios to this function causes error; we do -- not require NonEmpty here though for convenience. branchout :: HasCallStack => [(Text, IntegrationalScenario)] -> IntegrationalScenario -- | Make a tuple with name without extra syntactic noise. (?-) :: Text -> a -> (Text, a) infixr 0 ?- -- | Test given scenario with the state gathered till this moment; if this -- scenario passes, go on as if it never happened. offshoot :: Text -> IntegrationalScenario -> IntegrationalScenarioM () -- | Compose two success validators. -- -- For example: -- -- expectBalance bal addr composeValidators -- expectStorageUpdateConst addr2 ValueUnit composeValidators :: SuccessValidator -> SuccessValidator -> SuccessValidator -- | Compose a list of success validators. composeValidatorsList :: [SuccessValidator] -> SuccessValidator -- | SuccessValidator that always passes. expectAnySuccess :: SuccessValidator -- | Check that there were no updates. expectNoUpdates :: SuccessValidator -- | Check that there were no storage updates. expectNoStorageUpdates :: SuccessValidator -- | Similar to expectStorageUpdate, for Lorentz values. lExpectStorageUpdate :: forall st addr. (NiceStorage st, ToAddress addr, HasCallStack) => addr -> (st -> Either ValidationError ()) -> SuccessValidator -- | Like expectBalance, for Lorentz values. lExpectBalance :: ToAddress addr => addr -> Mutez -> SuccessValidator -- | Similar to expectStorageConst, for Lorentz values. lExpectStorageConst :: forall st addr. (NiceStorage st, ToAddress addr) => addr -> st -> SuccessValidator -- | Expect that interpretation of contract with given address ended with -- [FAILED]. lExpectMichelsonFailed :: forall addr. ToAddress addr => (MichelsonFailed -> Bool) -> addr -> InterpreterError -> Bool -- | Expect contract to fail with FAILWITH instruction and provided -- value to match against the given predicate. lExpectFailWith :: forall e. (Typeable (ToT e), IsoValue e) => (e -> Bool) -> InterpreterError -> Bool -- | Expect contract to fail with given error. lExpectError :: forall e. IsError e => (e -> Bool) -> InterpreterError -> Bool -- | Version of lExpectError for the case when numeric -- representation of errors is used. lExpectErrorNumeric :: forall e. IsError e => ErrorTagMap -> (e -> Bool) -> InterpreterError -> Bool -- | Expect contract to fail with given CustomError. lExpectCustomError :: forall tag arg. (IsError (CustomError tag), arg ~ ErrorArg tag, Eq arg) => Label tag -> arg -> InterpreterError -> Bool -- | Version of lExpectCustomError for the case when numeric -- representation of errors is used. lExpectCustomErrorNumeric :: forall tag arg. (IsError (CustomError tag), arg ~ ErrorArg tag, Eq arg) => ErrorTagMap -> Label tag -> arg -> InterpreterError -> Bool -- | Specialization of lExpectCustomError for non-arg error case. lExpectCustomError_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => Label tag -> InterpreterError -> Bool -- | Version of lExpectCustomError_ for the case when numeric -- representation of errors is used. lExpectCustomErrorNumeric_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => ErrorTagMap -> Label tag -> InterpreterError -> Bool -- | Version of lExpectStorageUpdate specialized to "consumer" -- contract (see contractConsumer). lExpectConsumerStorage :: forall cp st contract. (st ~ [cp], NiceStorage st, ToContractRef cp contract) => contract -> (st -> Either ValidationError ()) -> SuccessValidator -- | Assuming that "consumer" contract receives a value from View, -- expect this view return value to be the given one. -- -- Despite consumer stores parameters it was called with in reversed -- order, this function cares about it, so you should provide a list of -- expected values in the same order in which the corresponding events -- were happenning. lExpectViewConsumerStorage :: (st ~ [cp], Eq cp, Buildable cp, NiceStorage st, ToContractRef cp contract) => contract -> [cp] -> SuccessValidator module Lorentz.Test -- | Import contract and use it in the spec. Both versions of contract are -- passed to the callback function (untyped and typed). -- -- If contract's import fails, a spec with single failing expectation -- will be generated (so tests will likely run unexceptionally, but a -- failing result will notify about problem). specWithContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> Spec) -> Spec -- | A version of specWithContract which passes only the typed -- representation of the contract. specWithTypedContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> (Contract cp st -> Spec) -> Spec specWithUntypedContract :: FilePath -> (Contract -> Spec) -> Spec type ContractReturn st = (Either MichelsonFailed ([Operation], Value st), InterpreterState) -- | Type for contract execution validation. -- -- It's a function which is supplied with contract execution output -- (failure or new storage with operation list). -- -- Function returns a property which type is designated by type variable -- prop and might be Property or Expectation or -- anything else relevant. type ContractPropValidator st prop = ContractReturn st -> prop -- | Contract's property tester against given input. Takes contract -- environment, initial storage and parameter, interprets contract on -- this input and invokes validation function. contractProp :: (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> param -> storage -> prop -- | Version of contractProp which takes Val as arguments -- instead of regular Haskell values. contractPropVal :: Contract cp st -> ContractPropValidator st prop -> ContractEnv -> Value cp -> Value st -> prop contractRepeatedProp :: (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> [param] -> storage -> prop contractRepeatedPropVal :: Contract cp st -> ContractPropValidator st prop -> ContractEnv -> [Value cp] -> Value st -> prop -- | Validator for integrational testing. If an error is expected, it -- should be Left with validator for errors. Otherwise it should -- check final global state and its updates. type IntegrationalValidator = Either (InterpreterError -> Bool) SuccessValidator -- | Validator for integrational testing that expects successful execution. type SuccessValidator = InternalState -> GState -> [GStateUpdate] -> Either ValidationError () type IntegrationalScenario = IntegrationalScenarioM Validated -- | A monad inside which integrational tests can be described using -- do-notation. type IntegrationalScenarioM = StateT InternalState (Except ScenarioError) data ValidationError UnexpectedInterpreterError :: IntegrationalInterpreterError -> ValidationError UnexpectedTypeCheckError :: TCError -> ValidationError ExpectingInterpreterToFail :: ValidationError IncorrectUpdates :: ValidationError -> [GStateUpdate] -> ValidationError IncorrectStorageUpdate :: AddressName -> Text -> ValidationError InvalidStorage :: AddressName -> ExpectedStorage -> Text -> ValidationError InvalidBalance :: AddressName -> ExpectedBalance -> Text -> ValidationError UnexpectedUpdates :: NonEmpty GStateUpdate -> ValidationError CustomValidationError :: Text -> ValidationError -- | Integrational test that executes given operations and validates them -- using given validator. It can fail using Expectation -- capability. It starts with initGState and some reasonable dummy -- values for gas limit and current timestamp. You can update blockchain -- state by performing some operations. integrationalTestExpectation :: HasCallStack => IntegrationalScenario -> Expectation -- | Integrational test similar to integrationalTestExpectation. It -- can fail using Property capability. It can be used with -- QuickCheck's forAll to make a property-based test with -- arbitrary data. integrationalTestProperty :: IntegrationalScenario -> Property -- | Like originate, but for Lorentz contracts. lOriginate :: forall cp st. (NiceParameter cp, NiceStorage st) => Contract cp st -> Text -> st -> Mutez -> IntegrationalScenarioM (ContractRef cp) -- | Originate a contract with empty balance and default storage. lOriginateEmpty :: (NiceParameter cp, NiceStorage st, Default st) => Contract cp st -> Text -> IntegrationalScenarioM (ContractRef cp) -- | Similar to transfer, for Lorentz values. lTransfer :: forall cp contract. (NiceParameter cp, ToContractRef cp contract) => ("from" :! Address) -> ("to" :! contract) -> Mutez -> cp -> IntegrationalScenarioM () -- | Call a contract without caring about the source address. Transfers 0 -- mutez. lCall :: forall cp contract. (NiceParameter cp, ToContractRef cp contract) => contract -> cp -> IntegrationalScenarioM () -- | Execute all operations that were added to the scenarion since last -- validate call. If validator fails, the execution will be -- aborted. validate :: IntegrationalValidator -> IntegrationalScenario -- | Make all further interpreter calls (which are triggered by the -- validate function) use given gas limit. setMaxSteps :: RemainingSteps -> IntegrationalScenarioM () -- | Make all further interpreter calls (which are triggered by the -- validate function) use given timestamp as the current one. setNow :: Timestamp -> IntegrationalScenarioM () -- | Increase current time by the given number of seconds. rewindTime :: Integer -> IntegrationalScenarioM () -- | Pretend that given address initiates all the transfers within the code -- block (i.e. SENDER instruction will return this address). withSender :: Address -> IntegrationalScenarioM a -> IntegrationalScenarioM a -- | Make all further interpreter calls (which are triggered by the -- validate function) use given chain id. setChainId :: ChainId -> IntegrationalScenarioM () -- | Execute multiple testing scenarios independently, basing them on -- scenario built till this point. -- -- The following property holds for this function: -- -- pre >> branchout [a, b, c] = branchout [pre >> a, pre -- >> b, pre >> c] . -- -- In case of property failure in one of the branches no following branch -- is executed. -- -- Providing empty list of scenarios to this function causes error; we do -- not require NonEmpty here though for convenience. branchout :: HasCallStack => [(Text, IntegrationalScenario)] -> IntegrationalScenario -- | Make a tuple with name without extra syntactic noise. (?-) :: Text -> a -> (Text, a) infixr 0 ?- -- | Test given scenario with the state gathered till this moment; if this -- scenario passes, go on as if it never happened. offshoot :: Text -> IntegrationalScenario -> IntegrationalScenarioM () -- | Compose two success validators. -- -- For example: -- -- expectBalance bal addr composeValidators -- expectStorageUpdateConst addr2 ValueUnit composeValidators :: SuccessValidator -> SuccessValidator -> SuccessValidator -- | Compose a list of success validators. composeValidatorsList :: [SuccessValidator] -> SuccessValidator -- | SuccessValidator that always passes. expectAnySuccess :: SuccessValidator -- | Check that there were no updates. expectNoUpdates :: SuccessValidator -- | Check that there were no storage updates. expectNoStorageUpdates :: SuccessValidator -- | Similar to expectStorageUpdate, for Lorentz values. lExpectStorageUpdate :: forall st addr. (NiceStorage st, ToAddress addr, HasCallStack) => addr -> (st -> Either ValidationError ()) -> SuccessValidator -- | Like expectBalance, for Lorentz values. lExpectBalance :: ToAddress addr => addr -> Mutez -> SuccessValidator -- | Similar to expectStorageConst, for Lorentz values. lExpectStorageConst :: forall st addr. (NiceStorage st, ToAddress addr) => addr -> st -> SuccessValidator -- | Expect that interpretation of contract with given address ended with -- [FAILED]. lExpectMichelsonFailed :: forall addr. ToAddress addr => (MichelsonFailed -> Bool) -> addr -> InterpreterError -> Bool -- | Expect contract to fail with FAILWITH instruction and provided -- value to match against the given predicate. lExpectFailWith :: forall e. (Typeable (ToT e), IsoValue e) => (e -> Bool) -> InterpreterError -> Bool -- | Expect contract to fail with given error. lExpectError :: forall e. IsError e => (e -> Bool) -> InterpreterError -> Bool -- | Version of lExpectError for the case when numeric -- representation of errors is used. lExpectErrorNumeric :: forall e. IsError e => ErrorTagMap -> (e -> Bool) -> InterpreterError -> Bool -- | Expect contract to fail with given CustomError. lExpectCustomError :: forall tag arg. (IsError (CustomError tag), arg ~ ErrorArg tag, Eq arg) => Label tag -> arg -> InterpreterError -> Bool -- | Version of lExpectCustomError for the case when numeric -- representation of errors is used. lExpectCustomErrorNumeric :: forall tag arg. (IsError (CustomError tag), arg ~ ErrorArg tag, Eq arg) => ErrorTagMap -> Label tag -> arg -> InterpreterError -> Bool -- | Specialization of lExpectCustomError for non-arg error case. lExpectCustomError_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => Label tag -> InterpreterError -> Bool -- | Version of lExpectCustomError_ for the case when numeric -- representation of errors is used. lExpectCustomErrorNumeric_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => ErrorTagMap -> Label tag -> InterpreterError -> Bool -- | Version of lExpectStorageUpdate specialized to "consumer" -- contract (see contractConsumer). lExpectConsumerStorage :: forall cp st contract. (st ~ [cp], NiceStorage st, ToContractRef cp contract) => contract -> (st -> Either ValidationError ()) -> SuccessValidator -- | Assuming that "consumer" contract receives a value from View, -- expect this view return value to be the given one. -- -- Despite consumer stores parameters it was called with in reversed -- order, this function cares about it, so you should provide a list of -- expected values in the same order in which the corresponding events -- were happenning. lExpectViewConsumerStorage :: (st ~ [cp], Eq cp, Buildable cp, NiceStorage st, ToContractRef cp contract) => contract -> [cp] -> SuccessValidator -- | Data associated with a particular transaction. data TxData TxData :: !Address -> !Value -> !Mutez -> TxData [tdSenderAddress] :: TxData -> !Address [tdParameter] :: TxData -> !Value [tdAmount] :: TxData -> !Mutez -- | Initially these addresses have a lot of money. genesisAddresses :: NonEmpty Address -- | One of genesis addresses. genesisAddress :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress1 :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress2 :: Address -- | More genesis addresses -- -- We know size of genesisAddresses, so it is safe to use -- !! genesisAddress3 :: Address genesisAddress4 :: Address genesisAddress5 :: Address genesisAddress6 :: Address -- | A Property that always failes with given message. failedProp :: Text -> Property -- | A Property that always succeeds. succeededProp :: Property -- | The Property holds on `Left a`. qcIsLeft :: Show b => Either a b -> Property -- | The Property holds on `Right b`. qcIsRight :: Show a => Either a b -> Property -- | Dummy ContractEnv with some reasonable hardcoded values. You -- can override values you are interested in using record update syntax. dummyContractEnv :: ContractEnv -- | Minimal (earliest) timestamp used for Arbitrary (CValue -- 'CTimestamp) minTimestamp :: Timestamp -- | Maximal (latest) timestamp used for Arbitrary (CValue -- 'CTimestamp) maxTimestamp :: Timestamp -- | Median of minTimestamp and maxTimestamp. Useful for -- testing (exactly half of generated dates will be before and after this -- date). midTimestamp :: Timestamp -- | Remembers parameters it was called with, last goes first. contractConsumer :: Contract cp [cp]