packages feed

morley 1.5.0 → 1.6.0

raw patch · 31 files changed

+618/−111 lines, 31 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Michelson.Doc: instance Util.Markdown.ToAnchor (Michelson.Doc.DocItemRef 'Michelson.Doc.DocItemInDefinitions)
- Michelson.Runtime.TxData: instance Data.Aeson.Types.FromJSON.FromJSON Michelson.Runtime.TxData.TxData
- Michelson.Runtime.TxData: instance GHC.Classes.Eq Michelson.Runtime.TxData.TxData
- Michelson.Typed.Arith: data ArithErrorType
- Michelson.Typed.Arith: instance Control.DeepSeq.NFData Michelson.Typed.Arith.ArithErrorType
- Michelson.Typed.Arith: instance Formatting.Buildable.Buildable Michelson.Typed.Arith.ArithErrorType
- Michelson.Typed.Arith: instance GHC.Classes.Eq Michelson.Typed.Arith.ArithErrorType
- Michelson.Typed.Arith: instance GHC.Classes.Ord Michelson.Typed.Arith.ArithErrorType
- Michelson.Typed.Arith: instance GHC.Generics.Generic Michelson.Typed.Arith.ArithErrorType
- Michelson.Typed.Arith: instance GHC.Show.Show Michelson.Typed.Arith.ArithErrorType
- Michelson.Typed.Instr: [PAIR] :: Instr (a : (b : s)) ('TPair a b : s)
- Michelson.Untyped.Entrypoints: instance Data.Default.Class.Default Michelson.Untyped.Entrypoints.EpName
+ Michelson.Doc: DToc :: Markdown -> DToc
+ Michelson.Doc: DocItemPos :: (Natural, Text) -> DocItemPos
+ Michelson.Doc: [DocItemRefInlined] :: DocItemId -> DocItemRef 'DocItemInlined 'True
+ Michelson.Doc: contractDocToToc :: ContractDoc -> Markdown
+ Michelson.Doc: data DToc
+ Michelson.Doc: docItemToToc :: DocItem d => HeaderLevel -> d -> Markdown
+ Michelson.Doc: instance Michelson.Doc.DocItem Michelson.Doc.DToc
+ Michelson.Doc: instance Util.Markdown.ToAnchor (Michelson.Doc.DocItemRef d 'GHC.Types.True)
+ Michelson.Doc: mdTocFromRef :: (DocItem d, DocItemReferenced d ~ 'True) => HeaderLevel -> Markdown -> d -> Markdown
+ Michelson.Doc: newtype DocItemPos
+ Michelson.Doc: type DocItemReferenced d = 'False;
+ Michelson.Doc: type DocItemReferencedKind = Bool
+ Michelson.Interpret.Pack: packValuePrefix :: IsString s => s
+ Michelson.Parser: MultiRootAnnotationException :: CustomParserException
+ Michelson.Parser.Error: MultiRootAnnotationException :: CustomParserException
+ Michelson.Runtime: EEUnexpectedParameterType :: T -> T -> ExecutorError' a
+ Michelson.Runtime: [TxTypedParam] :: forall t. ParameterScope t => Value t -> TxParam
+ Michelson.Runtime: [TxUntypedParam] :: Value -> TxParam
+ Michelson.Runtime: data TxParam
+ Michelson.Runtime.TxData: [TxTypedParam] :: forall t. ParameterScope t => Value t -> TxParam
+ Michelson.Runtime.TxData: [TxUntypedParam] :: Value -> TxParam
+ Michelson.Runtime.TxData: data TxParam
+ Michelson.Runtime.TxData: instance Data.Aeson.Types.ToJSON.ToJSON Michelson.Runtime.TxData.TxParam
+ Michelson.Runtime.TxData: instance GHC.Show.Show Michelson.Runtime.TxData.TxParam
+ Michelson.Typed.Arith: commutativityProof :: ArithOp aop n m => Maybe $ Dict (ArithRes aop n m ~ ArithRes aop m n, ArithOp aop m n)
+ Michelson.Typed.Arith: data MutezArithErrorType
+ Michelson.Typed.Arith: data ShiftArithErrorType
+ Michelson.Typed.Arith: instance Control.DeepSeq.NFData Michelson.Typed.Arith.MutezArithErrorType
+ Michelson.Typed.Arith: instance Control.DeepSeq.NFData Michelson.Typed.Arith.ShiftArithErrorType
+ Michelson.Typed.Arith: instance Formatting.Buildable.Buildable Michelson.Typed.Arith.MutezArithErrorType
+ Michelson.Typed.Arith: instance Formatting.Buildable.Buildable Michelson.Typed.Arith.ShiftArithErrorType
+ Michelson.Typed.Arith: instance GHC.Classes.Eq Michelson.Typed.Arith.MutezArithErrorType
+ Michelson.Typed.Arith: instance GHC.Classes.Eq Michelson.Typed.Arith.ShiftArithErrorType
+ Michelson.Typed.Arith: instance GHC.Classes.Ord Michelson.Typed.Arith.MutezArithErrorType
+ Michelson.Typed.Arith: instance GHC.Classes.Ord Michelson.Typed.Arith.ShiftArithErrorType
+ Michelson.Typed.Arith: instance GHC.Generics.Generic Michelson.Typed.Arith.MutezArithErrorType
+ Michelson.Typed.Arith: instance GHC.Generics.Generic Michelson.Typed.Arith.ShiftArithErrorType
+ Michelson.Typed.Arith: instance GHC.Show.Show Michelson.Typed.Arith.MutezArithErrorType
+ Michelson.Typed.Arith: instance GHC.Show.Show Michelson.Typed.Arith.ShiftArithErrorType
+ Michelson.Typed.Convert: sampleValueFromUntype :: HasCallStack => Type -> Value' ExpandedOp
+ Michelson.Typed.Haskell.Doc: instance GHC.Classes.Eq Michelson.Typed.Haskell.Doc.DStorageType
+ Michelson.Typed.Haskell.Doc: instance GHC.Classes.Ord Michelson.Typed.Haskell.Doc.DStorageType
+ Michelson.Typed.Instr: [AnnPAIR] :: TypeAnn -> FieldAnn -> FieldAnn -> Instr (a : (b : s)) ('TPair a b : s)
+ Michelson.Typed.Instr: [WithLoc] :: InstrCallStack -> Instr a b -> Instr a b
+ Michelson.Untyped.Entrypoints: epNameFromSelfAnn :: FieldAnn -> EpName
+ Michelson.Untyped.Entrypoints: isDefEpName :: EpName -> Bool
+ Tezos.Crypto: formatSecretKey :: SecretKey -> Text
+ Tezos.Crypto: instance Formatting.Buildable.Buildable Tezos.Crypto.SecretKey
+ Tezos.Crypto: parseSecretKey :: Text -> Either CryptoParseError SecretKey
+ Tezos.Crypto.P256: formatSecretKey :: SecretKey -> Text
+ Tezos.Crypto.P256: instance Formatting.Buildable.Buildable Tezos.Crypto.P256.SecretKey
+ Tezos.Crypto.P256: parseSecretKey :: Text -> Either CryptoParseError SecretKey
+ Tezos.Crypto.Secp256k1: formatSecretKey :: SecretKey -> Text
+ Tezos.Crypto.Secp256k1: instance Formatting.Buildable.Buildable Tezos.Crypto.Secp256k1.SecretKey
+ Tezos.Crypto.Secp256k1: parseSecretKey :: Text -> Either CryptoParseError SecretKey
+ Tezos.Crypto.Util: mkSecretKey_ :: ByteArray ba => Curve -> ba -> KeyPair
+ Tezos.Crypto.Util: secretKeyToBytes_ :: ByteArray ba => KeyPair -> ba
+ Util.Markdown: mdEscapeAnchor :: ToAnchor anchor => anchor -> Markdown
+ Util.Markdown: mdToc :: ToAnchor anchor => HeaderLevel -> Markdown -> anchor -> Markdown
- Michelson.Doc: [DocItemNoRef] :: DocItemRef 'DocItemInlined
+ Michelson.Doc: [DocItemNoRef] :: DocItemRef 'DocItemInlined 'False
- Michelson.Doc: [DocItemRef] :: DocItemId -> DocItemRef 'DocItemInDefinitions
+ Michelson.Doc: [DocItemRef] :: DocItemId -> DocItemRef 'DocItemInDefinitions 'True
- Michelson.Doc: data DocItemRef (p :: DocItemPlacementKind)
+ Michelson.Doc: data DocItemRef (p :: DocItemPlacementKind) (r :: DocItemReferencedKind)
- Michelson.Doc: docItemRef :: (DocItem d, DocItemPlacement d ~ 'DocItemInlined) => d -> DocItemRef (DocItemPlacement d)
+ Michelson.Doc: docItemRef :: (DocItem d, DocItemPlacement d ~ 'DocItemInlined, DocItemReferenced d ~ 'False) => d -> DocItemRef (DocItemPlacement d) (DocItemReferenced d)
- Michelson.Doc: type family DocItemPlacement d :: DocItemPlacementKind;
+ Michelson.Doc: type family DocItemReferenced d :: DocItemReferencedKind;
- Michelson.Runtime: TxData :: Address -> Value -> EpName -> Mutez -> TxData
+ Michelson.Runtime: TxData :: Address -> TxParam -> EpName -> Mutez -> TxData
- Michelson.Runtime: [tdParameter] :: TxData -> Value
+ Michelson.Runtime: [tdParameter] :: TxData -> TxParam
- Michelson.Runtime.TxData: TxData :: Address -> Value -> EpName -> Mutez -> TxData
+ Michelson.Runtime.TxData: TxData :: Address -> TxParam -> EpName -> Mutez -> TxData
- Michelson.Runtime.TxData: [tdParameter] :: TxData -> Value
+ Michelson.Runtime.TxData: [tdParameter] :: TxData -> TxParam
- Michelson.Runtime.TxData: tdParameterL :: Lens' TxData Value
+ Michelson.Runtime.TxData: tdParameterL :: Lens' TxData TxParam
- Michelson.Typed.Arith: AddOverflow :: ArithErrorType
+ Michelson.Typed.Arith: AddOverflow :: MutezArithErrorType
- Michelson.Typed.Arith: LslOverflow :: ArithErrorType
+ Michelson.Typed.Arith: LslOverflow :: ShiftArithErrorType
- Michelson.Typed.Arith: LsrUnderflow :: ArithErrorType
+ Michelson.Typed.Arith: LsrUnderflow :: ShiftArithErrorType
- Michelson.Typed.Arith: MulOverflow :: ArithErrorType
+ Michelson.Typed.Arith: MulOverflow :: MutezArithErrorType
- Michelson.Typed.Arith: MutezArithError :: ArithErrorType -> n -> m -> ArithError n m
+ Michelson.Typed.Arith: MutezArithError :: MutezArithErrorType -> n -> m -> ArithError n m
- Michelson.Typed.Arith: ShiftArithError :: ArithErrorType -> n -> m -> ArithError n m
+ Michelson.Typed.Arith: ShiftArithError :: ShiftArithErrorType -> n -> m -> ArithError n m
- Michelson.Typed.Arith: SubUnderflow :: ArithErrorType
+ Michelson.Typed.Arith: SubUnderflow :: MutezArithErrorType
- Michelson.Typed.Haskell: crDescriptionL :: forall a_a6ys3. Lens' (ConstructorRep a_a6ys3) (Maybe Text)
+ Michelson.Typed.Haskell: crDescriptionL :: forall a_a6wvr. Lens' (ConstructorRep a_a6wvr) (Maybe Text)
- Michelson.Typed.Haskell: crFieldsL :: forall a_a6ys3 a_a6ytl. Lens (ConstructorRep a_a6ys3) (ConstructorRep a_a6ytl) [FieldRep a_a6ys3] [FieldRep a_a6ytl]
+ Michelson.Typed.Haskell: crFieldsL :: forall a_a6wvr a_a6wwJ. Lens (ConstructorRep a_a6wvr) (ConstructorRep a_a6wwJ) [FieldRep a_a6wvr] [FieldRep a_a6wwJ]
- Michelson.Typed.Haskell: crNameL :: forall a_a6ys3. Lens' (ConstructorRep a_a6ys3) Text
+ Michelson.Typed.Haskell: crNameL :: forall a_a6wvr. Lens' (ConstructorRep a_a6wvr) Text
- Michelson.Typed.Haskell: frDescriptionL :: forall a_a6ys2. Lens' (FieldRep a_a6ys2) (Maybe Text)
+ Michelson.Typed.Haskell: frDescriptionL :: forall a_a6wvq. Lens' (FieldRep a_a6wvq) (Maybe Text)
- Michelson.Typed.Haskell: frNameL :: forall a_a6ys2. Lens' (FieldRep a_a6ys2) (Maybe Text)
+ Michelson.Typed.Haskell: frNameL :: forall a_a6wvq. Lens' (FieldRep a_a6wvq) (Maybe Text)
- Michelson.Typed.Haskell: frTypeRepL :: forall a_a6ys2 a_a6yv6. Lens (FieldRep a_a6ys2) (FieldRep a_a6yv6) a_a6ys2 a_a6yv6
+ Michelson.Typed.Haskell: frTypeRepL :: forall a_a6wvq a_a6wyu. Lens (FieldRep a_a6wvq) (FieldRep a_a6wyu) a_a6wvq a_a6wyu
- Michelson.Typed.Haskell.Doc: crDescriptionL :: forall a_a6ys3. Lens' (ConstructorRep a_a6ys3) (Maybe Text)
+ Michelson.Typed.Haskell.Doc: crDescriptionL :: forall a_a6wvr. Lens' (ConstructorRep a_a6wvr) (Maybe Text)
- Michelson.Typed.Haskell.Doc: crFieldsL :: forall a_a6ys3 a_a6ytl. Lens (ConstructorRep a_a6ys3) (ConstructorRep a_a6ytl) [FieldRep a_a6ys3] [FieldRep a_a6ytl]
+ Michelson.Typed.Haskell.Doc: crFieldsL :: forall a_a6wvr a_a6wwJ. Lens (ConstructorRep a_a6wvr) (ConstructorRep a_a6wwJ) [FieldRep a_a6wvr] [FieldRep a_a6wwJ]
- Michelson.Typed.Haskell.Doc: crNameL :: forall a_a6ys3. Lens' (ConstructorRep a_a6ys3) Text
+ Michelson.Typed.Haskell.Doc: crNameL :: forall a_a6wvr. Lens' (ConstructorRep a_a6wvr) Text
- Michelson.Typed.Haskell.Doc: frDescriptionL :: forall a_a6ys2. Lens' (FieldRep a_a6ys2) (Maybe Text)
+ Michelson.Typed.Haskell.Doc: frDescriptionL :: forall a_a6wvq. Lens' (FieldRep a_a6wvq) (Maybe Text)
- Michelson.Typed.Haskell.Doc: frNameL :: forall a_a6ys2. Lens' (FieldRep a_a6ys2) (Maybe Text)
+ Michelson.Typed.Haskell.Doc: frNameL :: forall a_a6wvq. Lens' (FieldRep a_a6wvq) (Maybe Text)
- Michelson.Typed.Haskell.Doc: frTypeRepL :: forall a_a6ys2 a_a6yv6. Lens (FieldRep a_a6ys2) (FieldRep a_a6yv6) a_a6ys2 a_a6yv6
+ Michelson.Typed.Haskell.Doc: frTypeRepL :: forall a_a6wvq a_a6wyu. Lens (FieldRep a_a6wvq) (FieldRep a_a6wyu) a_a6wvq a_a6wyu
- Michelson.Untyped.Entrypoints: unsafeBuildEpName :: Text -> EpName
+ Michelson.Untyped.Entrypoints: unsafeBuildEpName :: HasCallStack => Text -> EpName

Files

CHANGES.md view
@@ -1,3 +1,17 @@+1.6.0+=====+* [!323](https://gitlab.com/morley-framework/morley/-/merge_requests/323)+  Add `parseSecretKey` which allows parsing all types of `SecretKey`.+* [!537](https://gitlab.com/morley-framework/morley/-/merge_requests/537)+  Permit `SELF %default` instruction.+* [!522](https://gitlab.com/morley-framework/morley/-/merge_requests/522)+  + allow calling the interpreter with a typed transfer parameter and+  avoid unnecessary typechecking.+* [!495](https://gitlab.com/morley-framework/morley/-/merge_requests/495)+  Add source location to typed `Instr` AST.+* [!521](https://gitlab.com/morley-framework/morley/-/merge_requests/521)+  Document generater can now generate table of contents.+ 1.5.0 ===== * [!509](https://gitlab.com/morley-framework/morley/-/merge_requests/509)
morley.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: baa867af7f9b3c6cbf4de3c7d9746427b24b2cca6f9c9cb9025ad098b40ef60e+-- hash: e9b0b7602aa9e3fa21558643cd50b0071708c46a024ce35930b662fbec21b73e  name:           morley-version:        1.5.0+version:        1.6.0 synopsis:       Developer tools for the Michelson Language description:    A library to make writing smart contracts in Michelson — the smart contract language of the Tezos blockchain — pleasant and effective. category:       Language
src/Michelson/Doc.hs view
@@ -11,7 +11,9 @@   , docItemPosition   , DocItemId (..)   , DocItemPlacementKind (..)+  , DocItemPos (..)   , DocItemRef (..)+  , DocItemReferencedKind   , DocSectionNameStyle (..)   , SomeDocItem (..)   , SomeDocDefinitionItem (..)@@ -30,8 +32,10 @@   , docItemToBlock   , lookupDocBlockSection   , contractDocToMarkdown+  , contractDocToToc   , docGroupContent   , docDefinitionRef+  , mdTocFromRef    , DGeneralInfoSection (..)   , DName (..)@@ -42,8 +46,11 @@   , morleyRepoSettings   , DComment (..)   , DAnchor (..)+  , DToc (..)   ) where +import Control.Lens.Cons (_head)+import Data.Char (toLower) import qualified Data.Map as M import qualified Data.Map.Merge.Strict as M import qualified Data.Set as S@@ -123,15 +130,20 @@   type DocItemPlacement d :: DocItemPlacementKind   type DocItemPlacement d = 'DocItemInlined +  type DocItemReferenced d :: DocItemReferencedKind+  type DocItemReferenced d = 'False+   -- | 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 :: d -> DocItemRef (DocItemPlacement d)+  docItemRef :: d -> DocItemRef (DocItemPlacement d) (DocItemReferenced d)   default docItemRef-    :: (DocItemPlacement d ~ 'DocItemInlined)-    => d -> DocItemRef (DocItemPlacement d)+    :: ( DocItemPlacement d ~ 'DocItemInlined+       , DocItemReferenced d ~ 'False+       )+    => d -> DocItemRef (DocItemPlacement d) (DocItemReferenced d)   docItemRef _ = DocItemNoRef    -- | Render given doc item to Markdown, preferably one line,@@ -142,6 +154,10 @@   -- headers thus delivering mess).   docItemToMarkdown :: HeaderLevel -> d -> Markdown +  -- | Render table of contents entry for given doc item to Markdown.+  docItemToToc :: HeaderLevel -> d -> Markdown+  docItemToToc _ _ = ""+   -- | All doc items which this doc item refers to.   --   -- They will automatically be put to definitions as soon as given doc item@@ -161,8 +177,16 @@     [] -> []     docItems@(someDocItem : _) -> case docItemRef someDocItem of       DocItemNoRef -> docItems-      DocItemRef _ -> docItemsOrderById docItems+      DocItemRef _ ->+        docItemsOrderById docItems+      DocItemRefInlined _ ->+        docItems +-- | Generate 'DToc' entry anchor from 'docItemRef'.+mdTocFromRef :: (DocItem d, DocItemReferenced d ~ 'True) => HeaderLevel -> Markdown -> d -> Markdown+mdTocFromRef lvl text d =+  mdToc lvl text (toAnchor $ docItemRef d)+ -- | Get doc item position at term-level. docItemPosition :: forall d. DocItem d => DocItemPos docItemPosition = DocItemPos (docItemPos @d, show (typeRep $ Proxy @d))@@ -174,6 +198,7 @@   where     manchor = case docItemRef d of       DocItemRef docItemId -> mdAnchor docItemId+      DocItemRefInlined docItemId -> mdAnchor docItemId       DocItemNoRef -> ""  -- | Order items by their 'docItemId'.@@ -213,13 +238,17 @@   | DocItemInDefinitions     -- ^ Placed in dedicated definitions section; can later be referenced. --- | Defines an identifier which given doc item can be referenced with.-data DocItemRef (p :: DocItemPlacementKind) where-  DocItemRef :: DocItemId -> DocItemRef 'DocItemInDefinitions-  DocItemNoRef :: DocItemRef 'DocItemInlined+-- | Type-level check whether or not a doc item can be referenced.+type DocItemReferencedKind = Bool -instance ToAnchor (DocItemRef 'DocItemInDefinitions) where+data DocItemRef (p :: DocItemPlacementKind) (r :: DocItemReferencedKind) where+  DocItemRef        :: DocItemId -> DocItemRef 'DocItemInDefinitions 'True+  DocItemRefInlined :: DocItemId -> DocItemRef 'DocItemInlined 'True+  DocItemNoRef      :: DocItemRef 'DocItemInlined 'False++instance ToAnchor (DocItemRef d 'True) where   toAnchor (DocItemRef ref) = toAnchor ref+  toAnchor (DocItemRefInlined ref) = toAnchor ref  -- | How to render section name. data DocSectionNameStyle@@ -342,6 +371,24 @@        then ""        else sectionNameFull <> sectionDescFull <> content +-- | Render a part of table of contents from 'DocBlock'.+docBlockToToc :: HeaderLevel -> DocBlock -> Markdown+docBlockToToc hl block =+  mconcat $ M.elems block <&> \(DocSection items@((_ :: DocElem di) :| _)) ->+    let sectionName = docItemSectionName @di+        (sectionNameFull, headerLevelDelta) =+          case sectionName of+            Nothing -> ("", id)+            Just "Table of contents" -> ("", id)+            Just sn ->+              (mdToc hl (build sn) (over _head toLower $ sn), nextHeaderLevel)+        resItems = docItemsOrder $ map deItem (toList items)+        content =+          mconcat $ resItems <&> docItemToToc (headerLevelDelta hl)+    in if null resItems+       then ""+       else sectionNameFull <> content+ -- | Lift a doc item to a block, be it atomic doc item or grouping one. docItemToBlockGeneral :: forall di. DocItem di => di -> Maybe SubDoc -> DocBlock docItemToBlockGeneral di msub =@@ -372,6 +419,10 @@ subDocToMarkdown :: HeaderLevel -> SubDoc -> Markdown subDocToMarkdown hl (SubDoc d) = docBlockToMarkdown hl d +-- | Render documentation for 'SubDoc'.+subDocToToc :: HeaderLevel -> SubDoc -> Markdown+subDocToToc hl (SubDoc d) = docBlockToToc hl d+ -- | Keeps documentation gathered for some piece of contract code. -- -- Used for building documentation of a contract.@@ -426,6 +477,7 @@         case docItemRef di of           DocItemNoRef -> False           DocItemRef docItemId -> docItemId `S.member` defs+          DocItemRefInlined docItemId -> docItemId `S.member` defs  instance Monoid ContractDoc where   mempty = ContractDoc@@ -448,6 +500,18 @@     total = fmt (contents <> definitions)   in LT.strip total <> "\n" +contractDocToToc :: ContractDoc -> Markdown+contractDocToToc ContractDoc{..} =+  let+    contents =+      docBlockToToc (HeaderLevel 1) cdContents++    definitions+      | null cdDefinitions = ""+      | otherwise = "\n**[Definitions](#definitions)**\n\n"+          +| docBlockToToc (HeaderLevel 2) cdDefinitions+  in contents <> definitions <> "\n"+ -- | A function which groups a piece of doc under one doc item. type DocGrouping = SubDoc -> SomeDocItem @@ -479,6 +543,8 @@   docItemSectionName = Nothing   docItemToMarkdown lvl (DGeneralInfoSection subDoc) =     subDocToMarkdown lvl subDoc+  docItemToToc lvl (DGeneralInfoSection subDoc) =+    subDocToToc lvl subDoc  -- | Give a name to document block. data DName = DName Text SubDoc@@ -489,6 +555,8 @@   docItemToMarkdown lvl (DName name doc) =     mdHeader lvl (build name) <>     subDocToMarkdown (nextHeaderLevel lvl) doc+  docItemToToc lvl (DName _ doc) =+    subDocToToc (nextHeaderLevel lvl) doc  -- | Description of something. data DDescription = DDescription Markdown@@ -577,6 +645,18 @@   docItemSectionName = Nothing   docItemToMarkdown _ (DComment commentText) =     "<!---\n" +| commentText |+ "\n-->"++-- | @Table of contents@ to be inserted into the doc in an ad-hoc way.+--+-- It is not intended to be inserted manually. See 'attachToc' to understand+-- how this works.+--+data DToc = DToc Markdown++instance DocItem DToc where+  docItemPos = 11+  docItemSectionName = Just "Table of contents"+  docItemToMarkdown _ (DToc toc) = toc  -- | A hand-made anchor. data DAnchor = DAnchor Anchor
src/Michelson/Interpret.hs view
@@ -331,6 +331,7 @@ -- | Function to interpret Michelson instruction(s) against given stack. runInstrImpl :: EvalM m => InstrRunner m -> InstrRunner m runInstrImpl runner (Seq i1 i2) r = runner i1 r >>= \r' -> runner i2 r'+runInstrImpl runner (WithLoc _ i) r = runInstrImpl runner i r runInstrImpl runner (InstrWithNotes _ i) r = runner i r runInstrImpl runner (InstrWithVarNotes _ i) r = runner i r runInstrImpl runner (FrameInstr (_ :: Proxy s) i) r = do@@ -381,7 +382,7 @@ runInstrImpl _ UNIT r = pure $ VUnit :& r runInstrImpl runner (IF_NONE _bNone bJust) (VOption (Just a) :& r) = runner bJust (a :& r) runInstrImpl runner (IF_NONE bNone _bJust) (VOption Nothing :& r) = runner bNone r-runInstrImpl _ PAIR (a :& b :& r) = pure $ VPair (a, b) :& r+runInstrImpl _ (AnnPAIR{}) (a :& b :& r) = pure $ VPair (a, b) :& r runInstrImpl _ (AnnCAR _) (VPair (a, _b) :& r) = pure $ a :& r runInstrImpl _ (AnnCDR _) (VPair (_a, b) :& r) = pure $ b :& r runInstrImpl _ LEFT (a :& r) =@@ -541,7 +542,7 @@               -- context, therefore we generate dummy contract address with its own origination               -- operation and counter set to 0.               originationNonce-  let resEpAddr = EpAddress resAddr def+  let resEpAddr = EpAddress resAddr DefEpName   let resOp = CreateContract originator (unwrapMbKeyHash mbKeyHash) m g ops   pure $ VOp (OpCreateContract resOp)       :& (VAddress resEpAddr)@@ -565,10 +566,10 @@ runInstrImpl _ HASH_KEY (VKey k :& r) = pure $ (VKeyHash $ hashKey k) :& r runInstrImpl _ SOURCE r = do   ContractEnv{..} <- ask-  pure $ (VAddress $ EpAddress ceSource def) :& r+  pure $ (VAddress $ EpAddress ceSource DefEpName) :& r runInstrImpl _ SENDER r = do   ContractEnv{..} <- ask-  pure $ (VAddress $ EpAddress ceSender def) :& r+  pure $ (VAddress $ EpAddress ceSender DefEpName) :& r runInstrImpl _ ADDRESS (VContract a sepc :& r) =   pure $ (VAddress $ EpAddress a (sepcName sepc)) :& r runInstrImpl _ CHAIN_ID r = do
src/Michelson/Interpret/Pack.hs view
@@ -10,6 +10,7 @@   , packT'   , packValue   , packValue'+  , packValuePrefix     -- * Serializers used in morley-client   , encodeValue'   , packNotedT'@@ -39,9 +40,13 @@ import qualified Tezos.Crypto.Secp256k1 as Secp256k1 import Util.Peano (peanoValSing) +-- | Prefix prepended to the binary representation of a value.+packValuePrefix :: IsString s => s+packValuePrefix = "\x05"+ -- | Serialize a value given to @PACK@ instruction. packValue :: PackedValScope t => Value t -> LByteString-packValue x = "\x05" <> encodeValue x+packValue x = packValuePrefix <> encodeValue x  -- | Same as 'packValue', for strict bytestring. packValue' :: PackedValScope t => Value t -> ByteString@@ -191,6 +196,8 @@ -- | Encode an instruction. encodeInstr :: forall inp out. Instr inp out -> LByteString encodeInstr = \case+  WithLoc _ i ->+    encodeInstr i   InstrWithNotes n a ->     encodeNotedInstr a n []   InstrWithVarNotes varNotes a ->@@ -229,8 +236,8 @@     "\x03\x4f"   IF_NONE a b ->     "\x07\x2f" <> encodeInstrs a <> encodeInstrs b-  PAIR ->-    "\x03\x42"+  AnnPAIR tn fn1 fn2 ->+    encodeWithAnns [tn] [fn1, fn2] [] "\x03\x42"   (AnnCAR fn) ->     encodeWithAnns [] [fn] [] "\x03\x16"   (AnnCDR fn) ->@@ -407,14 +414,14 @@ encodeNotedInstr   :: forall inp out. Instr inp out -> PackedNotes out -> [VarAnn] -> LByteString encodeNotedInstr a (PackedNotes n) vns = case (a, Proxy @out, n) of+  (WithLoc _ a0, _, _) ->+    encodeNotedInstr a0 (PackedNotes n) vns   (SOME, _, NTOption tn _ns) ->     encodeWithAnns [tn] [] vns $ encodeInstr a   (NONE, _ :: Proxy ('TOption t ': s), NTOption tn ns) ->     encodeWithAnns [tn] [] vns $ "\x05\x3e" <> encodeNotedT' @t ns   (UNIT, _, NTUnit tn) ->     encodeWithAnns [tn] [] vns $ encodeInstr a-  (PAIR, _, NTPair tn fn1 fn2 _ns1 _ns2) ->-    encodeWithAnns [tn] [fn1, fn2] vns $ encodeInstr a   (LEFT, _ :: Proxy ('TOr l r ': s), NTOr tn fn1 fn2 _ns1 ns2) ->     encodeWithAnns [tn] [fn1, fn2] vns $ "\x05\x33" <> encodeNotedT' @r ns2   (RIGHT, _ :: Proxy ('TOr l r ': s), NTOr tn fn1 fn2 ns1 _ns2) ->
src/Michelson/Interpret/Unpack.hs view
@@ -238,9 +238,14 @@       ( decodeWithTag "key_hash" keyHashDecoders       , parseKeyHash       )-    STTimestamp -> do-      expectTag "Timestamp" 0x00-      T.VTimestamp . timestampFromSeconds <$> decodeInt+    STTimestamp -> Get.label "Timestamp" $ Get.getWord8 >>= \case+      0x00 -> do+        T.VTimestamp . timestampFromSeconds <$> decodeInt+      0x01 -> do+        str <- decodeString+        maybe (fail $ toString $ "failed to parse timestamp from " <> unMText str)+          (pure . T.VTimestamp) $ parseTimestamp $ unMText str+      other -> unknownTag "int or string" other     STAddress ->       T.VAddress <$> decodeAsBytesOrString       ( decodeBytesLike "EpAddress" parseEpAddressRaw
src/Michelson/Optimizer.hs view
@@ -24,11 +24,13 @@  import Prelude hiding (EQ) +import Data.Constraint (Dict(..)) import Data.Default (Default(def)) import Data.Singletons (sing)  import Michelson.Interpret.Pack (packValue') import Michelson.Typed.Aliases (Value)+import Michelson.Typed.Arith import Michelson.Typed.Instr import Michelson.Typed.Scope (PackedValScope) import Michelson.Typed.Sing@@ -95,8 +97,10 @@     `orSimpleRule` internalNop     `orSimpleRule` simpleDips     `orSimpleRule` adjacentDips+    `orSimpleRule` adjacentDrops     `orSimpleRule` specificPush     `orSimpleRule` pairUnpair+    `orSimpleRule` swapBeforeCommutative  -- | We do not enable 'pushPack' rule by default because it is -- potentially dangerous.@@ -264,9 +268,24 @@ adjacentDips :: Rule adjacentDips = \case   Seq (DIP f) (DIP g) -> Just (DIP (Seq f g))+  Seq (DIP f) (Seq (DIP g) c) -> Just (DIP (Seq f g) `Seq` c)    _ -> Nothing +-- TODO (#299): optimize sequences of more than 2 DROPs.+-- | Sequences of @DROP@s can be turned into single @DROP n@.+-- When @n@ is greater than 2 it saves size and gas.+-- When @n@ is 2 it saves gas only.+adjacentDrops :: Rule+adjacentDrops = \case+  Seq DROP DROP -> Just (DROPN (SS $ SS SZ))+  Seq DROP (Seq DROP c) -> Just (DROPN (SS $ SS SZ) `Seq` c)++  -- Does not compile, need to do something smart+  -- Seq (DROPN (SS (SS SZ))) DROP -> Just (DROPN (SS $ SS $ SS SZ))++  _ -> Nothing+ specificPush :: Rule specificPush = \case   push@PUSH{} -> optimizePush push@@ -300,6 +319,23 @@    UNPAIR_c (Seq PAIR c) -> Just c   UNPAIR_c      PAIR    -> Just Nop++  _ -> Nothing++commuteArith ::+  forall n m s out. Instr (n ': m ': s) out -> Maybe (Instr (m ': n ': s) out)+commuteArith = \case+  ADD -> do Dict <- commutativityProof @Add @n @m; Just ADD+  MUL -> do Dict <- commutativityProof @Mul @n @m; Just MUL+  OR -> do Dict <- commutativityProof @Or @n @m; Just OR+  AND -> do Dict <- commutativityProof @And @n @m; Just AND+  XOR -> do Dict <- commutativityProof @Xor @n @m; Just XOR+  _ -> Nothing++swapBeforeCommutative :: Rule+swapBeforeCommutative = \case+  Seq SWAP (Seq i c) -> (`Seq` c) <$> commuteArith i+  Seq SWAP i -> commuteArith i    _ -> Nothing 
src/Michelson/Parser.hs view
@@ -43,12 +43,13 @@ import Prelude hiding (try)  import qualified Language.Haskell.TH.Quote as TH-import Text.Megaparsec-  (Parsec, choice, eitherP, eof, errorBundlePretty, getSourcePos, lookAhead, parse, try)+import Text.Megaparsec (Parsec, choice, customFailure, eitherP, eof, errorBundlePretty,+  getSourcePos, lookAhead, parse, try) import Text.Megaparsec.Pos (SourcePos(..), unPos)  import Michelson.ErrorPos (SrcPos(..), mkPos) import Michelson.Macro (LetMacro, Macro(..), ParsedInstr, ParsedOp(..), ParsedValue, expandValue)+import Michelson.Parser.Annotations (noteF) import Michelson.Parser.Error import Michelson.Parser.Ext import Michelson.Parser.Instr@@ -92,8 +93,17 @@  cbParameter :: Parser ParameterType cbParameter = do-  (fieldAnn, t) <- symbol "parameter" *> field-  pure $ ParameterType t (convAnn fieldAnn)+  symbol "parameter"+  prefixRootAnn <- optional noteF+  (inTypeRootAnn, t) <- field+  rootAnn <- case (prefixRootAnn, inTypeRootAnn) of+    -- TODO: [#310] Handle cases where there are 2 empty root annotations.+    -- For example: root % (unit %) which should throw the error.+    (Just "", "") -> pure noAnn+    (Just a, "") -> pure a+    (Nothing, b) -> pure b+    (Just _, _) -> customFailure MultiRootAnnotationException+  pure $ ParameterType t (convAnn rootAnn)  cbStorage :: Parser Type cbStorage = symbol "storage" *> type_
src/Michelson/Parser/Error.hs view
@@ -28,6 +28,7 @@   | WrongAccessArgs Natural Positive   | WrongSetArgs Natural Positive   | ExcessFieldAnnotation+  | MultiRootAnnotationException   deriving stock (Eq, Data, Ord, Show, Generic)  instance NFData CustomParserException@@ -37,6 +38,7 @@   showErrorComponent (StringLiteralException e) = showErrorComponent e   showErrorComponent OddNumberBytesException = "odd number bytes"   showErrorComponent ExcessFieldAnnotation = "excess field annotation"+  showErrorComponent MultiRootAnnotationException = "unexpected multiple root annotations"   showErrorComponent (WrongTagArgs idx size) =     "TAG: too large index: " +| idx |+ " \            \exceedes union size " +| size |+ ""
src/Michelson/Runtime.hs view
@@ -21,6 +21,7 @@   , ContractState (..)   , AddressState (..)   , TxData (..)+  , TxParam (..)    -- * For testing   , ExecutorOp (..)@@ -55,6 +56,8 @@ import Named ((:!), (:?), arg, argDef, defaults, (!)) import Text.Megaparsec (parse) +import Data.Singletons (demote)+import Data.Typeable (gcast) import Michelson.Interpret   (ContractEnv(..), InterpretError(..), InterpretResult(..), InterpreterState(..), MorleyLogs(..),   RemainingSteps(..), handleContractReturn, interpret)@@ -64,7 +67,7 @@ import Michelson.Runtime.TxData import Michelson.TypeCheck (TCError, typeVerifyParameter) import Michelson.Typed-  (CreateContract(..), EpName, Operation'(..), SomeValue'(..), TransferTokens(..),+  (CreateContract(..), EntrypointCallT, EpName, Operation'(..), SomeValue'(..), TransferTokens(..),   convertContractCode, untypeValue) import qualified Michelson.Typed as T import Michelson.Untyped@@ -164,6 +167,9 @@   -- ^ Contract storage is ill-typed.   | EEIllTypedParameter !TCError   -- ^ Contract parameter is ill-typed.+  | EEUnexpectedParameterType T.T T.T+  -- ^ Contract parameter is well-typed, but its type does+  -- not match the entrypoint's type.   | EEUnknownEntrypoint EpName   -- ^ Specified entrypoint to run is not found.   deriving stock (Show, Functor)@@ -188,6 +194,10 @@       EEIllTypedContract err -> "The contract is ill-typed: " +| err |+ ""       EEIllTypedStorage err -> "The contract storage is ill-typed: " +| err |+ ""       EEIllTypedParameter err -> "The contract parameter is ill-typed: " +| err |+ ""+      EEUnexpectedParameterType expectedT actualT ->+        "The contract parameter is well-typed, but did not match the contract's entrypoint's type.\n" <>+        "Expected: " +| expectedT |+ "\n" <>+        "Got: " +| actualT |+ ""       EEUnknownEntrypoint epName -> "The contract does not contain entrypoint '" +| epName |+ "'"  type ExecutorError = ExecutorError' Address@@ -529,11 +539,23 @@             }           epName = tdEntrypoint txData -        T.MkEntrypointCallRes _ epc+        T.MkEntrypointCallRes _ (epc :: EntrypointCallT cp epArg)           <- T.mkEntrypointCall epName (T.cParamNotes csContract)              & maybe (throwError $ EEUnknownEntrypoint epName) pure-        typedParameter <- liftEither $ first EEIllTypedParameter $-           typeVerifyParameter existingContracts (tdParameter txData)++        -- If the parameter has already been typechecked, simply check if+        -- its type matches the contract's entrypoint's type.+        -- Otherwise (e.g. if it was parsed from stdin via the CLI),+        -- we need to typecheck the parameter.+        typedParameter <-+          case tdParameter txData of+            TxTypedParam (typedVal :: T.Value t) ->+              maybe (throwError $ EEUnexpectedParameterType (demote @epArg) (demote @t)) pure $+                gcast @t @epArg typedVal+            TxUntypedParam untypedVal ->+              liftEither $ first EEIllTypedParameter $+                typeVerifyParameter @epArg existingContracts untypedVal+         iur@InterpretResult           { iurOps = sideEffects           , iurNewStorage = newValue@@ -597,7 +619,7 @@                 TxData                   { tdSenderAddress = interpretedAddr                   , tdEntrypoint = T.sepcName sepc-                  , tdParameter = untypeValue (ttTransferArgument tt)+                  , tdParameter = TxTypedParam (ttTransferArgument tt)                   , tdAmount = ttAmount tt                   }           in Just (TransferOp destAddress txData)
src/Michelson/Runtime/GState.hs view
@@ -117,9 +117,9 @@  instance Buildable ContractState where   build ContractState{..} =-    "Contractstate:\n csBalance: " +| csBalance |+-    "\n  csContract: " +| T.untypeValue csStorage ||+-    "\n  csStorage: " +| T.convertContract csContract ||+ ""+    "Contractstate:\n Balance: " +| csBalance |++    "\n  Storage: " +| T.untypeValue csStorage ||++    "\n  Contract: " +| T.convertContract csContract ||+ ""  -- | State of an arbitrary address. data AddressState@@ -159,9 +159,6 @@ makeLensesWith postfixLFields ''GState  deriveJSON morleyAesonOptions ''GState---  -- | Number of genesis addresses. genesisAddressesNum :: Word
src/Michelson/Runtime/TxData.hs view
@@ -6,6 +6,7 @@  module Michelson.Runtime.TxData        ( TxData (..)+       , TxParam(..)        , tdSenderAddressL        , tdParameterL        , tdEntrypointL@@ -13,21 +14,36 @@        ) where  import Control.Lens (makeLensesWith)-import Data.Aeson.TH (deriveJSON)+import Data.Aeson (ToJSON(toJSON))+import Data.Aeson.TH (deriveToJSON) -import Michelson.Untyped (EpName, Value)+import Michelson.Typed (ParameterScope)+import qualified Michelson.Typed as T+import Michelson.Untyped (EpName)+import qualified Michelson.Untyped as U import Tezos.Address (Address) import Tezos.Core (Mutez) import Util.Aeson (morleyAesonOptions) import Util.Lens (postfixLFields) +-- | A parameter associated with a particular transaction.+data TxParam where+  TxTypedParam :: forall t. ParameterScope t => T.Value t -> TxParam+  TxUntypedParam :: U.Value -> TxParam++deriving stock instance Show TxParam++instance ToJSON TxParam where+  toJSON (TxTypedParam val) = toJSON $ T.untypeValue val+  toJSON (TxUntypedParam val) = toJSON val+ -- | Data associated with a particular transaction. data TxData = TxData   { tdSenderAddress :: Address-  , tdParameter :: Value+  , tdParameter :: TxParam   , tdEntrypoint :: EpName   , tdAmount :: Mutez-  } deriving stock (Show, Eq)+  } deriving stock Show  makeLensesWith postfixLFields ''TxData-deriveJSON morleyAesonOptions ''TxData+deriveToJSON morleyAesonOptions ''TxData
src/Michelson/TypeCheck/Helpers.hs view
@@ -269,13 +269,19 @@     Un.SeqEx sq : rs                 -> typeCheckSeq Nothing sq rs     []                               -> pure $ a :/ Nop ::: a   where-    typeCheckPrim (Just cs) i [] = local (const cs) $ tcInstr i t-    typeCheckPrim (Just cs) i rs = local (const cs) $ typeCheckImplDo (tcInstr i t) id rs+    -- If we know source location from the untyped instruction, keep it in the typed one.+    typeCheckPrim (Just cs) i [] = local (const cs) $ (tcInstr i t <&> wrapWithLoc cs)+    typeCheckPrim (Just cs) i rs = local (const cs) $ typeCheckImplDo (tcInstr i t <&> wrapWithLoc cs) id rs     typeCheckPrim Nothing i [] = tcInstr i t     typeCheckPrim Nothing i rs = typeCheckImplDo (tcInstr i t) id rs      typeCheckSeq (Just cs) sq = local (const cs) . typeCheckImplDo (typeCheckImpl tcInstr sq t) Nested     typeCheckSeq Nothing sq = typeCheckImplDo (typeCheckImpl tcInstr sq t) Nested++    wrapWithLoc :: InstrCallStack -> SomeInstr inp -> SomeInstr inp+    wrapWithLoc _ si@(_ :/ (WithLoc _ _) ::: _) = si+    wrapWithLoc cs (inp :/ instr ::: out) = inp :/ WithLoc cs instr ::: out+    wrapWithLoc _ si = si      typeCheckImplDo       :: TypeCheckInstr (SomeInstr inp)
src/Michelson/TypeCheck/Instr.hs view
@@ -341,7 +341,8 @@   (U.PAIR tn vn pfn qfn, (an, _, avn) ::& (bn, _, bvn) ::& rs) -> do     let (vn', pfn', qfn') = deriveSpecialFNs pfn qfn avn bvn     case NTPair tn pfn' qfn' an bn of-      (ns :: Notes ('TPair a b)) -> withWTPInstr @('TPair a b) $ pure (inp :/ PAIR ::: ((ns, Dict, vn `orAnn` vn') ::& rs))+      (ns :: Notes ('TPair a b)) -> withWTPInstr @('TPair a b) $+        pure (inp :/ AnnPAIR tn pfn qfn ::: ((ns, Dict, vn `orAnn` vn') ::& rs))    (U.PAIR {}, _) -> notEnoughItemsOnStack @@ -918,8 +919,7 @@         TypeCheckValue (value, ty) ->           tcFailedOnValue value ty "The SELF instruction cannot appear in a lambda." Nothing         TypeCheckContract (SomeParamType _ notescp) -> do-          epName <- onTypeCheckInstrErr uInstr (SomeHST inp) Nothing $-                      epNameFromRefAnn fn `onLeft` IllegalEntrypoint+          let epName = U.epNameFromSelfAnn fn           MkEntrypointCallRes (argNotes :: Notes arg) epc <-             mkEntrypointCall epName notescp               & maybeToRight (EntrypointNotFound epName)
src/Michelson/Typed/Annotation.hs view
@@ -2,8 +2,6 @@ -- -- SPDX-License-Identifier: LicenseRef-MIT-TQ -{-# LANGUAGE DataKinds, GADTs #-}- -- | Module, providing @Notes t@ data type, which holds annotations for a -- given type @t@. --
src/Michelson/Typed/Arith.hs view
@@ -2,8 +2,6 @@ -- -- SPDX-License-Identifier: LicenseRef-MIT-TQ -{-# LANGUAGE DataKinds, MultiParamTypeClasses, TypeFamilies #-}- -- | Module, containing some boilerplate for support of -- arithmetic operations in Michelson language. @@ -11,7 +9,8 @@   ( ArithOp (..)   , UnaryArithOp (..)   , ArithError (..)-  , ArithErrorType (..)+  , ShiftArithErrorType (..)+  , MutezArithErrorType (..)   , Add   , Sub   , Mul@@ -34,13 +33,14 @@   ) where  import Data.Bits (complement, shift, (.&.), (.|.))+import Data.Constraint (Dict(..)) import Data.Singletons (Sing, SingI(..)) import Fmt (Buildable(build))  import Michelson.Typed.Annotation (AnnConvergeError, Notes(..), converge, convergeAnns, starNotes) import Michelson.Typed.Sing (SingT(..)) import Michelson.Typed.T (T(..))-import Michelson.Typed.Value (Comparable, Comparability(..), checkComparability, Value'(..))+import Michelson.Typed.Value (Comparability(..), Comparable, Value'(..), checkComparability) import Tezos.Core (addMutez, mulMutez, subMutez, timestampFromSeconds, timestampToSeconds)  -- | Class for binary arithmetic operation.@@ -71,21 +71,36 @@     -> Value' instr m     -> Either (ArithError (Value' instr n) (Value' instr m)) (Value' instr (ArithRes aop n m)) --- | Denotes the error type occured in the arithmetic operation.-data ArithErrorType+  -- | An operation can marked as commutative, it does not affect its+  -- runtime behavior, but enables certain optimization in the optimizer.+  -- We conservatively consider operations non-commutative by default.+  --+  -- Note that there is one unusual case: @AND@ works with @int : nat@+  -- but not with @nat : int@. That's how it's specified in Michelson.+  commutativityProof :: Maybe $ Dict (ArithRes aop n m ~ ArithRes aop m n, ArithOp aop m n)+  commutativityProof = Nothing++-- | Denotes the error type occurred in the arithmetic shift operation.+data ShiftArithErrorType+  = LslOverflow+  | LsrUnderflow+  deriving stock (Show, Eq, Ord, Generic)++instance NFData ShiftArithErrorType++-- | Denotes the error type occurred in the arithmetic operation involving mutez.+data MutezArithErrorType   = AddOverflow   | MulOverflow   | SubUnderflow-  | LslOverflow-  | LsrUnderflow   deriving stock (Show, Eq, Ord, Generic) -instance NFData ArithErrorType+instance NFData MutezArithErrorType  -- | Represents an arithmetic error of the operation. data ArithError n m-  = MutezArithError ArithErrorType n m-  | ShiftArithError ArithErrorType n m+  = MutezArithError MutezArithErrorType n m+  | ShiftArithError ShiftArithErrorType n m   deriving stock (Show, Eq, Ord, Generic)  instance (NFData n, NFData m) => NFData (ArithError n m)@@ -120,34 +135,41 @@   type ArithRes Add 'TNat 'TInt = 'TInt   convergeArith _ _ n2 = Right n2   evalOp _ (VNat i) (VInt j) = Right $ VInt (toInteger i + j)+  commutativityProof = Just Dict instance ArithOp Add 'TInt 'TNat where   type ArithRes Add 'TInt 'TNat = 'TInt   convergeArith _ n1 _ = Right n1   evalOp _ (VInt i) (VNat j) = Right $ VInt (i + toInteger j)+  commutativityProof = Just Dict instance ArithOp Add 'TNat 'TNat where   type ArithRes Add 'TNat 'TNat = 'TNat   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VNat i) (VNat j) = Right $ VNat (i + j)+  commutativityProof = Just Dict instance ArithOp Add 'TInt 'TInt where   type ArithRes Add 'TInt 'TInt = 'TInt   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VInt i) (VInt j) = Right $ VInt (i + j)+  commutativityProof = Just Dict instance ArithOp Add 'TTimestamp 'TInt where   type ArithRes Add 'TTimestamp 'TInt = 'TTimestamp   convergeArith _ n1 _ = Right n1   evalOp _ (VTimestamp i) (VInt j) =     Right $ VTimestamp $ timestampFromSeconds $ timestampToSeconds i + j+  commutativityProof = Just Dict instance ArithOp Add 'TInt 'TTimestamp where   type ArithRes Add 'TInt 'TTimestamp = 'TTimestamp   convergeArith _ _ n2 = Right n2   evalOp _ (VInt i) (VTimestamp j) =     Right $ VTimestamp $ timestampFromSeconds $ timestampToSeconds j + i+  commutativityProof = Just Dict instance ArithOp Add 'TMutez 'TMutez where   type ArithRes Add 'TMutez 'TMutez = 'TMutez   convergeArith _ n1 n2 = converge n1 n2   evalOp _ n@(VMutez i) m@(VMutez j) = res     where       res = maybe (Left $ MutezArithError AddOverflow n m) (Right . VMutez) $ i `addMutez` j+  commutativityProof = Just Dict  instance ArithOp Sub 'TNat 'TInt where   type ArithRes Sub 'TNat 'TInt = 'TInt@@ -187,30 +209,36 @@   type ArithRes Mul 'TNat 'TInt = 'TInt   convergeArith _ _ n2 = Right n2   evalOp _ (VNat i) (VInt j) = Right $ VInt (toInteger i * j)+  commutativityProof = Just Dict instance ArithOp Mul 'TInt 'TNat where   type ArithRes Mul 'TInt 'TNat = 'TInt   convergeArith _ n1 _ = Right n1   evalOp _ (VInt i) (VNat j) = Right $ VInt (i * toInteger j)+  commutativityProof = Just Dict instance ArithOp Mul 'TNat 'TNat where   type ArithRes Mul 'TNat 'TNat = 'TNat   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VNat i) (VNat j) = Right $ VNat (i * j)+  commutativityProof = Just Dict instance ArithOp Mul 'TInt 'TInt where   type ArithRes Mul 'TInt 'TInt = 'TInt   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VInt i) (VInt j) = Right $ VInt (i * j)+  commutativityProof = Just Dict instance ArithOp Mul 'TNat 'TMutez where   type ArithRes Mul 'TNat 'TMutez = 'TMutez   convergeArith _ _ n2 = Right n2   evalOp _ n@(VNat i) m@(VMutez j) = res     where       res = maybe (Left $ MutezArithError MulOverflow n m) (Right . VMutez) $ j `mulMutez` i+  commutativityProof = Just Dict instance ArithOp Mul 'TMutez 'TNat where   type ArithRes Mul 'TMutez 'TNat = 'TMutez   convergeArith _ n1 _ = Right n1   evalOp _ n@(VMutez i) m@(VNat j) = res     where       res = maybe (Left $ MutezArithError MulOverflow n m) (Right . VMutez) $ i `mulMutez` j+  commutativityProof = Just Dict  instance UnaryArithOp Abs 'TInt where   type UnaryArithRes Abs 'TInt = 'TNat@@ -227,10 +255,12 @@   type ArithRes Or 'TNat 'TNat = 'TNat   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VNat i) (VNat j) = Right $ VNat (i .|. j)+  commutativityProof = Just Dict instance ArithOp Or 'TBool 'TBool where   type ArithRes Or 'TBool 'TBool = 'TBool   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VBool i) (VBool j) = Right $ VBool (i .|. j)+  commutativityProof = Just Dict  instance ArithOp And 'TInt 'TNat where   type ArithRes And 'TInt 'TNat = 'TNat@@ -240,19 +270,23 @@   type ArithRes And 'TNat 'TNat = 'TNat   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VNat i) (VNat j) = Right $ VNat (i .&. j)+  commutativityProof = Just Dict instance ArithOp And 'TBool 'TBool where   type ArithRes And 'TBool 'TBool = 'TBool   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VBool i) (VBool j) = Right $ VBool (i .&. j)+  commutativityProof = Just Dict  instance ArithOp Xor 'TNat 'TNat where   type ArithRes Xor 'TNat 'TNat = 'TNat   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VNat i) (VNat j) = Right $ VNat (i `xor` j)+  commutativityProof = Just Dict instance ArithOp Xor 'TBool 'TBool where   type ArithRes Xor 'TBool 'TBool = 'TBool   convergeArith _ n1 n2 = converge n1 n2   evalOp _ (VBool i) (VBool j) = Right $ VBool (i `xor` j)+  commutativityProof = Just Dict  instance ArithOp Lsl 'TNat 'TNat where   type ArithRes Lsl 'TNat 'TNat = 'TNat@@ -325,13 +359,16 @@   evalUnaryArithOp _ (VInt i) = VBool (i >= 0)  -instance Buildable ArithErrorType where+instance Buildable ShiftArithErrorType where   build = \case+    LslOverflow -> "lsl overflow"+    LsrUnderflow -> "lsr underflow"++instance Buildable MutezArithErrorType where+  build = \case     AddOverflow -> "add overflow"     MulOverflow -> "mul overflow"     SubUnderflow -> "sub overflow"-    LslOverflow -> "lsl overflow"-    LsrUnderflow -> "lsr underflow"  instance (Show n, Show m) => Buildable (ArithError n m) where   build (MutezArithError errType n m) = "Mutez "
src/Michelson/Typed/Convert.hs view
@@ -9,24 +9,31 @@   , convertContract   , instrToOps   , untypeValue++  -- Helper for generating documentation+  , sampleValueFromUntype   ) where +import Data.Constraint (Dict(..)) import qualified Data.Map as Map-import Data.Singletons (demote)+import qualified Data.Set as Set+import Data.Singletons (Sing, demote) import Fmt (Buildable(..), pretty)  import Michelson.Text+import Michelson.Typed.Aliases import Michelson.Typed.Annotation (Notes(..)) import Michelson.Typed.Entrypoints-import Michelson.Typed.Extract (mkUType, toUType)+import Michelson.Typed.Extract (fromUType, mkUType, toUType) import Michelson.Typed.Instr as Instr import Michelson.Typed.Scope-import Michelson.Typed.Sing (SingT(..))+import Michelson.Typed.Sing (SingT(..), withSomeSingT) import Michelson.Typed.T (T(..)) import Michelson.Typed.Value import qualified Michelson.Untyped as U-import Tezos.Core (mformatChainId, unMutez)-import Tezos.Crypto (mformatKeyHash, mformatPublicKey, mformatSignature)+import Tezos.Core+  (mformatChainId, parseChainId, timestampFromSeconds, unMutez, unsafeMkMutez)+import Tezos.Crypto import Util.Peano import Util.Typeable @@ -133,12 +140,16 @@   DocGroup _ sq -> instrToOps sq   Ext (ext :: ExtInstr inp) -> (U.PrimEx . U.EXT) <$> extInstrToOps ext   FrameInstr _ i -> instrToOps i+  -- TODO [#283] After representation of locations is polished,+  -- this place should be updated to pass it from typed to untyped ASTs.+  WithLoc _ i -> instrToOps i   InstrWithNotes n i -> case i of     Nop -> instrToOps i     Seq _ _ -> instrToOps i     Nested _ -> instrToOps i     DocGroup _ _ -> instrToOps i     Ext _ -> instrToOps i+    WithLoc _ i0 -> instrToOps (InstrWithNotes n i0)     InstrWithNotes _ _ -> instrToOps i     InstrWithVarNotes _ _ -> instrToOps i     -- For inner instruction, filter out values that we don't want to apply@@ -152,12 +163,11 @@     Nested _ -> instrToOps i     DocGroup _ _ -> instrToOps i     Ext _ -> instrToOps i+    WithLoc _ i0 -> instrToOps (InstrWithVarNotes n i0)     InstrWithNotes _ _ -> instrToOps i     InstrWithVarNotes _ _ -> instrToOps i     _ -> [U.PrimEx $ handleInstrVarNotes i n]   i -> [U.PrimEx $ handleInstr i]-  -- TODO pva701: perphaps, typed instr has to hold a position too-  -- to make it possible to report a precise location of a runtime error   where     handleInstrAnnotate       :: forall inp' out' . HasCallStack@@ -173,7 +183,7 @@             (_, U.SOME _ va, NTOption ta _) -> U.SOME ta va             (STOption _, U.NONE _ va _, NTOption ta nt) -> U.NONE ta va (mkUType nt)             (_, U.UNIT _ va, NTUnit ta) -> U.UNIT ta va-            (_, U.PAIR _ va _ _, NTPair ta f1 f2 _ _) -> U.PAIR ta va f1 f2+            (_, U.PAIR ta va f1 f2, _) -> U.PAIR ta va f1 f2             (_, U.CAR va f1, _) -> U.CAR va f1             (_, U.CDR va f1, _) -> U.CDR va f1             (STOr _ _, U.LEFT _ va _ _ _, NTOr ta f1 f2 _ n2) ->@@ -350,6 +360,7 @@      handleInstr :: Instr inp out -> U.ExpandedInstr     handleInstr = \case+      (WithLoc _ _) -> error "impossible"       (InstrWithNotes _ _) -> error "impossible"       (InstrWithVarNotes _ _) -> error "impossible"       (FrameInstr _ _) -> error "impossible"@@ -372,7 +383,7 @@       SOME -> U.SOME U.noAnn U.noAnn       UNIT -> U.UNIT U.noAnn U.noAnn       (IF_NONE i1 i2) -> U.IF_NONE (instrToOps i1) (instrToOps i2)-      PAIR -> U.PAIR U.noAnn U.noAnn U.noAnn U.noAnn+      AnnPAIR tn fn1 fn2 -> U.PAIR tn U.noAnn fn1 fn2       (AnnCAR fn) -> U.CAR U.noAnn fn       (AnnCDR fn) -> U.CDR U.noAnn fn       i@LEFT | _ :: Instr (a ': s) ('TOr a b ': s) <- i ->@@ -510,3 +521,86 @@  instance (SingI t, HasNoOp t) => Buildable (Value' Instr t) where   build = build . untypeValue++-- | Get 'sampleTypedValue' from untyped value.+--+-- Throw error if @U.Type@ contains @TOperation@.+sampleValueFromUntype :: HasCallStack => U.Type -> U.Value' U.ExpandedOp+sampleValueFromUntype ty = withSomeSingT (fromUType ty) $ \(_ :: Sing t) ->+  case checkScope @(ParameterScope t) of+    Left bt -> error $ "Scope error: " <> pretty bt+    Right Dict -> untypeValue $ sampleTypedValue @t++-- | Sample values used for generating examples of entrypoint parameter in documentation.+sampleTypedValue :: forall t. (HasCallStack, ParameterScope t) => Value t+sampleTypedValue = case sing @t of+    STInt              -> VInt -1+    STNat              -> VNat 0+    STString           -> VString [mt|hello|]+    STMutez            -> VMutez (unsafeMkMutez 100)+    STBool             -> VBool True+    STKey              -> VKey samplePublicKey+    STKeyHash          -> VKeyHash $ hashKey samplePublicKey+    STTimestamp        -> VTimestamp $ timestampFromSeconds 1564142952+    STBytes            -> VBytes "\10"+    STAddress          -> VAddress $ sampleAddress+    STUnit             -> VUnit+    STSignature        -> VSignature $ sampleSignature+    STChainId          -> VChainId sampleChainId+    STOption (_ :: Sing t2) -> VOption $ Just $ sampleTypedValue @t2+    STList (_ :: Sing t2) -> VList [sampleTypedValue @t2]+    STSet (s2 :: Sing t2) ->+      case ( checkComparability s2+           , checkNestedBigMapsPresence s2+           ) of+        (CanBeCompared, NestedBigMapsAbsent) ->+          VSet $ Set.fromList [sampleTypedValue @t2]+        _ -> error $ "Error generating sample value: scope error"+    STContract _ ->+      VContract (eaAddress sampleAddress) $ SomeEpc epcCallRootUnsafe+    STPair (s2 :: Sing t2) (s3 :: Sing t3) ->+      case ( checkOpPresence s2+           , checkNestedBigMapsPresence s2+           , checkOpPresence s3+           , checkNestedBigMapsPresence s3+           ) of+        (OpAbsent, NestedBigMapsAbsent, OpAbsent, NestedBigMapsAbsent) ->+          VPair (sampleTypedValue @t2, sampleTypedValue @t3)+    STOr (s2 :: Sing t2) _ ->+      case (checkNestedBigMapsPresence s2, checkOpPresence s2) of+        (NestedBigMapsAbsent, OpAbsent) ->+          VOr $ Left $ sampleTypedValue @t2+    STMap (s2 :: Sing t2) (s3 :: Sing t3) ->+      case ( checkNestedBigMapsPresence s2+           , checkComparability s2+           , checkOpPresence s2+           , checkNestedBigMapsPresence s3+           ) of+        (NestedBigMapsAbsent, CanBeCompared, OpAbsent, NestedBigMapsAbsent) ->+            VMap $ Map.fromList [(sampleTypedValue @t2, sampleTypedValue @t3)]+        _ -> error $ "Error generating sample value: scope error"+    STBigMap (s2 :: Sing t2) (s3 :: Sing t3) ->+      case ( checkNestedBigMapsPresence s2+           , checkComparability s2+           , checkOpPresence s2+           , checkNestedBigMapsPresence s3+           ) of+        (NestedBigMapsAbsent, CanBeCompared, OpAbsent, NestedBigMapsAbsent) ->+            VBigMap $ Map.fromList [(sampleTypedValue @t2, sampleTypedValue @t3)]+        _ -> error $ "Error generating sample value: scope error"+    STLambda (_ :: Sing t2) (s3 :: Sing t3) ->+      case ( checkNestedBigMapsPresence s3+           , checkBigMapPresence s3+           , checkContractTypePresence s3+           , checkOpPresence s3+           ) of+        (NestedBigMapsAbsent, BigMapAbsent, ContractAbsent, OpAbsent) ->+          VLam $ RfNormal (DROP `Seq` PUSH (sampleTypedValue @t3))+        _ -> VLam $ RfAlwaysFails (PUSH (VString [mt|lambda sample|]) `Seq` FAILWITH)+    where+      sampleAddress =  unsafeParseEpAddress "KT1AEseqMV6fk2vtvQCVyA7ZCaxv7cpxtXdB"+      samplePublicKey = fromRight (error "impossible") $ parsePublicKey+        "edpkuwTWKgQNnhR5v17H2DYHbfcxYepARyrPGbf1tbMoGQAj8Ljr3V"+      sampleSignature = fromRight (error "impossible") $ parseSignature+        "edsigtrs8bK7vNfiR4Kd9dWasVa1bAWaQSu2ipnmLGZuwQa8ktCEMYVKqbWsbJ7zTS8dgYT9tiSUKorWCPFHosL5zPsiDwBQ6vb"+      sampleChainId = fromRight (error "impossible") $ parseChainId "NetXUdfLh6Gm88t"
src/Michelson/Typed/Doc.hs view
@@ -37,6 +37,8 @@   () <- case docItemRef di of     DocItemNoRef ->       modify (<> mempty{ cdContents = docItemToBlock di })+    DocItemRefInlined{} ->+      modify (<> mempty{ cdContents = docItemToBlock di })     DocItemRef{} ->       someDefinitionDocItemToContractDoc (SomeDocDefinitionItem di)   forM_ @_ @_ @() (docItemDependencies di) $ \(SomeDocDefinitionItem dep) ->@@ -57,10 +59,19 @@   DGitRevisionUnknown -> Just gitRev   _ -> Nothing +attachToc :: DToc -> Instr inp out -> Instr inp out+attachToc toc = modifyInstrDoc $ \case+  DToc "" -> Just $ toc+  _ -> Nothing+ -- | Assemble contract documentation with the revision of the contract. buildInstrDocWithGitRev :: DGitRevision -> Instr inp out -> ContractDoc buildInstrDocWithGitRev gitRev contract =-  buildInstrDoc $ attachGitInfo gitRev contract+  let toc = DToc $ contractDocToToc $ buildInstrDoc contract+      c = contract+            & attachGitInfo gitRev+            & attachToc toc+  in buildInstrDoc c  -- | Assemble contract documentation. buildInstrDoc :: Instr inp out -> ContractDoc
src/Michelson/Typed/Entrypoints.hs view
@@ -48,7 +48,6 @@ import Control.Monad.Except (throwError) import qualified Data.ByteString as BS import Data.Constraint (Dict(..))-import Data.Default (Default(..)) import qualified Data.List.NonEmpty as NE import qualified Data.Text as T import Fmt (Buildable(..), hexF, pretty, (+|), (|+))@@ -92,7 +91,7 @@  formatEpAddress :: EpAddress -> Text formatEpAddress (EpAddress addr ep)-  | ep == def = formatAddress addr+  | isDefEpName ep = formatAddress addr   | otherwise = formatAddress addr <> "%" <> pretty ep  mformatEpAddress :: EpAddress -> MText@@ -133,7 +132,7 @@   in case mannotTxt of     "" -> do       addr <- first ParseEpAddressBadAddress $ parseAddress addrTxt-      return $ EpAddress addr def+      return $ EpAddress addr DefEpName     annotTxt' -> do       addr <- first ParseEpAddressBadAddress $ parseAddress addrTxt       annot <- first ParseEpAddressBadRefAnn $ case T.stripPrefix "%" annotTxt' of@@ -278,8 +277,8 @@         haveDefLL <- first (AcLeft  :) $ ensureAllCallable l         haveDefRR <- first (AcRight :) $ ensureAllCallable r -        let haveDefL = or [haveDefLL, epNameL == Just (def @EpName)]-        let haveDefR = or [haveDefRR, epNameR == Just (def @EpName)]+        let haveDefL = or [haveDefLL, maybe False isDefEpName epNameL]+        let haveDefR = or [haveDefRR, maybe False isDefEpName epNameR]          when haveDefL $ first (AcRight :) $ checkAllEpsNamed epNameR r         when haveDefR $ first (AcLeft  :) $ checkAllEpsNamed epNameL l@@ -360,7 +359,7 @@ -- Validity of such operation is not ensured. epcCallRootUnsafe :: ParameterScope param => EntrypointCallT param param epcCallRootUnsafe = EntrypointCall-  { epcName = def+  { epcName = DefEpName   , epcParamProxy = Proxy   , epcLiftSequence = EplArgHere   }@@ -482,9 +481,9 @@         , epcParamProxy = Proxy         , epcLiftSequence = liftSeq         }-  , guard (epName == def) $>+  , guard (isDefEpName epName) $>       MkEntrypointCallRes paramNotes EntrypointCall-        { epcName = def+        { epcName = epName         , epcParamProxy = Proxy         , epcLiftSequence = EplArgHere         }@@ -502,11 +501,3 @@ -- duplicate entrypoints are handled. flattenEntrypoints :: SingI t => ParamNotes t -> Map EpName U.Type flattenEntrypoints (pnNotes -> notes) = mkEntrypointsMap (mkUType notes)---- TODO [#35]: Root annotation is currently support as a dedicated field--- in 'ParamNotes'.------ Also it would be nice to automatically add @%root@ annotation in each parameter--- declaration when compiling Lorentz to Michelson.--- In addition to this, we should actually use @%root@ annotation in the entrypoint engine--- and not just store it.
src/Michelson/Typed/Haskell/Doc.hs view
@@ -318,6 +318,7 @@  instance DocItem DType where   type DocItemPlacement DType = 'DocItemInDefinitions+  type DocItemReferenced DType = 'True   docItemPos = 5000    docItemSectionName = Just "Types"@@ -359,6 +360,9 @@         in rendered <> "\n\n"     ] +  docItemToToc lvl d@(DType ap') =+    mdTocFromRef lvl (build $ typeDocName ap') d+ -- | Create a 'DType' in form suitable for putting to 'typeDocDependencies'. dTypeDep :: forall (t :: Kind.Type). TypeHasDoc t => SomeDocDefinitionItem dTypeDep = SomeDocDefinitionItem (DType (Proxy @t))@@ -372,12 +376,19 @@  -- | Doc element with description of contract storage type. newtype DStorageType = DStorageType DType-  deriving stock Generic+  deriving stock (Generic, Eq, Ord)  instance DocItem DStorageType where+  type DocItemPlacement DStorageType = 'DocItemInlined+  type DocItemReferenced DStorageType = 'True++  docItemRef (DStorageType (DType a)) = DocItemRefInlined $+    DocItemId ("storage-" <> typeDocName a)   docItemPos = 835   docItemSectionName = Just "Storage"   docItemToMarkdown lvl (DStorageType t) = docItemToMarkdown lvl t+  docItemToToc lvl d@(DStorageType (DType a)) =+    mdTocFromRef lvl (build $ typeDocName a) d   docItemDependencies (DStorageType t) = docItemDependencies t  -- Default implementations
src/Michelson/Typed/Haskell/Value.hs view
@@ -151,7 +151,7 @@  instance IsoValue Address where   type ToT Address = 'TAddress-  toVal addr = VAddress $ EpAddress addr def+  toVal addr = VAddress $ EpAddress addr DefEpName   fromVal (VAddress x) = eaAddress x  instance IsoValue EpAddress where
src/Michelson/Typed/Instr.hs view
@@ -20,6 +20,7 @@   , mapEntriesOrdered   , pattern CAR   , pattern CDR+  , pattern PAIR   , pattern UNPAIR   , PackedNotes(..)   , ConstraintDIPN@@ -36,6 +37,7 @@ import qualified Text.Show  import Michelson.Doc+import Michelson.ErrorPos import Michelson.Printer.Util (RenderDoc(..), buildRenderDoc, needsParens, printDocS) import Michelson.Typed.Annotation (Notes(..)) import Michelson.Typed.Arith@@ -45,7 +47,7 @@ import Michelson.Typed.Sing (KnownT) import Michelson.Typed.T (T(..)) import Michelson.Typed.Value (Comparable, ContractInp, ContractOut, Value'(..))-import Michelson.Untyped (Annotation(..), EntriesOrder(..), FieldAnn, VarAnn, entriesOrderToInt)+import Michelson.Untyped (Annotation(..), EntriesOrder(..), FieldAnn, TypeAnn, VarAnn, entriesOrderToInt) import Util.Peano import Util.TH import Util.Type (type (++), KnownList)@@ -116,6 +118,11 @@ -- 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]) where+  -- | A wrapper carrying original source location of the instruction.+  --+  -- TODO [#283]: replace this wrapper with something more clever and abstract.+  WithLoc :: InstrCallStack -> Instr a b -> Instr a b+   -- | A wrapper for instruction that also contain annotations for the   -- top type on the result stack.   --@@ -197,7 +204,10 @@     :: Instr s s'     -> Instr (a ': s) s'     -> Instr ('TOption a ': s) s'-  PAIR :: Instr (a ': b ': s) ('TPair a b ': s)+  -- | Annotations for PAIR instructions can be different from notes presented on the stack+  -- in case of special field annotations, so we carry annotations for instruction+  -- separately from notes.+  AnnPAIR :: TypeAnn -> FieldAnn -> FieldAnn -> Instr (a ': b ': s) ('TPair a b ': s)   LEFT :: forall b a s . KnownT b => Instr (a ': s) ('TOr a b ': s)   RIGHT :: forall a b s . KnownT a => Instr (b ': s) ('TOr a b ': s)   IF_LEFT@@ -378,6 +388,9 @@  pattern UNPAIR :: () => (i ~ ('TPair a b : s), o ~ (a : b : s)) => Instr i o pattern UNPAIR = Seq DUP (Seq CAR (DIP CDR))++pattern PAIR :: () => (i ~ (a ': b ': s), o ~ ('TPair a b ': s)) => Instr i o+pattern PAIR = AnnPAIR (AnnotationUnsafe "") (AnnotationUnsafe "") (AnnotationUnsafe "")  data TestAssert (s :: [T]) where   TestAssert
src/Michelson/Typed/T.hs view
@@ -2,8 +2,6 @@ -- -- SPDX-License-Identifier: LicenseRef-MIT-TQ -{-# LANGUAGE DataKinds #-}- -- | Module, providing 'T' data type, representing Michelson -- language types without annotations. module Michelson.Typed.T
src/Michelson/Typed/Util.hs view
@@ -91,6 +91,7 @@ dfsInstr settings@DfsSettings{..} step i =   case i of     Seq i1 i2 -> recursion2 Seq i1 i2+    WithLoc loc i1 -> recursion1 (WithLoc loc) i1     InstrWithNotes notes i1 -> recursion1 (InstrWithNotes notes) i1     InstrWithVarNotes varNotes i1 -> recursion1 (InstrWithVarNotes varNotes) i1     FrameInstr p i1 -> recursion1 (FrameInstr p) i1@@ -155,7 +156,7 @@     SOME{} -> step i     NONE{} -> step i     UNIT{} -> step i-    PAIR{} -> step i+    AnnPAIR{} -> step i     LEFT{} -> step i     RIGHT{} -> step i     NIL{} -> step i@@ -274,6 +275,10 @@   where   go :: Instr i o -> RemFail Instr i o   go = \case+    WithLoc loc i -> case go i of+      RfNormal i0 ->+        RfNormal (WithLoc loc i0)+      r -> r     InstrWithNotes pn i -> case go i of       RfNormal i0 ->         RfNormal (InstrWithNotes pn i0)@@ -320,7 +325,7 @@     i@SOME{} -> RfNormal i     i@NONE{} -> RfNormal i     i@UNIT{} -> RfNormal i-    i@PAIR{} -> RfNormal i+    i@AnnPAIR{} -> RfNormal i     i@LEFT{} -> RfNormal i     i@RIGHT{} -> RfNormal i     i@NIL{} -> RfNormal i
src/Michelson/Untyped/Entrypoints.hs view
@@ -5,9 +5,11 @@ module Michelson.Untyped.Entrypoints   ( EpName (..)   , pattern DefEpName+  , isDefEpName   , epNameFromParamAnn   , epNameToParamAnn   , epNameFromRefAnn+  , epNameFromSelfAnn   , epNameToRefAnn   , EpNameFromRefAnnError (..)   , buildEpName@@ -16,7 +18,6 @@   ) where  import Data.Aeson.TH (deriveJSON)-import Data.Default (Default(..)) import qualified Data.Map as Map import Fmt (Buildable(..), pretty, (+|), (|+)) import Test.QuickCheck (Arbitrary(..), suchThatMap)@@ -28,9 +29,31 @@  -- | 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.+-- There are two properties we care about:+--+-- 1. Special treatment of the @default@ entrypoint name.+-- @default@ is prohibited in the @CONTRACT@ instruction and in+-- values of @address@ and @contract@ types.+-- However, it is not prohibited in the @SELF@ instruction.+-- Hence, the value inside @EpName@ __can__ be @"default"@, so that+-- we can distinguish @SELF@ and @SELF %default@. It is important+-- to distinguish them because their binary representation that is+-- inserted into blockchain is different. For example, typechecking+-- @SELF %default@ consumes more gas than @SELF@.+-- In this module, we provide several smart constructors with different+-- handling of @default@, please use the appropriate one for your use case.+-- 2. The set of permitted characters. Intuitively, an entrypoint name should+-- be valid only if it is a valid annotation (because entrypoints are defined+-- using field annotations). However, it is not enforced in Tezos.+-- It is not clear whether this behavior is intended. There is an upstream+-- [issue](https://gitlab.com/tezos/tezos/-/issues/851) which received @bug@+-- label, so probably it is considered a bug. Currently we treat it as a bug+-- and deviate from upstream implementation by probiting entrypoint names that+-- are not valid annotations. If Tezos developers fix it soon, we will be happy.+-- If they don't, we should (maybe temporarily) remove this limitation from our+-- code. There is an+-- [issue](https://gitlab.com/morley-framework/morley/-/issues/275) in our+-- repo as well. newtype EpName = EpNameUnsafe { unEpName :: Text }   deriving stock (Show, Eq, Ord, Generic) @@ -38,17 +61,32 @@  deriveJSON morleyAesonOptions ''EpName +-- | This is a bidirectional pattern that can be used for two purposes:+--+-- 1. Construct an 'EpName' referring to the default entrypoint.+-- 2. Use it in pattern-matching or in equality comparison to check whether+-- 'EpName' refers to the default entrypoint. This is trickier because there+-- are two possible 'EpName' values referring to the default entrypoints.+-- 'DefEpName' will match only the most common one (no entrypoint).+-- However, there is a special case: @SELF@ instruction can have explicit+-- @%default@ reference. For this reason, it is recommended to use+-- 'isDefEpName' instead. Pattern-matching on 'DefEpName' is still permitted+-- for backwards compatibility and for the cases when you are sure that+-- 'EpName' does not come from the @SELF@ instruction. pattern DefEpName :: EpName pattern DefEpName = EpNameUnsafe "" +-- | Check whether given 'EpName' refers to the default entrypoint.+-- Unlike 'DefEpName' pattern, this function correctly handles all cases,+-- including the @SELF@ instruction.+isDefEpName :: EpName -> Bool+isDefEpName epName = epName == DefEpName || epName == EpNameUnsafe "default"+ instance Buildable EpName where   build = \case     DefEpName -> "<default>"     EpNameUnsafe name -> build name -instance Default EpName where-  def = EpNameUnsafe ""- -- | Make up 'EpName' from annotation in parameter type declaration. -- -- Returns 'Nothing' if no entrypoint is assigned here.@@ -75,19 +113,34 @@     InEpNameBadAnnotation (Annotation an) ->       "Invalid entrypoint reference `" +| an |+ "`" --- | Make up 'EpName' from annotation which is reference to an entrypoint--- (e.g. annotation in @CONTRACT@ instruction).+-- | Make up 'EpName' from annotation which is reference to an entrypoint.+-- Note that it's more common for Michelson to prohibit explicit @default@+-- entrypoint reference. ----- Fails if annotation is invalid.+-- Specifically, @%default@ annotation is probitited in values of @address@+-- and @contract@ types. It's also prohibited in the @CONTRACT@ instruction.+-- However, there is an exception: @SELF %default@ is a perfectly valid+-- instruction. Hence, when you construct an 'EpName' from an annotation+-- that's part of @SELF@, you should use 'epNameFromSelfAnn' instead. epNameFromRefAnn :: FieldAnn -> Either EpNameFromRefAnnError EpName epNameFromRefAnn an@(Annotation a)   | a == "default" = Left $ InEpNameBadAnnotation an   | otherwise = Right $ EpNameUnsafe a +-- | Make up an 'EpName' from an annotation which is part of the+-- @SELF@ instruction.+epNameFromSelfAnn :: FieldAnn -> EpName+epNameFromSelfAnn (Annotation a) = EpNameUnsafe a+ -- | Turn entrypoint name into annotation used as reference to entrypoint. epNameToRefAnn :: EpName -> FieldAnn epNameToRefAnn (EpNameUnsafe name) = ann name +-- | Make a valid entrypoint name from an arbitrary text. This+-- function prohibits explicit @default@ entrypoint name which is+-- permitted by Michelson inside the @SELF@ instruction. This+-- limitation shouldn't be restrictive because @SELF@ is equivalent to+-- @SELF %default@. buildEpName :: Text -> Either String EpName buildEpName txt = do   annotation <-@@ -96,7 +149,8 @@   epNameFromRefAnn annotation     & first pretty -unsafeBuildEpName :: Text -> EpName+-- | Partial version of 'buildEpName'.+unsafeBuildEpName :: HasCallStack => Text -> EpName unsafeBuildEpName = either (error . pretty) id . buildEpName  instance Arbitrary FieldAnn => Arbitrary EpName where
src/Morley/CLI.hs view
@@ -32,7 +32,7 @@ import Options.Applicative.Help.Pretty (Doc)  import qualified Michelson.Parser as P-import Michelson.Runtime (TxData(..))+import Michelson.Runtime (TxData(..), TxParam(..)) import Michelson.Runtime.GState (genesisAddress) import Michelson.Text (MText) import Michelson.Untyped (EpName)@@ -118,7 +118,7 @@     mkTxData addr param amount epName =       TxData         { tdSenderAddress = addr-        , tdParameter = param+        , tdParameter = TxUntypedParam param         , tdEntrypoint = epName         , tdAmount = amount         }
src/Tezos/Crypto.hs view
@@ -65,6 +65,8 @@   , parseKeyHash   , parseKeyHashRaw   , keyHashLengthBytes+  , formatSecretKey+  , parseSecretKey    -- * Hashing   , hashKey@@ -89,6 +91,7 @@ import qualified Data.ByteArray as BA import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS+import qualified Data.Text as T import Fmt (Buildable, build, hexF, pretty) import Test.QuickCheck (Arbitrary(..), elements, oneof) @@ -345,6 +348,33 @@     , fmap SignatureP256 . P256.parseSignature     , parseImpl genericSignatureTag (pure . SignatureGeneric)     ])++formatSecretKey :: SecretKey -> Text+formatSecretKey = \case+  SecretKeyEd25519 sig -> Ed25519.formatSecretKey sig+  SecretKeySecp256k1 sig -> Secp256k1.formatSecretKey sig+  SecretKeyP256 sig -> P256.formatSecretKey sig++instance Buildable SecretKey where+  build = build . formatSecretKey++-- | Parse __unencrypted__ secret key. It accepts formats containing+-- either with or without the @unecrypted@ prefix.+parseSecretKey :: Text -> Either CryptoParseError SecretKey+parseSecretKey txt =+  firstRight $ map (\f -> f $ removePrefix txt)+    ( fmap SecretKeyEd25519 . Ed25519.parseSecretKey :|+    [ fmap SecretKeySecp256k1 . Secp256k1.parseSecretKey+    , fmap SecretKeyP256 . P256.parseSecretKey+    ])+  where+    removePrefix :: Text -> Text+    removePrefix input =+      let unencrypted = "unencrypted:"+          (prefix, payload) = T.splitAt (length unencrypted) input+      in case prefix == unencrypted of+        True -> payload+        False -> input  ---------------------------------------------------------------------------- -- JSON encoding/decoding
src/Tezos/Crypto/P256.hs view
@@ -28,6 +28,8 @@   , formatSignature   , mformatSignature   , parseSignature+  , formatSecretKey+  , parseSecretKey    -- * Signing   , sign@@ -138,6 +140,14 @@ signatureLengthBytes :: Integral n => n signatureLengthBytes = signatureLengthBytes_ curve +mkSecretKey :: ByteArray ba => ba -> Either CryptoParseError SecretKey+mkSecretKey = Right . SecretKey . mkSecretKey_ curve++-- | Convert a 'PublicKey' to raw bytes.+secretKeyToBytes :: ByteArray ba => SecretKey -> ba+secretKeyToBytes (SecretKey kp) =+  secretKeyToBytes_ kp+ ---------------------------------------------------------------------------- -- Magic bytes ----------------------------------------------------------------------------@@ -145,6 +155,10 @@ publicKeyTag :: ByteString publicKeyTag = "\003\178\139\127" +-- | Base16 format is @1051eebd@+secretKeyTag :: ByteString+secretKeyTag = "\016\081\238\189"+ signatureTag :: ByteString signatureTag = "\054\240\044\052" @@ -175,6 +189,15 @@  parseSignature :: Text -> Either CryptoParseError Signature parseSignature = parseImpl signatureTag mkSignature++formatSecretKey :: SecretKey -> Text+formatSecretKey = formatImpl @ByteString secretKeyTag . secretKeyToBytes++instance Buildable SecretKey where+  build = build . formatSecretKey++parseSecretKey :: Text -> Either CryptoParseError SecretKey+parseSecretKey = parseImpl secretKeyTag mkSecretKey  ---------------------------------------------------------------------------- -- Signing
src/Tezos/Crypto/Secp256k1.hs view
@@ -28,6 +28,8 @@   , formatSignature   , mformatSignature   , parseSignature+  , formatSecretKey+  , parseSecretKey    -- * Signing   , sign@@ -138,6 +140,14 @@ signatureLengthBytes :: Integral n => n signatureLengthBytes = signatureLengthBytes_ curve +mkSecretKey :: ByteArray ba => ba -> Either CryptoParseError SecretKey+mkSecretKey = Right . SecretKey . mkSecretKey_ curve++-- | Convert a 'PublicKey' to raw bytes.+secretKeyToBytes :: ByteArray ba => SecretKey -> ba+secretKeyToBytes (SecretKey kp) =+  secretKeyToBytes_ kp+ ---------------------------------------------------------------------------- -- Magic bytes ----------------------------------------------------------------------------@@ -145,6 +155,10 @@ publicKeyTag :: ByteString publicKeyTag = "\003\254\226\086" +-- | Base16 format is @11a2e0c9@+secretKeyTag :: ByteString+secretKeyTag = "\017\162\224\201"+ signatureTag :: ByteString signatureTag = "\013\115\101\019\063" @@ -175,6 +189,15 @@  parseSignature :: Text -> Either CryptoParseError Signature parseSignature = parseImpl signatureTag mkSignature++formatSecretKey :: SecretKey -> Text+formatSecretKey = formatImpl @ByteString secretKeyTag . secretKeyToBytes++instance Buildable SecretKey where+  build = build . formatSecretKey++parseSecretKey :: Text -> Either CryptoParseError SecretKey+parseSecretKey = parseImpl secretKeyTag mkSecretKey  ---------------------------------------------------------------------------- -- Signing
src/Tezos/Crypto/Util.hs view
@@ -19,6 +19,8 @@   , rnfCurve   , publicKeyLengthBytes_   , mkSignature_+  , mkSecretKey_+  , secretKeyToBytes_   , signatureToBytes_   , mkPublicKey_   , publicKeyToBytes_@@ -30,6 +32,7 @@ import Crypto.Number.ModArithmetic (squareRoot) import Crypto.Random (ChaChaDRG, MonadPseudoRandom, drgNewSeed, seedFromInteger, withDRG) import qualified Crypto.PubKey.ECC.ECDSA as ECDSA+import qualified Crypto.PubKey.ECC.Generate as ECC.Generate import Crypto.PubKey.ECC.Types   (Curve(..), CurveCommon(..), CurvePrime(..), Point(..), curveSizeBits) import qualified Data.Binary.Get as Get@@ -222,6 +225,11 @@ signatureToBytes_ curve (ECDSA.Signature r s) =   coordToBytes curve r <> coordToBytes curve s +-- | Convert a 'PublicKey' to raw bytes.+secretKeyToBytes_ :: BA.ByteArray ba => ECDSA.KeyPair -> ba+secretKeyToBytes_ (ECDSA.KeyPair c _ s) =+  coordToBytes c s+ -- | Make a 'Signature' from raw bytes. mkSignature_ :: BA.ByteArray ba => Curve -> ba -> Either CryptoParseError ECDSA.Signature mkSignature_ curve ba@@ -232,3 +240,10 @@     Left $ CryptoParseUnexpectedLength "signature" l   where     l = BA.length ba++-- | Make a 'SecretKey' from raw bytes.+mkSecretKey_ :: BA.ByteArray ba => Curve -> ba -> ECDSA.KeyPair+mkSecretKey_ c ba =+  let s = os2ip ba+      p = ECC.Generate.generateQ c s+  in ECDSA.KeyPair c p s
src/Util/Markdown.hs view
@@ -10,6 +10,7 @@   , ToAnchor (..)   , nextHeaderLevel   , mdHeader+  , mdToc   , mdSubsection   , mdSubsectionTitle   , mdBold@@ -17,6 +18,7 @@   , mdTicked   , mdRef   , mdLocalRef+  , mdEscapeAnchor   , mdAnchor   , mdSeparator   , mdSpoiler@@ -27,6 +29,7 @@ import qualified Data.String.Interpolate.IsString as Interpolate import Data.String.Interpolate.Util (unindent) import Fmt (Builder, build, (+|), (|+))+ import Language.Haskell.TH.Quote (QuasiQuoter(..))  -- | A piece of markdown document.@@ -61,6 +64,11 @@ mdHeader :: HeaderLevel -> Markdown -> Markdown mdHeader (HeaderLevel lvl) text =   mconcat (replicate lvl "#") +| " " +| text |+ "\n\n"++mdToc :: ToAnchor anchor => HeaderLevel -> Markdown -> anchor -> Markdown+mdToc (HeaderLevel lvl) text anchor =+  mconcat (replicate (lvl - 2) "  ") +|+    "- " +| mdLocalRef text anchor |+ "\n"  mdSubsectionTitle :: Markdown -> Markdown mdSubsectionTitle title = mdBold (title <> ":")