Merge pull request #573 from ethereum/fixGetTrace

Fix Debugger plugin API
pull/5370/head
yann300 4 years ago committed by GitHub
commit 9a4c2b7dff
  1. 45
      apps/remix-ide-e2e/src/tests/debugger.test.ts
  2. 5
      apps/remix-ide/src/app.js
  3. 56
      apps/remix-ide/src/app/tabs/debugger-tab.js
  4. 4
      libs/remix-debug/src/code/codeManager.js
  5. 2
      libs/remix-debug/src/solidity-decoder/internalCallTree.js
  6. 19
      libs/remix-debug/src/trace/traceRetriever.js
  7. 70
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  8. 5
      package-lock.json

@ -178,6 +178,33 @@ module.exports = {
.getEditorValue((content) => {
browser.assert.ok(content.indexOf('if slt(sub(dataEnd, headStart), 32) { revert(0, 0) }') != -1, 'current displayed content is not a generated source')
})
.click('*[data-id="debuggerTransactionStartButton"]')
},
'Should call the debugger api: getTrace': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsGetTrace.js', { content: jsGetTrace })
.executeScript('remix.exeCurrent()')
.pause(3000)
.journalChildIncludes(`{ "gas": "0x2dc6c0", "return": "0x", "structLogs":`)
},
'Should call the debugger api: debug': function (browser: NightwatchBrowser) {
browser
.addFile('test_jsDebug.js', { content: jsDebug })
.executeScript('remix.exeCurrent()')
.pause(3000)
.clickLaunchIcon('debugger')
.waitForElementVisible('*[data-id="slider"]')
.click('*[data-id="slider"]')
.setValue('*[data-id="slider"]', '5')
.pause(1000)
/*
setting the slider to 5 leads to "vm trace step: 91" for chrome and "vm trace step: 92" for firefox
=> There is something going wrong with the nightwatch API here.
As we are only testing if debugger is active, this is ok to keep that for now.
*/
.assert.containsText('*[data-id="stepdetail"]', 'vm trace step:\n9')
.end()
},
@ -335,3 +362,21 @@ const localVariable_step717_ABIEncoder = {
"type": "bytes"
}
}
const jsGetTrace = `(async () => {
try {
const result = await remix.call('debugger', 'getTrace', '0xb175c3c9a9cd6bee3b6cc8be3369a945ac9611516005f8cba27a43486ff2bc50')
console.log('result ', result)
} catch (e) {
console.log(e.message)
}
})()`
const jsDebug = `(async () => {
try {
const result = await remix.call('debugger', 'debug', '0xb175c3c9a9cd6bee3b6cc8be3369a945ac9611516005f8cba27a43486ff2bc50')
console.log('result ', result)
} catch (e) {
console.log(e.message)
}
})()`

