From b42ae72a7e63f9fbed46c6389432e39fe8a32140 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 2 Aug 2018 16:05:40 +0200 Subject: [PATCH 1/3] add remix-debug to the console --- src/lib/cmdInterpreterAPI.js | 127 +++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 5 deletions(-) diff --git a/src/lib/cmdInterpreterAPI.js b/src/lib/cmdInterpreterAPI.js index 092c1da22f..456008165e 100644 --- a/src/lib/cmdInterpreterAPI.js +++ b/src/lib/cmdInterpreterAPI.js @@ -2,11 +2,16 @@ var yo = require('yo-yo') var async = require('async') var remixLib = require('remix-lib') +var remixCore = require('remix-core') var EventManager = remixLib.EventManager var executionContext = require('../execution-context') var toolTip = require('../app/ui/tooltip') var globalRegistry = require('../global/registry') +var SourceHighlighter = require('../app/editor/sourceHighlighter') +var RemixDebug = require('remix-debug').EthDebugger +var TreeView = require('../app/ui/TreeView') // TODO setup a direct reference to the UI components +var solidityTypeFormatter = require('../app/debugger/remix-debugger/src/ui/SolidityTypeFormatter') class CmdInterpreterAPI { constructor (terminal, localRegistry) { @@ -15,10 +20,13 @@ class CmdInterpreterAPI { self._components = {} self._components.registry = localRegistry || globalRegistry self._components.terminal = terminal + self._components.sourceHighlighter = new SourceHighlighter() self._deps = { app: self._components.registry.get('app').api, fileManager: self._components.registry.get('filemanager').api, - editor: self._components.registry.get('editor').api + editor: self._components.registry.get('editor').api, + compiler: self._components.registry.get('compiler').api, + offsetToLineColumnConverter: self._components.registry.get('offsettolinecolumnconverter').api } self.commandHelp = { 'remix.debug(hash)': 'Start debugging a transaction.', @@ -27,13 +35,95 @@ class CmdInterpreterAPI { 'remix.setproviderurl(url)': 'Change the current provider to Web3 provider and set the url endpoint.', 'remix.execute(filepath)': 'Run the script specified by file path. If filepath is empty, script currently displayed in the editor is executed.', 'remix.exeCurrent()': 'Run the script currently displayed in the editor', - 'remix.help()': 'Display this help message' + 'remix.help()': 'Display this help message', + 'remix.debugHelp()': 'Display help message for debugging' } } + log () { arguments[0] != null ? this._components.terminal.commands.html(arguments[0]) : this._components.terminal.commands.html(arguments[1]) } + highlight (rawLocation) { + var self = this + if (!rawLocation) { + self._components.sourceHighlighter.currentSourceLocation(null) + return + } + var lineColumnPos = self._deps.offsetToLineColumnConverter.offsetToLineColumn(rawLocation, rawLocation.file, self._deps.compiler.lastCompilationResult.source.sources) + self._components.sourceHighlighter.currentSourceLocation(lineColumnPos, rawLocation) + } debug (hash, cb) { - const self = this - self._deps.app.startdebugging(hash) - if (cb) cb() + var self = this + delete self.d + executionContext.web3().eth.getTransaction(hash, (error, tx) => { + if (error) return cb(error) + var debugSession = new RemixDebug({ + compilationResult: () => { + return self._deps.compiler.lastCompilationResult.data + } + }) + debugSession.addProvider('web3', executionContext.web3()) + debugSession.switchProvider('web3') + debugSession.debug(tx) + self.d = debugSession + this._components.terminal.commands.log('A new debugging session is available at remix.d') + if (cb) cb(null, debugSession) + // helpers + self.d.highlight = (address, vmtraceIndex) => { + if (!address) return self.highlight() + self.d.sourceLocationFromVMTraceIndex(address, vmtraceIndex, (error, rawLocation) => { + if (!error && rawLocation) { + self.highlight(rawLocation) + } + }) + } + self.d.stateAt = (vmTraceIndex) => { + self.d.extractStateAt(vmTraceIndex, (error, state) => { + if (error) return self.log(error) + self.d.decodeStateAt(vmTraceIndex, state, (error, state) => { + if (error) return this._components.terminal.commands.html(error) + var treeView = new TreeView({ + json: true, + formatSelf: solidityTypeFormatter.formatSelf, + extractData: solidityTypeFormatter.extractData + }) + self.log('State at ' + vmTraceIndex) + self._components.terminal.commands.html(treeView.render(state, true)) + }) + }) + } + self.d.localsAt = (contractAddress, vmTraceIndex) => { + debugSession.sourceLocationFromVMTraceIndex(contractAddress, vmTraceIndex, (error, location) => { + if (error) return self.log(error) + debugSession.decodeLocalsAt(23, location, (error, locals) => { + if (error) return this._components.terminal.commands.html(error) + var treeView = new TreeView({ + json: true, + formatSelf: solidityTypeFormatter.formatSelf, + extractData: solidityTypeFormatter.extractData + }) + self.log('Locals at ' + vmTraceIndex) + self._components.terminal.commands.html(treeView.render(locals, true)) + }) + }) + } + self.d.goTo = (row) => { + if (self._deps.editor.current()) { + var breakPoint = new remixCore.code.BreakpointManager(self.d, (sourceLocation) => { + return self._deps.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, self._deps.compiler.lastCompilationResult.source.sources) + }) + breakPoint.event.register('breakpointHit', (sourceLocation, currentStep) => { + self.log(null, 'step index ' + currentStep) + self.highlight(sourceLocation) + self.d.stateAt(currentStep) + self.d.traceManager.getCurrentCalledAddressAt(currentStep, (error, address) => { + if (error) return self.log(address) + self.d.localsAt(address, currentStep) + }) + }) + breakPoint.event.register('NoBreakpointHit', () => { self.log('line ' + row + ' is not part of the current execution') }) + breakPoint.add({fileName: self._deps.editor.current(), row: row - 1}) + breakPoint.jumpNextBreakpoint(0, true) + } + } + }) } loadgist (id, cb) { const self = this @@ -122,6 +212,33 @@ class CmdInterpreterAPI { if (cb) cb() return '' } + debugHelp (cb) { + const self = this + var help = yo`
Here are some examples of scripts that can be run (using remix.exeCurrent() or directly from the console)
` + help.appendChild(yo`
`) + help.appendChild(yo`
remix.debug('0x3c247ac268afb9a9c183feb9d4e83df51efbc8a2f4624c740789b788dac43029', function (error, debugSession) { + remix.d = debugSession + remix.log = function () { arguments[0] != null ? console.log(arguments[0]) : console.log(arguments[1]) } + + remix.d.traceManager.getLength(remix.log) + remix.storageView = remix.d.storageViewAt(97, '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a') + console.log('storage at 97 :') + remix.storageView.storageRange(remix.log) +})
`) + help.appendChild(yo`
remix.log = function () { arguments[0] != null ? console.log(arguments[0]) : console.log(arguments[1]) } + remix.d.extractStateAt(2, function (error, state) { + remix.d.decodeStateAt(97, state, remix.log) + })
`) + help.appendChild(yo`
`) + help.appendChild(yo`
remix.highlight(contractAddress, vmTraceIndex)
`) + help.appendChild(yo`
`) + help.appendChild(yo`
remix.stateAt(vmTraceIndex)
`) + help.appendChild(yo`
`) + help.appendChild(yo`
remix.localsAt(vmTraceIndex)
`) + self._components.terminal.commands.html(help) + if (cb) cb() + return '' + } } module.exports = CmdInterpreterAPI From ec10ae7ecad25829d31f1b7874e8ccfa907e47f7 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 2 Aug 2018 16:05:59 +0200 Subject: [PATCH 2/3] typo --- src/lib/cmdInterpreterAPI.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/cmdInterpreterAPI.js b/src/lib/cmdInterpreterAPI.js index 456008165e..aa6190dd61 100644 --- a/src/lib/cmdInterpreterAPI.js +++ b/src/lib/cmdInterpreterAPI.js @@ -92,7 +92,7 @@ class CmdInterpreterAPI { self.d.localsAt = (contractAddress, vmTraceIndex) => { debugSession.sourceLocationFromVMTraceIndex(contractAddress, vmTraceIndex, (error, location) => { if (error) return self.log(error) - debugSession.decodeLocalsAt(23, location, (error, locals) => { + debugSession.decodeLocalsAt(23, location, (error, locals) => { if (error) return this._components.terminal.commands.html(error) var treeView = new TreeView({ json: true, From 412e1599756a2a1b58d774d694773ad9b879c41f Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 22 Aug 2018 15:13:37 +0200 Subject: [PATCH 3/3] fix tests --- src/lib/cmdInterpreterAPI.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/cmdInterpreterAPI.js b/src/lib/cmdInterpreterAPI.js index aa6190dd61..52de828154 100644 --- a/src/lib/cmdInterpreterAPI.js +++ b/src/lib/cmdInterpreterAPI.js @@ -2,7 +2,6 @@ var yo = require('yo-yo') var async = require('async') var remixLib = require('remix-lib') -var remixCore = require('remix-core') var EventManager = remixLib.EventManager var executionContext = require('../execution-context') @@ -106,7 +105,7 @@ class CmdInterpreterAPI { } self.d.goTo = (row) => { if (self._deps.editor.current()) { - var breakPoint = new remixCore.code.BreakpointManager(self.d, (sourceLocation) => { + var breakPoint = new remixLib.code.BreakpointManager(self.d, (sourceLocation) => { return self._deps.offsetToLineColumnConverter.offsetToLineColumn(sourceLocation, sourceLocation.file, self._deps.compiler.lastCompilationResult.source.sources) }) breakPoint.event.register('breakpointHit', (sourceLocation, currentStep) => {