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 result
let next let next
let returnInstructionIndexes = []
let outOfGasInstructionIndexes = []
try { try {
result = codeMananger.getInstructionIndex(address, step) result = codeMananger.getInstructionIndex(address, step)
next = codeMananger.getInstructionIndex(address, step + 1) 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 { try {
codeMananger.event.trigger('changed', [code, address, result, next]) codeMananger.event.trigger('changed', [code, address, result, next, returnInstructionIndexes, outOfGasInstructionIndexes])
} catch (e) { } catch (e) {
console.log('dispatching event failed', e) console.log('dispatching event failed', e)
} }

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

@ -49,6 +49,17 @@ export class TraceAnalyser {
this.traceCache.pushReturnValue(index, returnParamsObj) 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) { buildCalldata (index, step, tx, newContext) {

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

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

@ -138,7 +138,7 @@ export class Web3VmProvider {
async txProcessed (data) { async txProcessed (data) {
const lastOp = this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1] const lastOp = this.vmTraces[this.processingHash].structLogs[this.processingIndex - 1]
if (lastOp) { 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) this.vmTraces[this.processingHash].gas = '0x' + data.gasUsed.toString(16)

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

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

Loading…
Cancel
Save