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/libs/remix-debug/src/Ethdebugger.ts

173 lines
6.0 KiB

7 years ago
'use strict'
import { StorageViewer } from './storage/storageViewer'
import { StorageResolver } from './storage/storageResolver'
import { TraceManager } from './trace/traceManager'
import { CodeManager } from './code/codeManager'
import { contractCreationToken } from './trace/traceHelper'
import { EventManager } from './eventManager'
import { SolidityProxy, stateDecoder, localDecoder, InternalCallTree } from './solidity-decoder'
7 years ago
/**
* 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
* - StorageResolver - Help resolving the storage accross different steps
7 years ago
*
* @param {Map} opts - { function compilationResult } //
*/
4 years ago
export class Ethdebugger {
compilationResult
web3
opts
event
tx
traceManager
codeManager
solidityProxy
storageResolver
callTree
breakpointManager
statusMessage
constructor (opts) {
this.compilationResult = opts.compilationResult || function (contractAddress) { return null }
this.web3 = opts.web3
this.opts = opts
this.event = new EventManager()
this.traceManager = new TraceManager({ web3: this.web3 })
4 years ago
this.codeManager = new CodeManager(this.traceManager)
this.solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager) })
4 years ago
this.storageResolver = null
const includeLocalVariables = true
this.callTree = new InternalCallTree(this.event,
this.traceManager,
this.solidityProxy,
this.codeManager,
{ ...opts, includeLocalVariables })
4 years ago
}
4 years ago
setManagers () {
this.traceManager = new TraceManager({ web3: this.web3 })
4 years ago
this.codeManager = new CodeManager(this.traceManager)
this.solidityProxy = new SolidityProxy({ getCurrentCalledAddressAt: this.traceManager.getCurrentCalledAddressAt.bind(this.traceManager), getCode: this.codeManager.getCode.bind(this.codeManager) })
4 years ago
this.storageResolver = null
const includeLocalVariables = true
this.callTree = new InternalCallTree(this.event,
this.traceManager,
this.solidityProxy,
this.codeManager,
{ ...this.opts, includeLocalVariables })
4 years ago
this.event.trigger('managersChanged')
}
7 years ago
4 years ago
resolveStep (index) {
this.codeManager.resolveStep(index, this.tx)
}
7 years ago
4 years ago
setCompilationResult (compilationResult) {
this.solidityProxy.reset((compilationResult && compilationResult.data) || {})
}
4 years ago
async sourceLocationFromVMTraceIndex (address, stepIndex) {
return this.callTree.sourceLocationTracker.getSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts)
}
7 years ago
4 years ago
async getValidSourceLocationFromVMTraceIndex (address, stepIndex) {
return this.callTree.sourceLocationTracker.getValidSourceLocationFromVMTraceIndex(address, stepIndex, this.solidityProxy.contracts)
}
4 years ago
4 years ago
async sourceLocationFromInstructionIndex (address, instIndex, callback) {
return this.callTree.sourceLocationTracker.getSourceLocationFromInstructionIndex(address, instIndex, this.solidityProxy.contracts)
}
7 years ago
4 years ago
/* breakpoint */
setBreakpointManager (breakpointManager) {
this.breakpointManager = breakpointManager
}
7 years ago
4 years ago
/* decode locals */
extractLocalsAt (step) {
return this.callTree.findScope(step)
}
4 years ago
async decodeLocalsAt (step, sourceLocation, callback) {
try {
4 years ago
const stack = this.traceManager.getStackAt(step)
const memory = this.traceManager.getMemoryAt(step)
const address = this.traceManager.getCurrentCalledAddressAt(step)
const calldata = this.traceManager.getCallDataAt(step)
4 years ago
try {
const storageViewer = new StorageViewer({ stepIndex: step, tx: this.tx, address: address }, this.storageResolver, this.traceManager)
const locals = await localDecoder.solidityLocals(step, this.callTree, stack, memory, storageViewer, calldata, sourceLocation, null)
if (locals['error']) {
return callback(locals['error'])
4 years ago
}
return callback(null, locals)
} catch (e) {
callback(e.message)
}
4 years ago
} catch (error) {
callback(error)
}
}
4 years ago
/* decode state */
async extractStateAt (step) {
return this.solidityProxy.extractStateVariablesAt(step)
}
4 years ago
async decodeStateAt (step, stateVars, callback) {
try {
const address = this.traceManager.getCurrentCalledAddressAt(step)
const storageViewer = new StorageViewer({ stepIndex: step, tx: this.tx, address: address }, this.storageResolver, this.traceManager)
4 years ago
const result = await stateDecoder.decodeState(stateVars, storageViewer)
return result
} catch (error) {
callback(error)
}
}
7 years ago
4 years ago
storageViewAt (step, address) {
return new StorageViewer({ stepIndex: step, tx: this.tx, address: address }, this.storageResolver, this.traceManager)
4 years ago
}
7 years ago
4 years ago
updateWeb3 (web3) {
this.web3 = web3
this.setManagers()
}
7 years ago
4 years ago
unLoad () {
this.traceManager.init()
this.codeManager.clear()
this.event.trigger('traceUnloaded')
7 years ago
}
4 years ago
debug (tx) {
if (this.traceManager.isLoading) {
return
7 years ago
}
tx.to = tx.to || contractCreationToken('0')
4 years ago
this.tx = tx
this.traceManager.resolveTrace(tx).then(async (result) => {
this.setCompilationResult(await this.compilationResult(tx.to))
this.event.trigger('newTraceLoaded', [this.traceManager.trace])
if (this.breakpointManager && this.breakpointManager.hasBreakpoint()) {
this.breakpointManager.jumpNextBreakpoint(false)
}
this.storageResolver = new StorageResolver({ web3: this.traceManager.web3 })
4 years ago
}).catch((error) => {
this.statusMessage = error ? error.message : 'Trace not loaded'
})
}
7 years ago
}