@ -370,7 +370,10 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
registry.get('fileproviders/browser').api,
)
const analysis = new AnalysisTab(registry)
const debug = new DebuggerTab(blockchain)
const debug = new DebuggerTab(
blockchain,
registry.get('editor').api,
registry.get('offsettolinecolumnconverter').api)
const test = new TestTab(
registry.get('filemanager').api,
registry.get('offsettolinecolumnconverter').api,

@ -3,6 +3,7 @@ const css = require('./styles/debugger-tab-styles')
import toaster from '../ui/tooltip'
import { DebuggerUI } from '@remix-ui/debugger-ui'
import { ViewPlugin } from '@remixproject/engine'
import remixDebug, { TransactionDebugger as Debugger } from '@remix-project/remix-debug'
import * as packageJson from '../../../../../package.json'
import React from 'react'
import ReactDOM from 'react-dom'
@ -22,13 +23,15 @@ const profile = {
class DebuggerTab extends ViewPlugin {
constructor (blockchain) {
constructor (blockchain, editor, offsetToLineColumnConverter) {
super(profile)
this.el = null
this.editor = editor
this.offsetToLineColumnConverter = offsetToLineColumnConverter
this.blockchain = blockchain
this.debugHash = null
this.getTraceHash = null
this.removeHighlights = false
this.debugHashRequest = 0
}
render () {
@ -81,12 +84,55 @@ class DebuggerTab extends ViewPlugin {
debug (hash) {
this.debugHash = hash
this.debugHashRequest++ // so we can trigger a debug using the same hash 2 times in a row. that's needs to be improved
this.renderComponent()
}
getTrace (hash) {
this.getTraceHash = hash
this.renderComponent()
getDebugWeb3 () {
return new Promise((resolve, reject) => {
this.blockchain.detectNetwork((error, network) => {
let web3
if (error || !network) {
web3 = remixDebug.init.web3DebugNode(this.blockchain.web3())
} else {
const webDebugNode = remixDebug.init.web3DebugNode(network.name)
web3 = !webDebugNode ? this.blockchain.web3() : webDebugNode
}
remixDebug.init.extendWeb3(web3)
resolve(web3)
})
})
}
async getTrace (hash) {
if (!hash) return
try {
const web3 = await this.getDebugWeb3()
const currentReceipt = await web3.eth.getTransactionReceipt(hash)
const debug = new Debugger({
web3,
offsetToLineColumnConverter: this.offsetToLineColumnConverter,
compilationResult: async (address) => {
try {
return await this.fetchContractAndCompile(address, currentReceipt)
} catch (e) {
console.error(e)
}
return null
},
debugWithGeneratedSources: false
})
return await debug.debugger.traceManager.getTrace(hash)
} catch (e) {
throw e
}
}
fetchContractAndCompile (address, receipt) {
const target = (address && remixDebug.traceHelper.isContractCreation(address)) ? receipt.contractAddress : address
return this.call('fetchAndCompile', 'resolve', target || receipt.contractAddress || receipt.to, '.debug', this.blockchain.web3())
}
// debugger () {

@ -142,7 +142,11 @@ function retrieveIndexAndTrigger (codeMananger, address, step, code) {
} catch (error) {
return console.log(error)
}
try {
codeMananger.event.trigger('changed', [code, address, result])
} catch (e) {
console.log('dispatching event failed', e)
}
}
module.exports = CodeManager

@ -292,7 +292,7 @@ async function includeVariableDeclaration (tree, step, sourceLocation, scopeId,
// }
// }
// input params
if (inputs) {
if (inputs && inputs.parameters) {
functionDefinitionAndInputs.inputs = addParams(inputs, tree, scopeId, states, contractObj.name, previousSourceLocation, stack.length, inputs.parameters.length, -1)
}
// output params

@ -1,19 +0,0 @@
'use strict'
function TraceRetriever (options) {
this.web3 = options.web3
}
TraceRetriever.prototype.getTrace = function (txHash, callback) {
const options = {
disableStorage: true,
disableMemory: false,
disableStack: false,
fullStorage: false
}
this.web3.debug.traceTransaction(txHash, options, function (error, result) {
callback(error, result)
})
}
module.exports = TraceRetriever

@ -5,11 +5,9 @@ import VmDebugger from './vm-debugger/vm-debugger'
import VmDebuggerHead from './vm-debugger/vm-debugger-head'
import remixDebug, { TransactionDebugger as Debugger } from '@remix-project/remix-debug'
/* eslint-disable-next-line */
import globalRegistry from '../../../../../apps/remix-ide/src/global/registry'
import './debugger-ui.css'
export const DebuggerUI = ({ debuggerModule }) => {
const init = remixDebug.init
const [state, setState] = useState({
isActive: false,
statusMessage: '',
@ -31,12 +29,10 @@ export const DebuggerUI = ({ debuggerModule }) => {
}, [])
useEffect(() => {
if (debuggerModule.debugHash) {
debug(debuggerModule.debugHash)
}, [debuggerModule.debugHash])
useEffect(() => {
getTrace(debuggerModule.getTraceHash)
}, [debuggerModule.getTraceHash])
}
}, [debuggerModule.debugHashRequest])
useEffect(() => {
if (debuggerModule.removeHighlights) deleteHighlights()
@ -44,7 +40,7 @@ export const DebuggerUI = ({ debuggerModule }) => {
useEffect(() => {
const setEditor = () => {
const editor = globalRegistry.get('editor').api
const editor = debuggerModule.editor
editor.event.register('breakpointCleared', (fileName, row) => {
if (state.debugger) state.debugger.breakPointManager.remove({fileName: fileName, row: row})
@ -64,12 +60,6 @@ export const DebuggerUI = ({ debuggerModule }) => {
setEditor()
}, [state.debugger])
const fetchContractAndCompile = (address, receipt) => {
const target = (address && remixDebug.traceHelper.isContractCreation(address)) ? receipt.contractAddress : address
return debuggerModule.call('fetchAndCompile', 'resolve', target || receipt.contractAddress || receipt.to, '.debug', debuggerModule.blockchain.web3())
}
const listenToEvents = (debuggerInstance, currentReceipt) => {
if (!debuggerInstance) return
@ -82,7 +72,7 @@ export const DebuggerUI = ({ debuggerModule }) => {
debuggerInstance.event.register('newSourceLocation', async (lineColumnPos, rawLocation, generatedSources) => {
if (!lineColumnPos) return
const contracts = await fetchContractAndCompile(
const contracts = await debuggerModule.fetchContractAndCompile(
currentReceipt.contractAddress || currentReceipt.to,
currentReceipt)
@ -128,22 +118,6 @@ export const DebuggerUI = ({ debuggerModule }) => {
return state.isActive
}
const getDebugWeb3 = (): Promise<any> => {
return new Promise((resolve, reject) => {
debuggerModule.blockchain.detectNetwork((error, network) => {
let web3
if (error || !network) {
web3 = init.web3DebugNode(debuggerModule.blockchain.web3())
} else {
const webDebugNode = init.web3DebugNode(network.name)
web3 = !webDebugNode ? debuggerModule.blockchain.web3() : webDebugNode
}
init.extendWeb3(web3)
resolve(web3)
})
})
}
const unLoad = () => {
if (state.debugger) state.debugger.unload()
setState(prevState => {
@ -169,14 +143,14 @@ export const DebuggerUI = ({ debuggerModule }) => {
const startDebugging = async (blockNumber, txNumber, tx) => {
if (state.debugger) unLoad()
if (!txNumber) return
const web3 = await getDebugWeb3()
const web3 = await debuggerModule.getDebugWeb3()
const currentReceipt = await web3.eth.getTransactionReceipt(txNumber)
const debuggerInstance = new Debugger({
web3,
offsetToLineColumnConverter: globalRegistry.get('offsettolinecolumnconverter').api,
offsetToLineColumnConverter: debuggerModule.offsetToLineColumnConverter,
compilationResult: async (address) => {
try {
return await fetchContractAndCompile(address, currentReceipt)
return await debuggerModule.fetchContractAndCompile(address, currentReceipt)
} catch (e) {
console.error(e)
}
@ -206,35 +180,7 @@ const debug = (txHash) => {
startDebugging(null, txHash, null)
}
const getTrace = (hash) => {
if (!hash) return
return new Promise(async (resolve, reject) => { /* eslint-disable-line */
const web3 = await getDebugWeb3()
const currentReceipt = await web3.eth.getTransactionReceipt(hash)
const debug = new Debugger({
web3,
offsetToLineColumnConverter: globalRegistry.get('offsettolinecolumnconverter').api,
compilationResult: async (address) => {
try {
return await fetchContractAndCompile(address, currentReceipt)
} catch (e) {
console.error(e)
}
return null
},
debugWithGeneratedSources: false
})
setState(prevState => {
return { ...prevState, currentReceipt }
})
debug.debugger.traceManager.traceRetriever.getTrace(hash, (error, trace) => {
if (error) return reject(error)
resolve(trace)
})
})
}
const deleteHighlights = async () => {
await debuggerModule.call('editor', 'discardHighlight')

5
package-lock.json generated

@ -28127,6 +28127,7 @@
},
"dezalgo": {
"version": "1.0.3",
"resolved": false,
"integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
"requires": {
"asap": "^2.0.0",
@ -28755,6 +28756,7 @@
},
"normalize-git-url": {
"version": "3.0.2",
"resolved": false,
"integrity": "sha1-jl8Uvgva7bc+ByADEKpBbCc1D8Q="
},
"normalize-package-data": {
@ -28792,6 +28794,7 @@
},
"npm-install-checks": {
"version": "3.0.0",
"resolved": false,
"integrity": "sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc=",
"requires": {
"semver": "^2.3.0 || 3.x || 4 || 5"
@ -29138,6 +29141,7 @@
},
"realize-package-specifier": {
"version": "3.0.3",
"resolved": false,
"integrity": "sha1-0N74gpUrjeP2frpekRmWYScfQfQ=",
"requires": {
"dezalgo": "^1.0.1",
@ -29674,6 +29678,7 @@
"dependencies": {
"unique-slug": {
"version": "2.0.0",
"resolved": false,
"integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=",
"requires": {
"imurmurhash": "^0.1.4"

Loading…
Cancel
Save