|
|
@ -1,15 +1,13 @@ |
|
|
|
var React = require('react'); |
|
|
|
var React = require('react') |
|
|
|
var BasicPanel = require('./basicPanel') |
|
|
|
var BasicPanel = require('./basicPanel') |
|
|
|
var Sticker = require('./sticker') |
|
|
|
var Sticker = require('./sticker') |
|
|
|
var ButtonNavigator = require('./vmTraceButtonNavigator') |
|
|
|
var ButtonNavigator = require('./vmTraceButtonNavigator') |
|
|
|
var codeUtils = require('./codeUtils') |
|
|
|
var codeUtils = require('./codeUtils') |
|
|
|
var style = require('./basicStyles') |
|
|
|
var style = require('./basicStyles') |
|
|
|
var Slider = require('./slider'); |
|
|
|
var Slider = require('./slider') |
|
|
|
|
|
|
|
|
|
|
|
module.exports = React.createClass({ |
|
|
|
module.exports = React.createClass({ |
|
|
|
|
|
|
|
getInitialState: function () { |
|
|
|
getInitialState: function() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return { |
|
|
|
return { |
|
|
|
currentSelected: -1, // current selected item in the vmTrace
|
|
|
|
currentSelected: -1, // current selected item in the vmTrace
|
|
|
|
selectedInst: -1, // current selected item in the contract assembly code
|
|
|
|
selectedInst: -1, // current selected item in the contract assembly code
|
|
|
@ -23,33 +21,45 @@ module.exports = React.createClass({ |
|
|
|
codes: {}, // assembly items instructions list by contract addesses
|
|
|
|
codes: {}, // assembly items instructions list by contract addesses
|
|
|
|
instructionsIndexByBytesOffset: {}, // mapping between bytes offset and instructions index.
|
|
|
|
instructionsIndexByBytesOffset: {}, // mapping between bytes offset and instructions index.
|
|
|
|
callStack: {} |
|
|
|
callStack: {} |
|
|
|
}; |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
getDefaultProps: function()
|
|
|
|
getDefaultProps: function () { |
|
|
|
{ |
|
|
|
|
|
|
|
return { |
|
|
|
return { |
|
|
|
vmTrace: null |
|
|
|
vmTrace: null |
|
|
|
}; |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
render: function()
|
|
|
|
render: function () { |
|
|
|
{
|
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<div style={this.props.vmTrace === null ? style.hidden : style.display}> |
|
|
|
<div style={this.props.vmTrace === null ? style.hidden : style.display}> |
|
|
|
<div style={style.container}><span style={style.address}>Current code: {this.state.currentAddress}</span></div> |
|
|
|
|
|
|
|
<div style={style.container}> |
|
|
|
<div style={style.container}> |
|
|
|
<Slider ref="slider" onChange={this.selectState} min="0" max={this.props.vmTrace ? this.props.vmTrace.length : 0}/> |
|
|
|
<span style={style.address}>Current code: {this.state.currentAddress}</span> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<div style={style.container}> |
|
|
|
|
|
|
|
<Slider |
|
|
|
|
|
|
|
ref='slider' |
|
|
|
|
|
|
|
onChange={this.selectState} |
|
|
|
|
|
|
|
min='0' |
|
|
|
|
|
|
|
max={this.props.vmTrace ? this.props.vmTrace.length : 0} /> |
|
|
|
<ButtonNavigator |
|
|
|
<ButtonNavigator |
|
|
|
vmTraceLength={this.props.vmTrace ? this.props.vmTrace.length : 0} step={this.state.currentSelected} stepIntoBack={this.stepIntoBack}
|
|
|
|
vmTraceLength={this.props.vmTrace ? this.props.vmTrace.length : 0} |
|
|
|
stepIntoForward={this.stepIntoForward} stepOverBack={this.stepOverBack} stepOverForward={this.stepOverForward} /> |
|
|
|
step={this.state.currentSelected} |
|
|
|
|
|
|
|
stepIntoBack={this.stepIntoBack} |
|
|
|
|
|
|
|
stepIntoForward={this.stepIntoForward} |
|
|
|
|
|
|
|
stepOverBack={this.stepOverBack} |
|
|
|
|
|
|
|
stepOverForward={this.stepOverForward} /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div style={style.container}> |
|
|
|
<div style={style.container}> |
|
|
|
<table> |
|
|
|
<table> |
|
|
|
<tbody> |
|
|
|
<tbody> |
|
|
|
<tr> |
|
|
|
<tr> |
|
|
|
<td> |
|
|
|
<td> |
|
|
|
<select size="10" ref='itemsList' style={style.instructionsList} value={this.state.selectedInst}> |
|
|
|
<select |
|
|
|
|
|
|
|
size='10' |
|
|
|
|
|
|
|
ref='itemsList' |
|
|
|
|
|
|
|
style={style.instructionsList} |
|
|
|
|
|
|
|
value={this.state.selectedInst}> |
|
|
|
{this.renderAssemblyItems()} |
|
|
|
{this.renderAssemblyItems()} |
|
|
|
</select> |
|
|
|
</select> |
|
|
|
<div style={Object.assign(style.inline, style.sticker)}> |
|
|
|
<div style={Object.assign(style.inline, style.sticker)}> |
|
|
@ -57,61 +67,74 @@ module.exports = React.createClass({ |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</td> |
|
|
|
</td> |
|
|
|
<td> |
|
|
|
<td> |
|
|
|
<BasicPanel name="CallData" data={this.state.currentCallData} /> |
|
|
|
<BasicPanel name='CallData' data={this.state.currentCallData} /> |
|
|
|
</td> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<tr> |
|
|
|
<td> |
|
|
|
<td> |
|
|
|
<BasicPanel name="Stack" data={this.state.currentStack} /> |
|
|
|
<BasicPanel name='Stack' data={this.state.currentStack} /> |
|
|
|
</td> |
|
|
|
</td> |
|
|
|
<td> |
|
|
|
<td> |
|
|
|
<BasicPanel name="CallStack" data={this.state.currentCallStack} />
|
|
|
|
<BasicPanel name='CallStack' data={this.state.currentCallStack} /> |
|
|
|
</td> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<tr> |
|
|
|
<td> |
|
|
|
<td> |
|
|
|
<BasicPanel name="Storage" data={this.state.currentStorage} renderRow={this.renderStorageRow} /> |
|
|
|
<BasicPanel name='Storage' data={this.state.currentStorage} renderRow={this.renderStorageRow} /> |
|
|
|
</td> |
|
|
|
</td> |
|
|
|
<td> |
|
|
|
<td> |
|
|
|
<BasicPanel name="Memory" data={this.state.currentMemory} renderRow={this.renderMemoryRow} /> |
|
|
|
<BasicPanel name='Memory' data={this.state.currentMemory} renderRow={this.renderMemoryRow} /> |
|
|
|
</td> |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
</tr> |
|
|
|
</tbody> |
|
|
|
</tbody> |
|
|
|
</table> |
|
|
|
</table> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
); |
|
|
|
) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
renderStorageRow: function(data) |
|
|
|
renderStorageRow: function (data) { |
|
|
|
{ |
|
|
|
|
|
|
|
var ret = [] |
|
|
|
var ret = [] |
|
|
|
if (data) |
|
|
|
if (data) { |
|
|
|
{ |
|
|
|
for (var key in data) { |
|
|
|
for (var key in data) |
|
|
|
ret.push( |
|
|
|
ret.push(<tr key={key} ><td>{key}</td><td>{data[key]}</td></tr>) |
|
|
|
<tr key={key}> |
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
|
|
{key} |
|
|
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
|
|
{data[key]} |
|
|
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
</tr>) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return ret |
|
|
|
return ret |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
renderMemoryRow: function(data) |
|
|
|
renderMemoryRow: function (data) { |
|
|
|
{ |
|
|
|
|
|
|
|
var ret = [] |
|
|
|
var ret = [] |
|
|
|
if (data) |
|
|
|
if (data) { |
|
|
|
{ |
|
|
|
for (var key in data) { |
|
|
|
for (var key in data) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var memSlot = data[key] |
|
|
|
var memSlot = data[key] |
|
|
|
ret.push(<tr key={key} ><td>{memSlot.address}</td><td>{memSlot.content.raw}</td><td>{memSlot.content.ascii}</td></tr>) |
|
|
|
ret.push( |
|
|
|
|
|
|
|
<tr key={key}> |
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
|
|
{memSlot.address} |
|
|
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
|
|
{memSlot.content.raw} |
|
|
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
|
|
{memSlot.content.ascii} |
|
|
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
</tr>) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return ret |
|
|
|
return ret |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
resolveAddress: function(address) |
|
|
|
resolveAddress: function (address) { |
|
|
|
{ |
|
|
|
if (!this.state.codes[address]) { |
|
|
|
if (!this.state.codes[address]) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var hexCode = web3.eth.getCode(address) |
|
|
|
var hexCode = web3.eth.getCode(address) |
|
|
|
var code = codeUtils.nameOpCodes(new Buffer(hexCode.substring(2), 'hex')) |
|
|
|
var code = codeUtils.nameOpCodes(new Buffer(hexCode.substring(2), 'hex')) |
|
|
|
this.state.codes[address] = code[0] |
|
|
|
this.state.codes[address] = code[0] |
|
|
@ -119,216 +142,203 @@ module.exports = React.createClass({ |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
renderAssemblyItems: function() |
|
|
|
renderAssemblyItems: function () { |
|
|
|
{ |
|
|
|
if (this.props.vmTrace) { |
|
|
|
if (this.props.vmTrace) |
|
|
|
return this.state.codes[this.state.currentAddress].map(function (item, i) { |
|
|
|
{ |
|
|
|
return <option key={i} value={i}>{item}</option> |
|
|
|
return this.state.codes[this.state.currentAddress].map(function(item, i)
|
|
|
|
}) |
|
|
|
{ |
|
|
|
|
|
|
|
return <option key={i} value={i} >{item}</option>; |
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
componentWillReceiveProps: function (nextProps)
|
|
|
|
componentWillReceiveProps: function (nextProps) { |
|
|
|
{
|
|
|
|
if (!nextProps.vmTrace) { |
|
|
|
if (!nextProps.vmTrace) |
|
|
|
|
|
|
|
return |
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
this.buildCallStack(nextProps.vmTrace) |
|
|
|
this.buildCallStack(nextProps.vmTrace) |
|
|
|
this.setState({"currentSelected": -1}) |
|
|
|
this.setState({'currentSelected': -1}) |
|
|
|
this.updateState(nextProps, 0) |
|
|
|
this.updateState(nextProps, 0) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
buildCallStack: function(vmTrace) |
|
|
|
buildCallStack: function (vmTrace) { |
|
|
|
{ |
|
|
|
if (!vmTrace) { |
|
|
|
if (!vmTrace) |
|
|
|
|
|
|
|
return |
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
var callStack = [] |
|
|
|
var callStack = [] |
|
|
|
var depth = -1 |
|
|
|
var depth = -1 |
|
|
|
for (var k = 0; k < vmTrace.length; k++) |
|
|
|
for (var k = 0; k < vmTrace.length; k++) { |
|
|
|
{ |
|
|
|
|
|
|
|
var trace = vmTrace[k] |
|
|
|
var trace = vmTrace[k] |
|
|
|
if (trace.depth === undefined || trace.depth === depth) |
|
|
|
if (trace.depth === undefined || trace.depth === depth) { |
|
|
|
continue |
|
|
|
continue |
|
|
|
if (trace.depth > depth) |
|
|
|
} |
|
|
|
|
|
|
|
if (trace.depth > depth) { |
|
|
|
callStack.push(trace.address) // new context
|
|
|
|
callStack.push(trace.address) // new context
|
|
|
|
else if (trace.depth < depth) |
|
|
|
} else if (trace.depth < depth) { |
|
|
|
callStack.pop() // returning from context
|
|
|
|
callStack.pop() // returning from context
|
|
|
|
|
|
|
|
} |
|
|
|
depth = trace.depth |
|
|
|
depth = trace.depth |
|
|
|
this.state.callStack[k] = callStack.slice(0) |
|
|
|
this.state.callStack[k] = callStack.slice(0) |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
updateState: function(props, vmTraceIndex) |
|
|
|
updateState: function (props, vmTraceIndex) { |
|
|
|
{ |
|
|
|
if (!props.vmTrace || !props.vmTrace[vmTraceIndex]) { |
|
|
|
if (!props.vmTrace || !props.vmTrace[vmTraceIndex]) |
|
|
|
|
|
|
|
return |
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
var previousIndex = this.state.currentSelected |
|
|
|
var previousIndex = this.state.currentSelected |
|
|
|
var stateChanges = {} |
|
|
|
var stateChanges = {} |
|
|
|
|
|
|
|
|
|
|
|
if (props.vmTrace[vmTraceIndex].stack) // there's always a stack
|
|
|
|
if (props.vmTrace[vmTraceIndex].stack) { // there's always a stack
|
|
|
|
{ |
|
|
|
|
|
|
|
var stack = props.vmTrace[vmTraceIndex].stack |
|
|
|
var stack = props.vmTrace[vmTraceIndex].stack |
|
|
|
stack.reverse() |
|
|
|
stack.reverse() |
|
|
|
stateChanges["currentStack"] = stack |
|
|
|
stateChanges['currentStack'] = stack |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var currentAddress = this.state.currentAddress |
|
|
|
var currentAddress = this.state.currentAddress |
|
|
|
var addressIndex = this.shouldUpdateStateProperty("address", vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
var addressIndex = this.shouldUpdateStateProperty('address', vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
if (addressIndex > -1) |
|
|
|
if (addressIndex > -1) { |
|
|
|
{ |
|
|
|
|
|
|
|
currentAddress = props.vmTrace[addressIndex].address |
|
|
|
currentAddress = props.vmTrace[addressIndex].address |
|
|
|
this.resolveAddress(currentAddress) |
|
|
|
this.resolveAddress(currentAddress) |
|
|
|
Object.assign(stateChanges, { "currentAddress": currentAddress }) |
|
|
|
Object.assign(stateChanges, { 'currentAddress': currentAddress }) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var depthIndex = this.shouldUpdateStateProperty("depth", vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
var depthIndex = this.shouldUpdateStateProperty('depth', vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
if (depthIndex > -1) |
|
|
|
if (depthIndex > -1) { |
|
|
|
Object.assign(stateChanges, { "currentCallStack": this.state.callStack[depthIndex] }) |
|
|
|
Object.assign(stateChanges, { 'currentCallStack': this.state.callStack[depthIndex] }) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var storageIndex = this.shouldUpdateStateProperty("storage", vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
var storageIndex = this.shouldUpdateStateProperty('storage', vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
if (storageIndex > -1) |
|
|
|
if (storageIndex > -1) { |
|
|
|
Object.assign(stateChanges, { "currentStorage": props.vmTrace[storageIndex].storage }) |
|
|
|
Object.assign(stateChanges, { 'currentStorage': props.vmTrace[storageIndex].storage }) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var memoryIndex = this.shouldUpdateStateProperty("memory", vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
var memoryIndex = this.shouldUpdateStateProperty('memory', vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
if (memoryIndex > -1) |
|
|
|
if (memoryIndex > -1) { |
|
|
|
Object.assign(stateChanges, { "currentMemory": this.formatMemory(props.vmTrace[memoryIndex].memory, 16) }) |
|
|
|
Object.assign(stateChanges, { 'currentMemory': this.formatMemory(props.vmTrace[memoryIndex].memory, 16) }) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var callDataIndex = this.shouldUpdateStateProperty("calldata", vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
var callDataIndex = this.shouldUpdateStateProperty('calldata', vmTraceIndex, previousIndex, props.vmTrace) |
|
|
|
if (callDataIndex > -1) |
|
|
|
if (callDataIndex > -1) { |
|
|
|
Object.assign(stateChanges, { "currentCallData": [props.vmTrace[callDataIndex].calldata] }) |
|
|
|
Object.assign(stateChanges, { 'currentCallData': [props.vmTrace[callDataIndex].calldata] }) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
stateChanges["selectedInst"] = this.state.instructionsIndexByBytesOffset[currentAddress][props.vmTrace[vmTraceIndex].pc] |
|
|
|
stateChanges['selectedInst'] = this.state.instructionsIndexByBytesOffset[currentAddress][props.vmTrace[vmTraceIndex].pc] |
|
|
|
stateChanges["currentSelected"] = vmTraceIndex |
|
|
|
stateChanges['currentSelected'] = vmTraceIndex |
|
|
|
|
|
|
|
|
|
|
|
stateChanges["currentStepInfo"] = [ |
|
|
|
stateChanges['currentStepInfo'] = [ |
|
|
|
"Current Step: " + props.vmTrace[vmTraceIndex].steps, |
|
|
|
'Current Step: ' + props.vmTrace[vmTraceIndex].steps, |
|
|
|
"Adding Memory: " + (props.vmTrace[vmTraceIndex].memexpand ? props.vmTrace[vmTraceIndex].memexpand : ""), |
|
|
|
'Adding Memory: ' + (props.vmTrace[vmTraceIndex].memexpand ? props.vmTrace[vmTraceIndex].memexpand : ''), |
|
|
|
"Step Cost: " + props.vmTrace[vmTraceIndex].gascost, |
|
|
|
'Step Cost: ' + props.vmTrace[vmTraceIndex].gascost, |
|
|
|
"Remaining Gas: " + props.vmTrace[vmTraceIndex].gas |
|
|
|
'Remaining Gas: ' + props.vmTrace[vmTraceIndex].gas |
|
|
|
] |
|
|
|
] |
|
|
|
this.refs.slider.setValue(vmTraceIndex) |
|
|
|
this.refs.slider.setValue(vmTraceIndex) |
|
|
|
this.setState(stateChanges) |
|
|
|
this.setState(stateChanges) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
shouldUpdateStateProperty: function(vmTraceName, nextIndex, previousIndex, vmTrace) |
|
|
|
shouldUpdateStateProperty: function (vmTraceName, nextIndex, previousIndex, vmTrace) { |
|
|
|
{ |
|
|
|
|
|
|
|
var propIndex = -1 |
|
|
|
var propIndex = -1 |
|
|
|
if (previousIndex + 1 === nextIndex) |
|
|
|
if (previousIndex + 1 === nextIndex) { |
|
|
|
propIndex = nextIndex |
|
|
|
propIndex = nextIndex |
|
|
|
else |
|
|
|
} else { |
|
|
|
propIndex = this.retrieveLastSeenProperty(nextIndex, vmTraceName, vmTrace) |
|
|
|
propIndex = this.retrieveLastSeenProperty(nextIndex, vmTraceName, vmTrace) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (propIndex > -1 && vmTrace[propIndex][vmTraceName] !== undefined) |
|
|
|
if (propIndex > -1 && vmTrace[propIndex][vmTraceName] !== undefined) { |
|
|
|
return propIndex |
|
|
|
return propIndex |
|
|
|
else |
|
|
|
} else { |
|
|
|
return -1 |
|
|
|
return -1 |
|
|
|
|
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
retrieveLastSeenProperty: function(currentIndex, propertyName, vmTrace) |
|
|
|
retrieveLastSeenProperty: function (currentIndex, propertyName, vmTrace) { |
|
|
|
{ |
|
|
|
|
|
|
|
var index = currentIndex |
|
|
|
var index = currentIndex |
|
|
|
while (index > 0) |
|
|
|
while (index > 0) { |
|
|
|
{ |
|
|
|
if (vmTrace[index][propertyName]) { |
|
|
|
if (vmTrace[index][propertyName]) |
|
|
|
|
|
|
|
break |
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
index-- |
|
|
|
index-- |
|
|
|
} |
|
|
|
} |
|
|
|
return index |
|
|
|
return index |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
stepIntoBack: function() |
|
|
|
stepIntoBack: function () { |
|
|
|
{ |
|
|
|
|
|
|
|
this.moveSelection(-1) |
|
|
|
this.moveSelection(-1) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
stepIntoForward: function() |
|
|
|
stepIntoForward: function () { |
|
|
|
{ |
|
|
|
|
|
|
|
this.moveSelection(1) |
|
|
|
this.moveSelection(1) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
stepOverBack: function() |
|
|
|
stepOverBack: function () { |
|
|
|
{ |
|
|
|
if (this.isReturnInstruction(this.state.currentSelected - 1)) { |
|
|
|
if (this.isReturnInstruction(this.state.currentSelected - 1)) |
|
|
|
this.stepOutBack() |
|
|
|
this.stepOutBack(); |
|
|
|
} else { |
|
|
|
else |
|
|
|
this.moveSelection(-1) |
|
|
|
this.moveSelection(-1); |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
stepOverForward: function() |
|
|
|
stepOverForward: function () { |
|
|
|
{ |
|
|
|
if (this.isCallInstruction(this.state.currentSelected)) { |
|
|
|
if (this.isCallInstruction(this.state.currentSelected)) |
|
|
|
this.stepOutForward() |
|
|
|
this.stepOutForward(); |
|
|
|
} else { |
|
|
|
else |
|
|
|
this.moveSelection(1) |
|
|
|
this.moveSelection(1); |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
isCallInstruction: function(index) |
|
|
|
isCallInstruction: function (index) { |
|
|
|
{ |
|
|
|
var state = this.props.vmTrace[index] |
|
|
|
var state = this.props.vmTrace[index]; |
|
|
|
return state.instname === 'CALL' || state.instname === 'CALLCODE' || state.instname === 'CREATE' || state.instname === 'DELEGATECALL' |
|
|
|
return state.instname === "CALL" || state.instname === "CALLCODE" || state.instname === "CREATE" || state.instname === "DELEGATECALL" |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
isReturnInstruction: function(index) |
|
|
|
isReturnInstruction: function (index) { |
|
|
|
{ |
|
|
|
var state = this.props.vmTrace[index] |
|
|
|
var state = this.props.vmTrace[index]; |
|
|
|
return state.instname === 'RETURN' |
|
|
|
return state.instname === "RETURN" |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
stepOutBack: function() |
|
|
|
stepOutBack: function () { |
|
|
|
{ |
|
|
|
var i = this.state.currentSelected - 1 |
|
|
|
var i = this.state.currentSelected - 1; |
|
|
|
var depth = 0 |
|
|
|
var depth = 0; |
|
|
|
while (--i >= 0) { |
|
|
|
while (--i >= 0)
|
|
|
|
if (this.isCallInstruction(i)) { |
|
|
|
{ |
|
|
|
if (depth === 0) { |
|
|
|
if (this.isCallInstruction(i)) |
|
|
|
break |
|
|
|
{ |
|
|
|
} else { |
|
|
|
if (depth == 0) |
|
|
|
depth-- |
|
|
|
break; |
|
|
|
} |
|
|
|
else |
|
|
|
} else if (this.isReturnInstruction(i)) { |
|
|
|
depth--; |
|
|
|
depth++ |
|
|
|
} |
|
|
|
} |
|
|
|
else if (this.isReturnInstruction(i)) |
|
|
|
|
|
|
|
depth++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
this.selectState(i); |
|
|
|
this.selectState(i) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
stepOutForward: function() |
|
|
|
stepOutForward: function () { |
|
|
|
{ |
|
|
|
|
|
|
|
var i = this.state.currentSelected |
|
|
|
var i = this.state.currentSelected |
|
|
|
var depth = 0 |
|
|
|
var depth = 0 |
|
|
|
while (++i < this.props.vmTrace.length)
|
|
|
|
while (++i < this.props.vmTrace.length) { |
|
|
|
{ |
|
|
|
if (this.isReturnInstruction(i)) { |
|
|
|
if (this.isReturnInstruction(i)) |
|
|
|
if (depth === 0) { |
|
|
|
{ |
|
|
|
|
|
|
|
if (depth == 0) |
|
|
|
|
|
|
|
break |
|
|
|
break |
|
|
|
else |
|
|
|
} else { |
|
|
|
depth-- |
|
|
|
depth-- |
|
|
|
} |
|
|
|
} |
|
|
|
else if (this.isCallInstruction(i)) |
|
|
|
} else if (this.isCallInstruction(i)) { |
|
|
|
depth++ |
|
|
|
depth++ |
|
|
|
} |
|
|
|
} |
|
|
|
this.selectState(i + 1); |
|
|
|
} |
|
|
|
|
|
|
|
this.selectState(i + 1) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
moveSelection: function(incr) |
|
|
|
moveSelection: function (incr) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.selectState(this.state.currentSelected + incr) |
|
|
|
this.selectState(this.state.currentSelected + incr) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
selectState: function(index) |
|
|
|
selectState: function (index) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.updateState(this.props, index) |
|
|
|
this.updateState(this.props, index) |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
formatMemory: function(mem, width) |
|
|
|
formatMemory: function (mem, width) { |
|
|
|
{ |
|
|
|
|
|
|
|
var ret = [] |
|
|
|
var ret = [] |
|
|
|
for (var k = 0; k < mem.length; k += (width * 2)) |
|
|
|
for (var k = 0; k < mem.length; k += (width * 2)) { |
|
|
|
{ |
|
|
|
|
|
|
|
var memory = mem.substr(k, width * 2) |
|
|
|
var memory = mem.substr(k, width * 2) |
|
|
|
ret.push({ |
|
|
|
ret.push({ |
|
|
|
address: web3.toHex(k), |
|
|
|
address: web3.toHex(k), |
|
|
@ -338,18 +348,17 @@ module.exports = React.createClass({ |
|
|
|
return ret |
|
|
|
return ret |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
tryAsciiFormat: function(memorySlot) |
|
|
|
tryAsciiFormat: function (memorySlot) { |
|
|
|
{ |
|
|
|
var ret = { ascii: '', raw: '' } |
|
|
|
var ret = { ascii: "", raw: "" } |
|
|
|
for (var k = 0; k < memorySlot.length; k += 2) { |
|
|
|
for (var k = 0; k < memorySlot.length; k += 2) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var raw = memorySlot.substr(k, 2) |
|
|
|
var raw = memorySlot.substr(k, 2) |
|
|
|
var ascii = web3.toAscii(raw) |
|
|
|
var ascii = web3.toAscii(raw) |
|
|
|
if (ascii === String.fromCharCode(0)) |
|
|
|
if (ascii === String.fromCharCode(0)) { |
|
|
|
ret.ascii += "?" |
|
|
|
ret.ascii += '?' |
|
|
|
else |
|
|
|
} else { |
|
|
|
ret.ascii += ascii |
|
|
|
ret.ascii += ascii |
|
|
|
ret.raw += " " + raw |
|
|
|
} |
|
|
|
|
|
|
|
ret.raw += ' ' + raw |
|
|
|
} |
|
|
|
} |
|
|
|
return ret |
|
|
|
return ret |
|
|
|
} |
|
|
|
} |
|
|
|