Alpha Morley Debugger VSCode extension
The debugger is available as a
VS Code extension.
Debugger functionality and features
The debugger supports the following functionality:
- step-by-step execution, including in reverse order
- breakpoints
- stack during execution
- stack frames
New stack frames are created either when entering DIP
/DIP n
instructions,
or a lambda is called by EXEC
.
Execution of both Michelson (.tz
) and Morley (.mtz
) contracts are supported.
However, support for sapling Sapling types, instructions, and operations is not provided as redundant in actual development (see the related issue in Morley).
Special operations
and some of operations on contracts
are mocked with dummy values,
and operations produced by instructions neither cause any side effects on the blockchain nor
invoke a contract in case of TRANSFER_TOKENS
to the contract address.
Also, let
instructions in Morley contracts are not handled as well as you would expect them to be.
Usage
After you've installed the VS Code extension, you need to open a folder with a contract in VS Code,
and then open the contract itself.
On the left Activity bar click Debug icon:

To run a debug session click Run and Debug
in the Side bar (or press F5
)

After you run debugging of a contract,
you will be prompted to pick an entrypoint to run, if you have entrypoints in the contract.

Otherwise, this step will be omitted.
After that you need to input parameter and storage value. Types of them will be hinted for your convenience:

After this is done, execution should start with a cursor on the first instruction in the file.
During the execution of a contract, you have access to four panels on the left side:
- Breakpoints
- Variables
- Watch
- Call stack
Like in the screenshot below:

Breakpoints
panel contains active breakpoints with their positions.
Variables
contains stack cells.
Call stack
stack frames, every frame with a position where it has been entered,
the topmost frame is the current one.
Watch
is empty as watching functionality isn't supported for now but
will be supported soon.
Further plans
The current version of the debugger is a starting point towards
much more mature ones.
In the next versions, we are going to focus our efforts on the following workstreams:
developing an extensible debugger protocol for the high-level languages compiled to Michelson (like Ligo and Indigo).
We are going to come up with, implement, and describe a protocol to make it easier
for other Michelson-targeting languages to implement specific debuggers.
extending a contract execution environment.
This will start with a feature as simple as debugging a Michelson/Morley contract
against user-provided data for instructions like SENDER
, SOURCE
, NOW
, LEVEL
, etc to make
debugging process more customizable.
The next step will move towards connecting the debugger with the real blockchain:
you'll be able to specify a node to connect for fetching blockchain specific-data,
with different options to debug a contract that is already on the blockchain.
After that, the next useful feature will be debugging of invoked external contracts and
emitting produced operations to the blockchain.
implementing more convenient features for debugging.
We'll implement features
like watching expressions, conditional breakpoints, editing stack cell values during execution, etc.
The next version of the debugger will be focused on the support of contract operations.
Getting the extension
Apart from downloading the extension from the VS Code marketplace, there are
other ways to get it:
- download the latest version from the repository CI
- build the extension from scratch
These options will be described in depth below.
Downloading from the morley CI
The easiest way to obtain the extension is just to download it from the morley CI.
However, this way works only for Linux-based operating systems,
Windows and macOS users can still install the extension from the marketplace/the CI,
but they will have to build the adapter executable and replace the binary in the extension folder.
How to do that is described in the following section.
Go to the morley-debugger repo
Click on the Pipeline
button of the last successful commit, then go to the Jobs
tab.
Find there the build-morley-debugger-plugin
artifact and download it.
When you unarchive the artifact, it will contain a .vsix
extension which can be installed following the instruction here
Building manually
In the section below, we'll explain how to build and run the extension from scratch.
First of all, you need to have the following things installed:
After you've made sure you have everything above, follow these steps:
Build and install the debugger adapter: stack install --local-bin-path bin morley-debugger
Run yarn compile
Run yarn package
(you need vsce
installed)
Install michelson-debugger-0.0.1.vsix
following this instruction.
Just for your information: all VS extensions are stored on the disk unpacked (for instance, on Linux in ~/.vscode/extensions
),
so if you don't want to rebuild everything from scratch, or, for instance, you want to patch only the adapter but not JS code,
you can just replace the executable in the serokell.michelson-debugger-{version}/bin
folder,
but be aware that this approach is more fragile than the one described above.
Running in debug mode
This part describes how to run the extension in development mode and debug the JS part of the code.
First, run yarn
to install dependencies.
Then open this folder in VSCode, then press F5
. Extension
configuration should be run.
A new VSCode window will open. In it, open any .tz
file, press F5
and choose Michelson Morley Debugger
. Then click create a launch.json file
. VSCode will create a stub config. In that config,
you need to fill in the logDir
field with a directory where the logging file will be created.
Then a debug session will start.
In the morley-dap.log
file which, in turn, is in specified logDir
directory,
you will see something like this:
Right (DAPRequest {drSpecific = InitializeRequest (InitializeRequest {seqInitializeRequest = 1, typeInitializeRequest = "request", commandInitializeRequest = "initialize", argumentsInitializeRequest = InitializeRequestArguments {adapterIDInitializeRequestArguments = "michelson", linesStartAt1InitializeRequestArguments = True, columnsStartAt1InitializeRequestArguments = True, pathFormatInitializeRequestArguments = "path"}}), drRaw = Object (fromList [("command",String "initialize"),("arguments",Object (fromList [("clientID",String "vscode"),("supportsVariablePaging",Bool True),("supportsProgressReporting",Bool True),("supportsVariableType",Bool True),("adapterID",String "michelson"),("locale",String "ru"),("columnsStartAt1",Bool True),("supportsRunInTerminalRequest",Bool True),("clientName",String "Visual Studio Code"),("pathFormat",String "path"),("linesStartAt1",Bool True)])),("seq",Number 1.0),("type",String "request")])})
Right (DAPRequest {drSpecific = DisconnectRequest (DisconnectRequest {seqDisconnectRequest = 2, typeDisconnectRequest = "request", commandDisconnectRequest = "disconnect", argumentsDisconnectRequest = Just (DisconnectArguments {restartDisconnectRequestArguments = Just False})}), drRaw = Object (fromList [("command",String "disconnect"),("arguments",Object (fromList [("restart",Bool False)])),("seq",Number 2.0),("type",String "request")])})
This means it can successfully parse VSCode messages.