keep track of stop/revert/return indexes and outofgad indexes

pull/5370/head
yann300 3 years ago committed by joseph izang
parent 287f29be8c
commit dc598fe9bb
  1. 30
      libs/remix-debug/src/code/codeManager.ts
  2. 4
      libs/remix-debug/src/debugger/VmDebugger.ts
  3. 11
      libs/remix-debug/src/trace/traceAnalyser.ts
  4. 14
      libs/remix-debug/src/trace/traceCache.ts
  5. 8
      libs/remix-debug/src/trace/traceManager.ts
  6. 2
      libs/remix-lib/src/web3Provider/web3VmProvider.ts
  7. 69
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx
  8. 14
      libs/remix-ui/debugger-ui/src/reducers/assembly-items.ts

@ -145,17 +145,37 @@ export class CodeManager {
})
}
private retrieveIndexAndTrigger (codeMananger, address, step, code) {
private async retrieveIndexAndTrigger (codeMananger, address, step, code) {
let result
let next
let returnInstructionIndexes = []
let outOfGasInstructionIndexes = []
try {
result = codeMananger.getInstructionIndex(address, step)
next = codeMananger.getInstructionIndex(address, step + 1)
} catch (error) {
return console.log(error)
}
let values = this.traceManager.getAllStopIndexes()
values = values.filter((value) => value.address === address)
if (values) {
for (const value of values) {
returnInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address })
}
}
values = this.traceManager.getAllOutofGasIndexes()
values = values.filter((value) => value.address === address)
if (values) {
for (const value of values) {
outOfGasInstructionIndexes.push({ instructionIndex: this.getInstructionIndex(address, value.index), address })
}
}
} catch (error) {
return console.log(error)
}
try {
codeMananger.event.trigger('changed', [code, address, result, next])
codeMananger.event.trigger('changed', [code, address, result, next, returnInstructionIndexes, outOfGasInstructionIndexes])
} catch (e) {
console.log('dispatching event failed', e)
}

