remix-project mirror
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
remix-project/remix-debug/src/Ethdebugger.js

147 lines
4.9 KiB

7 years ago
'use strict'
var remixCore = require('remix-core')
var TraceManager = remixCore.trace.TraceManager
var remixLib = require('remix-lib')
var global = remixLib.global
var init = remixLib.init
var executionContext = remixLib.execution.executionContext
var EventManager = remixLib.EventManager
var Web3Providers = remixLib.vm.Web3Providers
var DummyProvider = remixLib.vm.DummyProvider
var CodeManager = remixCore.code.CodeManager
var remixSolidity = require('remix-solidity')
var SolidityProxy = remixSolidity.SolidityProxy
var InternalCallTree = remixSolidity.InternalCallTree
/**
* Ethdebugger is a wrapper around a few classes that helps debugging a transaction
*
* - Web3Providers - define which environment (web3) the transaction will be retrieved from
* - TraceManager - Load / Analyze the trace and retrieve details of specific test
* - CodeManager - Retrieve loaded byte code and help to resolve AST item from vmtrace index
* - SolidityProxy - Basically used to extract state variable from AST
* - Breakpoint Manager - Used to add / remove / jumpto breakpoint
* - InternalCallTree - Used to retrieved local variables
*
* @param {Map} opts - { function compilationResult } //
*/
function Ethdebugger (opts) {
this.opts = opts || {}
if (!this.opts.compilationResult) this.opts.compilationResult = () => { return null }
var self = this
this.event = new EventManager()
this.tx
this.web3Providers = new Web3Providers()
this.addProvider('DUMMYWEB3', new DummyProvider())
this.switchProvider('DUMMYWEB3')
this.traceManager = new TraceManager()
this.codeManager = new CodeManager(this.traceManager)
this.solidityProxy = new SolidityProxy(this.traceManager, this.codeManager)
this.callTree = new InternalCallTree(this.event, this.traceManager, this.solidityProxy, this.codeManager, { includeLocalVariables: true })
this.event.register('indexChanged', this, function (index) {
self.codeManager.resolveStep(index, self.tx)
})
}
Ethdebugger.prototype.sourceLocationFromVMTraceIndex = function (address, stepIndex, callback) {
this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts, (error, rawLocation) => {
callback(error, rawLocation)
})
}
Ethdebugger.prototype.sourceLocationFromInstructionIndex = function (address, instIndex, callback) {
this.debugger.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, instIndex, this.solidityProxy.contracts, function (error, rawLocation) {
callback(error, rawLocation)
})
}
Ethdebugger.prototype.setBreakpointManager = function (breakpointManager) {
this.breakpointManager = breakpointManager
}
Ethdebugger.prototype.resolveStep = function (index) {
this.codeManager.resolveStep(index, this.tx)
}
Ethdebugger.prototype.web3 = function () {
return global.web3
}
Ethdebugger.prototype.addProvider = function (type, obj) {
this.web3Providers.addProvider(type, obj)
this.event.trigger('providerAdded', [type])
}
Ethdebugger.prototype.switchProvider = function (type) {
var self = this
this.web3Providers.get(type, function (error, obj) {
if (error) {
console.log('provider ' + type + ' not defined')
} else {
global.web3 = obj
executionContext.detectNetwork((error, network) => {
if (error || !network) {
global.web3Debug = obj
} else {
var webDebugNode = init.web3DebugNode(network.name)
global.web3Debug = !webDebugNode ? obj : webDebugNode
}
})
self.event.trigger('providerChanged', [type])
}
})
}
Ethdebugger.prototype.setCompilationResult = function (compilationResult) {
if (compilationResult && compilationResult.sources && compilationResult.contracts) {
this.solidityProxy.reset(compilationResult)
} else {
this.solidityProxy.reset({})
}
}
Ethdebugger.prototype.debug = function (tx) {
this.setCompilationResult(this.opts.compilationResult())
if (tx instanceof Object) {
this.txBrowser.load(tx.hash)
} else if (tx instanceof String) {
this.txBrowser.load(tx)
}
}
Ethdebugger.prototype.unLoad = function () {
this.traceManager.init()
this.codeManager.clear()
this.stepManager.reset()
this.event.trigger('traceUnloaded')
}
Ethdebugger.prototype.debug = function (blockNumber, txIndex, tx) {
if (this.traceManager.isLoading) {
return
}
this.setCompilationResult(this.opts.compilationResult())
console.log('loading trace...')
this.tx = tx
var self = this
this.traceManager.resolveTrace(tx, function (error, result) {
console.log('trace loaded ' + result)
if (result) {
self.event.trigger('newTraceLoaded', [self.traceManager.trace])
if (self.breakpointManager && self.breakpointManager.hasBreakpoint()) {
self.breakpointManager.jumpNextBreakpoint(false)
}
} else {
self.statusMessage = error ? error.message : 'Trace not loaded'
}
})
}
module.exports = Ethdebugger