@ -59,8 +59,8 @@ export class VmDebuggerLogic {
}
listenToCodeManagerEvents () {
this._codeManager.event.register('changed', (code, address, index, nextIndex) => {
this.event.trigger('codeManagerChanged', [code, address, index, nextIndex])
this._codeManager.event.register('changed', (code, address, index, nextIndex, returnInstructionIndexes, outOfGasInstructionIndexes) => {
this.event.trigger('codeManagerChanged', [code, address, index, nextIndex, returnInstructionIndexes, outOfGasInstructionIndexes])
})
}

@ -49,6 +49,17 @@ export class TraceAnalyser {
this.traceCache.pushReturnValue(index, returnParamsObj)
}
if (traceHelper.isReturnInstruction(step) || traceHelper.isStopInstruction(step) || traceHelper.isRevertInstruction(step)) {
this.traceCache.pushStopIndex(index, this.traceCache.currentCall.call.address)
}
try {
if (parseInt(step.gas) - parseInt(step.gasCost) <= 0 || step.error === 'OutOfGas') {
this.traceCache.pushOutOfGasIndex(index, this.traceCache.currentCall.call.address)
}
} catch (e) {
console.error(e)
}
}
buildCalldata (index, step, tx, newContext) {

@ -5,6 +5,8 @@ const { sha3_256 } = util
export class TraceCache {
returnValues
stopIndexes
outofgasIndexes
currentCall
callsTree
callsData
@ -24,6 +26,8 @@ export class TraceCache {
// ...Changes contains index in the vmtrace of the corresponding changes
this.returnValues = {}
this.stopIndexes = []
this.outofgasIndexes = []
this.currentCall = null
this.callsTree = null
this.callsData = {}
@ -59,7 +63,7 @@ export class TraceCache {
this.currentCall.call.reverted = reverted
}
var parent = this.currentCall.parent
this.currentCall = parent ? { call: parent.call, parent: parent.parent } : null
if (parent) this.currentCall = { call: parent.call, parent: parent.parent }
return
}
const call = {
@ -78,6 +82,14 @@ export class TraceCache {
this.currentCall = { call: call, parent: this.currentCall }
}
pushOutOfGasIndex (index, address) {
this.outofgasIndexes.push({ index, address })
}
pushStopIndex (index, address) {
this.stopIndexes.push({ index, address })
}
pushReturnValue (step, value) {
this.returnValues[step] = value
}

@ -209,6 +209,14 @@ export class TraceManager {
return this.trace[stepIndex].pc
}
getAllStopIndexes () {
return this.traceCache.stopIndexes
}
getAllOutofGasIndexes () {
return this.traceCache.outofgasIndexes
}
getReturnValue (stepIndex) {
try {
this.checkRequestedStep(stepIndex)

@ -138,7 +138,7 @@ export class Web3VmProvider {
async txProcessed (data) {
const lastOp = this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1]
if (lastOp) {
lastOp.error = lastOp.op !== 'RETURN' && lastOp.op !== 'STOP' && lastOp.op !== 'thisDESTRUCT'
lastOp.error = lastOp.op !== 'RETURN' && lastOp.op !== 'STOP' && lastOp.op !== 'DESTRUCT'
}
this.vmTraces[this.processingHash].gas = '0x' + data.gasUsed.toString(16)

@ -7,12 +7,14 @@ export const AssemblyItems = ({ registerEvent }) => {
const [absoluteSelectedIndex, setAbsoluteSelectedIndex] = useState(0)
const [selectedItem, setSelectedItem] = useState(0)
const [nextSelectedItem, setNextSelectedItem] = useState(1)
const [returnInstructionIndexes, setReturnInstructionIndexes] = useState([])
const [outOfGasInstructionIndexes, setOutOfGasInstructionIndexes] = useState([])
const refs = useRef({})
const asmItemsRef = useRef(null)
useEffect(() => {
registerEvent && registerEvent('codeManagerChanged', (code, address, index, nextIndex) => {
dispatch({ type: 'FETCH_OPCODES_SUCCESS', payload: { code, address, index, nextIndex } })
registerEvent && registerEvent('codeManagerChanged', (code, address, index, nextIndex, returnInstructionIndexes, outOfGasInstructionIndexes) => {
dispatch({ type: 'FETCH_OPCODES_SUCCESS', payload: { code, address, index, nextIndex, returnInstructionIndexes, outOfGasInstructionIndexes } })
})
}, [])
@ -22,6 +24,8 @@ export const AssemblyItems = ({ registerEvent }) => {
clearItems()
indexChanged(assemblyItems.index)
nextIndexChanged(assemblyItems.nextIndex)
returnIndexes(assemblyItems.returnInstructionIndexes)
outOfGasIndexes(assemblyItems.outOfGasInstructionIndexes)
}
}, [assemblyItems.opCodes.index])
@ -45,10 +49,37 @@ export const AssemblyItems = ({ registerEvent }) => {
currentItem.firstChild.removeAttribute('style')
}
}
returnInstructionIndexes.map((index) => {
if (index < 0) return
currentItem = refs.current[index] ? refs.current[index] : null
if (currentItem) {
currentItem.removeAttribute('selected')
currentItem.removeAttribute('style')
if (currentItem.firstChild) {
currentItem.firstChild.removeAttribute('style')
}
}
})
outOfGasInstructionIndexes.map((index) => {
if (index < 0) return
currentItem = refs.current[index] ? refs.current[index] : null
if (currentItem) {
currentItem.removeAttribute('selected')
currentItem.removeAttribute('style')
if (currentItem.firstChild) {
currentItem.firstChild.removeAttribute('style')
}
}
})
}
const indexChanged = (index: number) => {
console.log('index ' + index)
if (index < 0) return
const codeView = asmItemsRef.current
@ -79,6 +110,38 @@ export const AssemblyItems = ({ registerEvent }) => {
setNextSelectedItem(index)
}
const returnIndexes = (indexes) => {
indexes.map((index) => {
if (index < 0) return
const codeView = asmItemsRef.current
const currentItem = codeView.children[index]
if (currentItem) {
currentItem.style.setProperty('border-color', 'var(--warning)')
currentItem.style.setProperty('border-style', 'dotted')
currentItem.setAttribute('selected', 'selected')
}
})
setReturnInstructionIndexes(indexes)
}
const outOfGasIndexes = (indexes) => {
indexes.map((index) => {
if (index < 0) return
const codeView = asmItemsRef.current
const currentItem = codeView.children[index]
if (currentItem) {
currentItem.style.setProperty('border-color', 'var(--danger)')
currentItem.style.setProperty('border-style', 'dotted')
currentItem.setAttribute('selected', 'selected')
}
})
setOutOfGasInstructionIndexes(indexes)
}
return (
<div className="border rounded px-1 mt-1 bg-light">
<div className='dropdownpanel'>

@ -14,6 +14,8 @@ export const initialState = {
display: [],
index: 0,
nextIndex: -1,
returnInstructionIndexes: [],
outOfGasInstructionIndexes: [],
top: 0,
bottom: 0,
isRequesting: false,
@ -21,7 +23,7 @@ export const initialState = {
hasError: null
}
const reducedOpcode = (opCodes) => {
const reducedOpcode = (opCodes, payload) => {
const length = 100
let bottom = opCodes.index - 10
bottom = bottom < 0 ? 0 : bottom
@ -29,7 +31,9 @@ const reducedOpcode = (opCodes) => {
return {
index: opCodes.index - bottom,
nextIndex: opCodes.nextIndex - bottom,
display: opCodes.code.slice(bottom, top)
display: opCodes.code.slice(bottom, top),
returnInstructionIndexes: payload.returnInstructionIndexes.map((index) => index.instructionIndex - bottom ),
outOfGasInstructionIndexes: payload.outOfGasInstructionIndexes.map((index) => index.instructionIndex - bottom )
}
}
@ -48,7 +52,7 @@ export const reducer = (state = initialState, action: Action) => {
...state.opCodes, index: action.payload.index, nextIndex: action.payload.nextIndex
} : deepEqual(action.payload.code, state.opCodes.code) ? state.opCodes : action.payload
const reduced = reducedOpcode(opCodes)
const reduced = reducedOpcode(opCodes, action.payload)
return {
opCodes,
display: reduced.display,
@ -56,7 +60,9 @@ export const reducer = (state = initialState, action: Action) => {
nextIndex: reduced.nextIndex,
isRequesting: false,
isSuccessful: true,
hasError: null
hasError: null,
returnInstructionIndexes: reduced.returnInstructionIndexes,
outOfGasInstructionIndexes: reduced.outOfGasInstructionIndexes
}
}
case 'FETCH_OPCODES_ERROR': {

Loading…
Cancel
Save